From f8a570a2cbe42f397e989ea4789d5df375470a37 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Thu, 7 Oct 2021 16:31:41 -0400 Subject: [PATCH] Remove poller props in favor of Spring Boot Starting with Spring Boot `2.6`, the auto-configuration for Spring Integration introduces `poller` properties. The `DefaultPollerProperties` and its respective `ChannelBindingAutoConfiguration` are not needed any more. * Add `PollerConfigEnvironmentPostProcessor` to remap deprecated `spring.cloud.stream.poller` into respective `spring.integration.poller` properties * Mention in the docs a deprecation move and its replacement Related to: https://github.com/spring-projects/spring-boot/pull/27992 Resolves #2233 --- .../main/asciidoc/spring-cloud-stream.adoc | 6 +- .../ChannelBindingAutoConfiguration.java | 54 --------- .../config/DefaultPollerProperties.java | 113 ------------------ .../PollerConfigEnvironmentPostProcessor.java | 70 +++++++++++ .../main/resources/META-INF/spring.factories | 5 +- 5 files changed, 76 insertions(+), 172 deletions(-) delete mode 100644 spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/ChannelBindingAutoConfiguration.java delete mode 100644 spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/DefaultPollerProperties.java create mode 100644 spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/PollerConfigEnvironmentPostProcessor.java diff --git a/docs/src/main/asciidoc/spring-cloud-stream.adoc b/docs/src/main/asciidoc/spring-cloud-stream.adoc index c1099a00b..2ceffea65 100644 --- a/docs/src/main/asciidoc/spring-cloud-stream.adoc +++ b/docs/src/main/asciidoc/spring-cloud-stream.adoc @@ -528,8 +528,7 @@ But if you do need to write an explicit `Consumer>`, remember to subscri ====== Polling Configuration Properties -The following properties are exposed by `org.springframework.cloud.stream.config.DefaultPollerProperties` and are prefixed with -`spring.cloud.stream.poller`: +The following properties are exposed (although deprecated since version 3.2) by Spring Cloud Stream and are prefixed with the `spring.cloud.stream.poller`: fixedDelay:: Fixed delay for default poller in milliseconds. @@ -558,6 +557,9 @@ Default: MILLISECONDS. For example `--spring.cloud.stream.poller.fixed-delay=2000` sets the poller interval to poll every two seconds. +IMPORTANT: These poller properties are deprecated starting version 3.2 in favor of similar configuration properties from Spring Boot auto-configuration for Spring Integration. +See `org.springframework.boot.autoconfigure.integration.IntegrationProperties.Poller` for more information. + ===== Sending arbitrary data to an output (e.g. Foreign event-driven sources) There are cases where the actual source of data may be coming from the external (foreign) system that is not a binder. For example, the diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/ChannelBindingAutoConfiguration.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/ChannelBindingAutoConfiguration.java deleted file mode 100644 index bbaca4c70..000000000 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/ChannelBindingAutoConfiguration.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2015-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.config; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.stream.binding.BindingService; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.integration.scheduling.PollerMetadata; -import org.springframework.messaging.MessageChannel; - -/** - * Configuration class with some useful beans for {@link MessageChannel} binding and - * general Spring Integration infrastructure. - * - * @author Dave Syer - * @author Marius Bogoevici - * @author Ilayaperumal Gopinathan - */ -@Configuration(proxyBeanMethods = false) -@ConditionalOnBean(BindingService.class) -@EnableConfigurationProperties(DefaultPollerProperties.class) -@AutoConfigureBefore(IntegrationAutoConfiguration.class) -public class ChannelBindingAutoConfiguration { - - @Autowired - private DefaultPollerProperties poller; - - @Bean(name = PollerMetadata.DEFAULT_POLLER) - @ConditionalOnMissingBean(PollerMetadata.class) - public PollerMetadata defaultPoller() { - return this.poller.getPollerMetadata(); - } - -} diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/DefaultPollerProperties.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/DefaultPollerProperties.java deleted file mode 100644 index f9a4f297a..000000000 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/DefaultPollerProperties.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2015-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.config; - -import java.util.concurrent.TimeUnit; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.integration.scheduling.PollerMetadata; -import org.springframework.scheduling.support.CronTrigger; -import org.springframework.scheduling.support.PeriodicTrigger; - -/** - * @author Dave Syer - * @author Oleg Zhurakousky - * @author Soby Chacko - */ -@ConfigurationProperties("spring.cloud.stream.poller") -public class DefaultPollerProperties { - - /** - * Fixed delay for default poller. - */ - private long fixedDelay = 1000L; - - /** - * Maximum messages per poll for the default poller. - */ - private long maxMessagesPerPoll = 1L; - - /** - * Cron expression value for the Cron Trigger. - */ - private String cron; - - /** - * Initial delay for periodic triggers. - */ - private int initialDelay = 0; - - /** - * The TimeUnit to apply to delay values. - */ - private TimeUnit timeUnit = TimeUnit.MILLISECONDS; - - public PollerMetadata getPollerMetadata() { - PollerMetadata pollerMetadata = new PollerMetadata(); - if (cron != null) { - pollerMetadata.setTrigger(new CronTrigger(cron)); - } - else { - final PeriodicTrigger periodicTrigger = new PeriodicTrigger(this.fixedDelay, this.timeUnit); - periodicTrigger.setInitialDelay(initialDelay); - pollerMetadata.setTrigger(periodicTrigger); - } - - pollerMetadata.setMaxMessagesPerPoll(this.maxMessagesPerPoll); - return pollerMetadata; - } - - public long getFixedDelay() { - return this.fixedDelay; - } - - public void setFixedDelay(long fixedDelay) { - this.fixedDelay = fixedDelay; - } - - public long getMaxMessagesPerPoll() { - return this.maxMessagesPerPoll; - } - - public void setMaxMessagesPerPoll(long maxMessagesPerPoll) { - this.maxMessagesPerPoll = maxMessagesPerPoll; - } - - public String getCron() { - return cron; - } - - public void setCron(String cron) { - this.cron = cron; - } - - public int getInitialDelay() { - return initialDelay; - } - - public void setInitialDelay(int initialDelay) { - this.initialDelay = initialDelay; - } - - public TimeUnit getTimeUnit() { - return timeUnit; - } - - public void setTimeUnit(TimeUnit timeUnit) { - this.timeUnit = timeUnit; - } -} diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/PollerConfigEnvironmentPostProcessor.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/PollerConfigEnvironmentPostProcessor.java new file mode 100644 index 000000000..8ced27582 --- /dev/null +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/PollerConfigEnvironmentPostProcessor.java @@ -0,0 +1,70 @@ +/* + * Copyright 2021-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.stream.config; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.context.properties.PropertyMapper; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.MapPropertySource; + +/** + * + * @author Artem Bilan + * + * @since 3.2 + */ +public class PollerConfigEnvironmentPostProcessor implements EnvironmentPostProcessor { + + private static final Log logger = LogFactory.getLog(PollerConfigEnvironmentPostProcessor.class); + + private static final String STREAM_PROPERTY_PREFIX = "spring.cloud.stream.poller."; + + private static final String INTEGRATION_PROPERTY_PREFIX = "spring.integration.poller."; + + @Override + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { + Map streamPollerProperties = new HashMap<>(); + + String[] pollerPropertySuffixes = { "fixed-delay", "max-messages-per-poll", "cron", "initial-delay" }; + + PropertyMapper map = PropertyMapper.get().alwaysApplying(PropertyMapper.Source::whenHasText); + + for (String pollerPropertySuffix : pollerPropertySuffixes) { + map.from(environment.getProperty(STREAM_PROPERTY_PREFIX + pollerPropertySuffix)) + .to((value) -> streamPollerProperties.put(INTEGRATION_PROPERTY_PREFIX + pollerPropertySuffix, value)); + } + + if (!streamPollerProperties.isEmpty()) { + logger.info("'spring.cloud.stream.poller' properties are deprecated in favor of 'spring.integration.poller' properties."); + } + + //TODO Must remain after removal of deprecated code above in the future + streamPollerProperties.putIfAbsent(INTEGRATION_PROPERTY_PREFIX + "fixed-delay", "1s"); + streamPollerProperties.putIfAbsent(INTEGRATION_PROPERTY_PREFIX + "max-messages-per-poll", "1"); + + environment.getPropertySources() + .addLast(new MapPropertySource("spring.integration.poller", streamPollerProperties)); + } + +} diff --git a/spring-cloud-stream/src/main/resources/META-INF/spring.factories b/spring-cloud-stream/src/main/resources/META-INF/spring.factories index 03891cfa7..d073a44f2 100644 --- a/spring-cloud-stream/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-stream/src/main/resources/META-INF/spring.factories @@ -1,5 +1,4 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration:\ -org.springframework.cloud.stream.config.ChannelBindingAutoConfiguration,\ org.springframework.cloud.stream.config.BindersHealthIndicatorAutoConfiguration,\ org.springframework.cloud.stream.config.ChannelsEndpointAutoConfiguration,\ org.springframework.cloud.stream.config.BindingsEndpointAutoConfiguration,\ @@ -7,7 +6,7 @@ org.springframework.cloud.stream.config.BindingServiceConfiguration,\ org.springframework.cloud.stream.function.FunctionConfiguration org.springframework.boot.env.EnvironmentPostProcessor:\ -org.springframework.cloud.stream.function.RoutingFunctionEnvironmentPostProcessor - +org.springframework.cloud.stream.function.RoutingFunctionEnvironmentPostProcessor,\ +org.springframework.cloud.stream.config.PollerConfigEnvironmentPostProcessor