Move EventPublisher to hawkbit-repository-core making hawkbit-reposit… (#2576)

* Move EventPublisher to hawkbit-repository-core making hawkbit-repository-api non dependent to rabbit binders

* Move EventPublisherHolder to org.eclipse.hawkbit.repository.event

* Fix overriding default values of RemoteEvents and rabbit binder

---------

Co-authored-by: vasilchev <vasil.ilchev@bosch.com>
This commit is contained in:
Vasil Ilchev
2025-08-01 08:48:07 +03:00
committed by GitHub
parent 107ebca740
commit cca105c80e
8 changed files with 42 additions and 31 deletions

View File

@@ -50,7 +50,6 @@ hawkbit.lock=inMemory
# Disable discovery client of spring-cloud-commons
spring.cloud.discovery.enabled=false
# remote events configuration
spring.config.import=classpath:/hawkbit-events-defaults.properties
# Optional: Use protostuff (if enabled)
# spring.cloud.stream.default.content-type=application/binary+protostuff

View File

@@ -36,6 +36,5 @@ hawkbit.lock=inMemory
spring.cloud.discovery.enabled=false
# remote events configuration
spring.config.import=classpath:/hawkbit-events-defaults.properties
# Optional: Use protostuff (if enabled)
# spring.cloud.stream.default.content-type=application/binary+protostuff

View File

@@ -54,6 +54,5 @@ springdoc.swagger-ui.csrf.enabled=true
springdoc.swagger-ui.doc-expansion=none
# remote events configuration
spring.config.import=classpath:/hawkbit-events-defaults.properties
# Optional: Use protostuff (if enabled)
# spring.cloud.stream.default.content-type=application/binary+protostuff

View File

@@ -33,11 +33,6 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>

View File

@@ -50,5 +50,9 @@
<artifactId>protostuff-runtime</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -9,35 +9,58 @@
*/
package org.eclipse.hawkbit.event;
import java.io.IOException;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.repository.event.ApplicationEventFilter;
import org.eclipse.hawkbit.repository.event.EventPublisherHolder;
import org.eclipse.hawkbit.repository.event.remote.AbstractRemoteEvent;
import org.eclipse.hawkbit.repository.event.remote.RemoteTenantAwareEvent;
import org.eclipse.hawkbit.repository.event.EventPublisherHolder;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.stream.config.BindingProperties;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.ResolvableType;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.support.ResourcePropertySource;
import org.springframework.messaging.converter.MessageConverter;
/**
* Autoconfiguration for the events.
*/
@Slf4j
@Configuration
@PropertySource("classpath:/hawkbit-events-defaults.properties")
public class EventPublisherConfiguration {
private final ConfigurableEnvironment environment;
public EventPublisherConfiguration(ConfigurableEnvironment environment) {
this.environment = environment;
}
@PostConstruct
public void registerProperties() {
try {
ResourcePropertySource props = new ResourcePropertySource("classpath:/hawkbit-events-defaults.properties");
// load manually to ensure that they are with the lowest precedence allowing to override them
environment.getPropertySources().addLast(props);
} catch (IOException ex) {
log.error("Failed to load default properties for event publisher", ex);
}
}
/**
* Server internal event publisher that allows parallel event processing if the event listener is marked as so.
*
@@ -116,29 +139,22 @@ public class EventPublisherConfiguration {
return publisher::publishEvent;
}
@Bean
@ConditionalOnProperty(name = "org.eclipse.hawkbit.events.remote-enabled", havingValue = "true")
@ConditionalOnProperty(name = "spring.cloud.stream.default.content-type", havingValue = "application/binary+stuff")
protected static class EventProtoStuffAutoConfiguration {
public MessageConverter eventMessageConverter(BindingProperties bindingProperties) {
/**
* @return the protostuff io message converter for events
*/
@Bean
public MessageConverter eventProtoStuffConverter() {
return new EventProtoStuffMessageConverter();
final String contentType = bindingProperties.getContentType();
if (contentType == null) {
throw new IllegalStateException("RemoteEvents are enabled and Content type must be specified in spring.cloud.stream.default.content-type.");
}
}
@ConditionalOnProperty(name = "org.eclipse.hawkbit.events.remote-enabled", havingValue = "true")
@ConditionalOnProperty(name = "spring.cloud.stream.default.content-type", havingValue = "application/remote-event-json")
protected static class EventJacksonAutoConfiguration {
/**
* @return the Jackson message converter for events
*/
@Bean
public MessageConverter eventJacksonMessageConverter() {
if (contentType.equals("application/binary+protostuff")) {
return new EventProtoStuffMessageConverter();
} else if (contentType.equals("application/remote-event-json")) {
return new EventJacksonMessageConverter();
} else {
throw new IllegalStateException("Unsupported content type: " + contentType + ". Supported types: application/x-protostuff, application/remote-event-json");
}
}
}

View File

@@ -16,8 +16,8 @@ import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.repository.event.remote.AbstractRemoteEvent;
import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent;
import org.eclipse.hawkbit.repository.event.remote.MultiActionCancelEvent;
import org.eclipse.hawkbit.repository.event.remote.MultiActionAssignEvent;
import org.eclipse.hawkbit.repository.event.remote.MultiActionCancelEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent;

View File

@@ -10,7 +10,6 @@
package org.eclipse.hawkbit.repository.jpa.model;
import java.io.Serial;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;