diff --git a/hawkbit-ddi/hawkbit-ddi-server/src/main/resources/application.properties b/hawkbit-ddi/hawkbit-ddi-server/src/main/resources/application.properties index 56c304456..dc6cd3340 100644 --- a/hawkbit-ddi/hawkbit-ddi-server/src/main/resources/application.properties +++ b/hawkbit-ddi/hawkbit-ddi-server/src/main/resources/application.properties @@ -50,8 +50,18 @@ hawkbit.lock=inMemory # Disable discovery client of spring-cloud-commons spring.cloud.discovery.enabled=false # remote events configuration +# remote events configuration +spring.cloud.function.definition=fanoutEventConsumer;serviceEventConsumer +spring.cloud.stream.default.content-type=application/remote-event-json # Optional: Use protostuff (if enabled) # spring.cloud.stream.default.content-type=application/binary+protostuff +# -- Consumer bindings -- +spring.cloud.stream.bindings.fanoutEventConsumer-in-0.destination=fanoutEventChannel +spring.cloud.stream.bindings.serviceEventConsumer-in-0.destination=serviceEventChannel +# -- Producer bindings (for StreamBridge) -- +spring.cloud.stream.bindings.fanoutEventChannel.destination=fanoutEventChannel +spring.cloud.stream.bindings.serviceEventChannel.destination=serviceEventChannel +spring.cloud.stream.bindings.serviceEventConsumer-in-0.group=${spring.application.name} # Swagger Configuration / https://springdoc.org/v2/#properties springdoc.api-docs.version=openapi_3_0 diff --git a/hawkbit-dmf/hawkbit-dmf-server/src/main/resources/application.properties b/hawkbit-dmf/hawkbit-dmf-server/src/main/resources/application.properties index c93094e42..050ec5bf3 100644 --- a/hawkbit-dmf/hawkbit-dmf-server/src/main/resources/application.properties +++ b/hawkbit-dmf/hawkbit-dmf-server/src/main/resources/application.properties @@ -36,5 +36,14 @@ hawkbit.lock=inMemory spring.cloud.discovery.enabled=false # remote events configuration +spring.cloud.function.definition=fanoutEventConsumer;serviceEventConsumer +spring.cloud.stream.default.content-type=application/remote-event-json # Optional: Use protostuff (if enabled) # spring.cloud.stream.default.content-type=application/binary+protostuff +# -- Consumer bindings -- +spring.cloud.stream.bindings.fanoutEventConsumer-in-0.destination=fanoutEventChannel +spring.cloud.stream.bindings.serviceEventConsumer-in-0.destination=serviceEventChannel +# -- Producer bindings (for StreamBridge) -- +spring.cloud.stream.bindings.fanoutEventChannel.destination=fanoutEventChannel +spring.cloud.stream.bindings.serviceEventChannel.destination=serviceEventChannel +spring.cloud.stream.bindings.serviceEventConsumer-in-0.group=${spring.application.name} diff --git a/hawkbit-mgmt/hawkbit-mgmt-server/src/main/resources/application.properties b/hawkbit-mgmt/hawkbit-mgmt-server/src/main/resources/application.properties index 1109ac309..f6afa16a5 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-server/src/main/resources/application.properties +++ b/hawkbit-mgmt/hawkbit-mgmt-server/src/main/resources/application.properties @@ -54,5 +54,14 @@ springdoc.swagger-ui.csrf.enabled=true springdoc.swagger-ui.doc-expansion=none # remote events configuration +spring.cloud.function.definition=fanoutEventConsumer;serviceEventConsumer +spring.cloud.stream.default.content-type=application/remote-event-json # Optional: Use protostuff (if enabled) -# spring.cloud.stream.default.content-type=application/binary+protostuff \ No newline at end of file +# spring.cloud.stream.default.content-type=application/binary+protostuff +# -- Consumer bindings -- +spring.cloud.stream.bindings.fanoutEventConsumer-in-0.destination=fanoutEventChannel +spring.cloud.stream.bindings.serviceEventConsumer-in-0.destination=serviceEventChannel +# -- Producer bindings (for StreamBridge) -- +spring.cloud.stream.bindings.fanoutEventChannel.destination=fanoutEventChannel +spring.cloud.stream.bindings.serviceEventChannel.destination=serviceEventChannel +spring.cloud.stream.bindings.serviceEventConsumer-in-0.group=${spring.application.name} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/event/EventPublisherConfiguration.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/event/EventPublisherConfiguration.java index a09cbca88..8dbc6552c 100644 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/event/EventPublisherConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/event/EventPublisherConfiguration.java @@ -9,12 +9,10 @@ */ package org.eclipse.hawkbit.event; -import java.io.IOException; import java.util.concurrent.Executor; import java.util.function.Consumer; - -import jakarta.annotation.PostConstruct; - +import io.protostuff.ProtostuffIOUtil; +import io.protostuff.Schema; import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.repository.event.ApplicationEventFilter; import org.eclipse.hawkbit.repository.event.EventPublisherHolder; @@ -22,9 +20,8 @@ import org.eclipse.hawkbit.repository.event.remote.AbstractRemoteEvent; import org.eclipse.hawkbit.repository.event.remote.RemoteTenantAwareEvent; import org.eclipse.hawkbit.security.SystemSecurityContext; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 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; @@ -33,8 +30,6 @@ 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; /** @@ -44,23 +39,6 @@ import org.springframework.messaging.converter.MessageConverter; @Configuration 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. * @@ -128,33 +106,29 @@ public class EventPublisherConfiguration { } @Bean - @ConditionalOnProperty(name = "org.eclipse.hawkbit.events.remote-enabled", havingValue = "true") public Consumer serviceEventConsumer(ApplicationEventPublisher publisher) { return publisher::publishEvent; } @Bean - @ConditionalOnProperty(name = "org.eclipse.hawkbit.events.remote-enabled", havingValue = "true") public Consumer fanoutEventConsumer(ApplicationEventPublisher publisher) { return publisher::publishEvent; } - @Bean - @ConditionalOnProperty(name = "org.eclipse.hawkbit.events.remote-enabled", havingValue = "true") - public MessageConverter eventMessageConverter(BindingProperties bindingProperties) { + @ConditionalOnClass({ Schema.class, ProtostuffIOUtil.class }) + protected static class EventProtostuffConfiguration { - 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."); - } - - if (contentType.equals("application/binary+protostuff")) { + /** + * @return the protostuff io message converter + */ + @Bean + public MessageConverter eventProtostuffMessageConverter() { 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"); } } + + @Bean + public MessageConverter eventJacksonMessageConverter() { + return new EventJacksonMessageConverter(); + } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/resources/hawkbit-events-defaults.properties b/hawkbit-repository/hawkbit-repository-core/src/main/resources/hawkbit-events-defaults.properties deleted file mode 100644 index 481b5cfc2..000000000 --- a/hawkbit-repository/hawkbit-repository-core/src/main/resources/hawkbit-events-defaults.properties +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright (c) 2015 Bosch Software Innovations GmbH and others -# -# This program and the accompanying materials are made -# available under the terms of the Eclipse Public License 2.0 -# which is available at https://www.eclipse.org/legal/epl-2.0/ -# -# SPDX-License-Identifier: EPL-2.0 -# - -org.eclipse.hawkbit.events.remote-enabled=true - -spring.cloud.function.definition=fanoutEventConsumer;serviceEventConsumer - -spring.cloud.stream.default.content-type=application/remote-event-json -# -- Consumer bindings -- -spring.cloud.stream.bindings.fanoutEventConsumer-in-0.destination=fanoutEventChannel -spring.cloud.stream.bindings.serviceEventConsumer-in-0.destination=serviceEventChannel - -# -- Producer bindings (for StreamBridge) -- -spring.cloud.stream.bindings.fanoutEventChannel.destination=fanoutEventChannel -spring.cloud.stream.bindings.serviceEventChannel.destination=serviceEventChannel - -spring.cloud.stream.bindings.serviceEventConsumer-in-0.group=${spring.application.name} - -# Performance -spring.cloud.stream.rabbit.binder.compressionLevel=0 -spring.cloud.stream.rabbit.bindings.fanoutEventConsumer-in-0.consumer.anonymousGroupPrefix=${spring.application.name}- -spring.cloud.stream.rabbit.bindings.fanoutEventConsumer-in-0.consumer.durableSubscription=false -spring.cloud.stream.rabbit.bindings.fanoutEventConsumer-in-0.consumer.maxConcurrency=1 -spring.cloud.stream.rabbit.bindings.fanoutEventConsumer-in-0.consumer.requeueRejected=false -spring.cloud.stream.rabbit.bindings.fanoutEventConsumer-in-0.consumer.prefetch=100 -spring.cloud.stream.rabbit.bindings.serviceEventConsumer-in-0.consumer.maxConcurrency=1 -spring.cloud.stream.rabbit.bindings.serviceEventConsumer-in-0.consumer.requeueRejected=false -spring.cloud.stream.rabbit.bindings.serviceEventConsumer-in-0.consumer.prefetch=100 - -spring.cloud.stream.rabbit.bindings.fanoutEventChannel.producer.declareExchange=false -spring.cloud.stream.rabbit.bindings.fanoutEventChannel.producer.batchingEnabled=true -spring.cloud.stream.rabbit.bindings.fanoutEventChannel.producer.batchSize=1000 -spring.cloud.stream.rabbit.bindings.fanoutEventChannel.producer.batch-buffer-limit=100000 -spring.cloud.stream.rabbit.bindings.fanoutEventChannel.producer.deliveryMode=NON_PERSISTENT - -spring.cloud.stream.rabbit.bindings.serviceEventChannel.producer.declareExchange=false -spring.cloud.stream.rabbit.bindings.serviceEventChannel.producer.batchingEnabled=true -spring.cloud.stream.rabbit.bindings.serviceEventChannel.producer.batchSize=1000 -spring.cloud.stream.rabbit.bindings.serviceEventChannel.producer.batch-buffer-limit=100000 -spring.cloud.stream.rabbit.bindings.serviceEventChannel.producer.deliveryMode=NON_PERSISTENT \ No newline at end of file