Skip to content

Commit 95fae5a

Browse files
committed
Introduce PollerMetadataCustomizer for Spring Integration
Fix spring-projectsGH-44534 Signed-off-by: Yanming Zhou <zhouyanming@gmail.com>
1 parent 207c8f5 commit 95fae5a

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import io.rsocket.transport.netty.server.TcpServerTransport;
2525

2626
import org.springframework.beans.factory.BeanFactory;
27+
import org.springframework.beans.factory.ObjectProvider;
2728
import org.springframework.boot.autoconfigure.AutoConfiguration;
2829
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
2930
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
@@ -85,6 +86,7 @@
8586
* @author Vedran Pavic
8687
* @author Madhura Bhave
8788
* @author Yong-Hyun Kim
89+
* @author Yanming Zhou
8890
* @since 1.1.0
8991
*/
9092
@AutoConfiguration(after = { DataSourceAutoConfiguration.class, JmxAutoConfiguration.class,
@@ -130,7 +132,8 @@ protected static class IntegrationConfiguration {
130132

131133
@Bean(PollerMetadata.DEFAULT_POLLER)
132134
@ConditionalOnMissingBean(name = PollerMetadata.DEFAULT_POLLER)
133-
public PollerMetadata defaultPollerMetadata(IntegrationProperties integrationProperties) {
135+
public PollerMetadata defaultPollerMetadata(IntegrationProperties integrationProperties,
136+
ObjectProvider<PollerMetadataCustomizer> customizers) {
134137
IntegrationProperties.Poller poller = integrationProperties.getPoller();
135138
MutuallyExclusiveConfigurationPropertiesException.throwIfMultipleNonNullValuesIn((entries) -> {
136139
entries.put("spring.integration.poller.cron",
@@ -143,6 +146,7 @@ public PollerMetadata defaultPollerMetadata(IntegrationProperties integrationPro
143146
map.from(poller::getMaxMessagesPerPoll).to(pollerMetadata::setMaxMessagesPerPoll);
144147
map.from(poller::getReceiveTimeout).as(Duration::toMillis).to(pollerMetadata::setReceiveTimeout);
145148
map.from(poller).as(this::asTrigger).to(pollerMetadata::setTrigger);
149+
customizers.orderedStream().forEach((customizer) -> customizer.customize(pollerMetadata));
146150
return pollerMetadata;
147151
}
148152

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2012-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.integration;
18+
19+
import org.springframework.integration.scheduling.PollerMetadata;
20+
21+
/**
22+
* Callback interface that can be implemented by beans wishing to customize the
23+
* {@link PollerMetadata} whilst retaining default auto-configuration.
24+
*
25+
* @author Yanming Zhou
26+
* @since 3.5.0
27+
*/
28+
@FunctionalInterface
29+
public interface PollerMetadataCustomizer {
30+
31+
/**
32+
* Customize the {@link PollerMetadata}.
33+
* @param pollerMetadata the {@code PollerMetadata} to customize
34+
*/
35+
void customize(PollerMetadata pollerMetadata);
36+
37+
}

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java

+16
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@
6262
import org.springframework.context.annotation.Configuration;
6363
import org.springframework.context.annotation.Primary;
6464
import org.springframework.core.task.SimpleAsyncTaskExecutor;
65+
import org.springframework.core.task.SyncTaskExecutor;
66+
import org.springframework.core.task.TaskExecutor;
6567
import org.springframework.integration.annotation.IntegrationComponentScan;
6668
import org.springframework.integration.annotation.MessagingGateway;
6769
import org.springframework.integration.annotation.ServiceActivator;
@@ -105,6 +107,7 @@
105107
* @author Stephane Nicoll
106108
* @author Vedran Pavic
107109
* @author Yong-Hyun Kim
110+
* @author Yanming Zhou
108111
*/
109112
class IntegrationAutoConfigurationTests {
110113

@@ -543,6 +546,19 @@ void integrationVirtualThreadsEnabled() {
543546
.usesVirtualThreads()));
544547
}
545548

549+
@Test
550+
void pollerMetadataCanBeCustomizedViaPollerMetadataCustomizer() {
551+
TaskExecutor taskExecutor = new SyncTaskExecutor();
552+
this.contextRunner.withUserConfiguration(PollingConsumerConfiguration.class)
553+
.withBean(PollerMetadataCustomizer.class,
554+
() -> (pollerMetadata) -> pollerMetadata.setTaskExecutor(taskExecutor))
555+
.run((context) -> {
556+
assertThat(context).hasSingleBean(PollerMetadata.class);
557+
PollerMetadata metadata = context.getBean(PollerMetadata.DEFAULT_POLLER, PollerMetadata.class);
558+
assertThat(metadata.getTaskExecutor()).isSameAs(taskExecutor);
559+
});
560+
}
561+
546562
@Configuration(proxyBeanMethods = false)
547563
static class CustomMBeanExporter {
548564

0 commit comments

Comments
 (0)