Skip to content

Commit 536b6b1

Browse files
artembilangaryrussell
authored andcommitted
INT-4565: Fix IntComponentScan for profiles (#2652)
* INT-4565: Fix IntComponentScan for profiles JIRA: https://jira.spring.io/browse/INT-4565 * Propagate an `Environment` to the internal `ClassPathScanningCandidateComponentProvider` in the `IntegrationComponentScanRegistrar` for proper profiles activation * Ensure the logic works in the `GatewayInterfaceTests` * Some polishing and performance improvement for the `GatewayInterfaceTests` * Add a note about `@Profile` in the `gateway.adoc` * Polishing for the `gateway.adoc` **Cherry-pick to 5.0.x & 4.3.x** * * Add not activated by profile gateway interface into the `GatewayInterfaceTests` * More `GatewayInterfaceTests` polishing * Fix typo in the `gateway.adoc` * Fix Checkstyle violation
1 parent 2cde493 commit 536b6b1

File tree

3 files changed

+97
-71
lines changed

3 files changed

+97
-71
lines changed

spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationComponentScanRegistrar.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,14 @@
6161
*
6262
* @author Artem Bilan
6363
* @author Gary Russell
64+
*
6465
* @since 4.0
6566
*/
6667
public class IntegrationComponentScanRegistrar implements ImportBeanDefinitionRegistrar,
6768
ResourceLoaderAware, EnvironmentAware {
6869

69-
private final Map<TypeFilter, ImportBeanDefinitionRegistrar> componentRegistrars = new HashMap<TypeFilter, ImportBeanDefinitionRegistrar>();
70+
private final Map<TypeFilter, ImportBeanDefinitionRegistrar> componentRegistrars =
71+
new HashMap<TypeFilter, ImportBeanDefinitionRegistrar>();
7072

7173
private ResourceLoader resourceLoader;
7274

@@ -98,14 +100,16 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B
98100
basePackages = Collections.singleton(ClassUtils.getPackageName(importingClassMetadata.getClassName()));
99101
}
100102

101-
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false) {
103+
ClassPathScanningCandidateComponentProvider scanner =
104+
new ClassPathScanningCandidateComponentProvider(false, this.environment) {
102105

103-
@Override
104-
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
105-
return beanDefinition.getMetadata().isIndependent()
106-
&& !beanDefinition.getMetadata().isAnnotation();
107-
}
108-
};
106+
@Override
107+
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
108+
return beanDefinition.getMetadata().isIndependent()
109+
&& !beanDefinition.getMetadata().isAnnotation();
110+
}
111+
112+
};
109113

110114
if ((boolean) componentScan.get("useDefaultFilters")) { // NOSONAR - never null
111115
for (TypeFilter typeFilter : this.componentRegistrars.keySet()) {

spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests.java

Lines changed: 76 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import static org.junit.Assert.assertFalse;
2424
import static org.junit.Assert.assertNotEquals;
2525
import static org.junit.Assert.assertNotNull;
26+
import static org.junit.Assert.assertNotSame;
2627
import static org.junit.Assert.assertNull;
2728
import static org.junit.Assert.assertSame;
2829
import static org.junit.Assert.assertThat;
@@ -59,6 +60,7 @@
5960
import org.springframework.context.annotation.ComponentScan;
6061
import org.springframework.context.annotation.Configuration;
6162
import org.springframework.context.annotation.FilterType;
63+
import org.springframework.context.annotation.Profile;
6264
import org.springframework.context.support.ClassPathXmlApplicationContext;
6365
import org.springframework.core.task.AsyncTaskExecutor;
6466
import org.springframework.core.task.SimpleAsyncTaskExecutor;
@@ -77,6 +79,7 @@
7779
import org.springframework.integration.context.IntegrationProperties;
7880
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
7981
import org.springframework.integration.handler.BridgeHandler;
82+
import org.springframework.integration.handler.DelayHandler;
8083
import org.springframework.integration.support.MessageBuilder;
8184
import org.springframework.integration.test.util.TestUtils;
8285
import org.springframework.lang.Nullable;
@@ -93,6 +96,7 @@
9396
import org.springframework.scheduling.annotation.AsyncResult;
9497
import org.springframework.stereotype.Component;
9598
import org.springframework.test.annotation.DirtiesContext;
99+
import org.springframework.test.context.ActiveProfiles;
96100
import org.springframework.test.context.ContextConfiguration;
97101
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
98102
import org.springframework.util.concurrent.ListenableFuture;
@@ -107,6 +111,7 @@
107111
@ContextConfiguration(classes = GatewayInterfaceTests.TestConfig.class)
108112
@RunWith(SpringJUnit4ClassRunner.class)
109113
@DirtiesContext
114+
@ActiveProfiles("gatewayTest")
110115
public class GatewayInterfaceTests {
111116

112117
private static final String IGNORE_HEADER = "ignoreHeader";
@@ -153,20 +158,23 @@ public class GatewayInterfaceTests {
153158
@Autowired
154159
private IgnoredHeaderGateway ignoredHeaderGateway;
155160

161+
@Autowired(required = false)
162+
private NotActivatedByProfileGateway notActivatedByProfileGateway;
163+
156164
@Test
157165
public void testWithServiceSuperclassAnnotatedMethod() throws Exception {
158-
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this
159-
.getClass());
166+
ConfigurableApplicationContext ac =
167+
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
160168
DirectChannel channel = ac.getBean("requestChannelFoo", DirectChannel.class);
161169
final Method fooMethod = Foo.class.getMethod("foo", String.class);
162170
final AtomicBoolean called = new AtomicBoolean();
163171
MessageHandler handler = message -> {
164-
assertThat((String) message.getHeaders().get("name"), equalTo("foo"));
165-
assertThat(
166-
(String) message.getHeaders().get("string"),
167-
equalTo("public abstract void org.springframework.integration.gateway.GatewayInterfaceTests$Foo.foo(java.lang.String)"));
168-
assertThat((Method) message.getHeaders().get("object"), equalTo(fooMethod));
169-
assertThat((String) message.getPayload(), equalTo("hello"));
172+
assertThat(message.getHeaders().get("name"), equalTo("foo"));
173+
assertThat(message.getHeaders().get("string"),
174+
equalTo("public abstract void org.springframework.integration.gateway." +
175+
"GatewayInterfaceTests$Foo.foo(java.lang.String)"));
176+
assertThat(message.getHeaders().get("object"), equalTo(fooMethod));
177+
assertThat(message.getPayload(), equalTo("hello"));
170178
assertThat(new MessageHeaderAccessor(message).getErrorChannel(), equalTo("errorChannel"));
171179
called.set(true);
172180
};
@@ -181,18 +189,18 @@ public void testWithServiceSuperclassAnnotatedMethod() throws Exception {
181189

182190
@Test
183191
public void testWithServiceSuperclassAnnotatedMethodOverridePE() throws Exception {
184-
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests2-context.xml", this
185-
.getClass());
192+
ConfigurableApplicationContext ac =
193+
new ClassPathXmlApplicationContext("GatewayInterfaceTests2-context.xml", getClass());
186194
DirectChannel channel = ac.getBean("requestChannelFoo", DirectChannel.class);
187195
final Method fooMethod = Foo.class.getMethod("foo", String.class);
188196
final AtomicBoolean called = new AtomicBoolean();
189197
MessageHandler handler = message -> {
190-
assertThat((String) message.getHeaders().get("name"), equalTo("foo"));
191-
assertThat(
192-
(String) message.getHeaders().get("string"),
193-
equalTo("public abstract void org.springframework.integration.gateway.GatewayInterfaceTests$Foo.foo(java.lang.String)"));
194-
assertThat((Method) message.getHeaders().get("object"), equalTo(fooMethod));
195-
assertThat((String) message.getPayload(), equalTo("foo"));
198+
assertThat(message.getHeaders().get("name"), equalTo("foo"));
199+
assertThat(message.getHeaders().get("string"),
200+
equalTo("public abstract void org.springframework.integration.gateway." +
201+
"GatewayInterfaceTests$Foo.foo(java.lang.String)"));
202+
assertThat(message.getHeaders().get("object"), equalTo(fooMethod));
203+
assertThat(message.getPayload(), equalTo("foo"));
196204
called.set(true);
197205
};
198206
channel.subscribe(handler);
@@ -204,8 +212,8 @@ public void testWithServiceSuperclassAnnotatedMethodOverridePE() throws Exceptio
204212

205213
@Test
206214
public void testWithServiceAnnotatedMethod() {
207-
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this
208-
.getClass());
215+
ConfigurableApplicationContext ac =
216+
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
209217
DirectChannel channel = ac.getBean("requestChannelBar", DirectChannel.class);
210218
MessageHandler handler = mock(MessageHandler.class);
211219
channel.subscribe(handler);
@@ -217,15 +225,16 @@ public void testWithServiceAnnotatedMethod() {
217225

218226
@Test
219227
public void testWithServiceSuperclassUnAnnotatedMethod() throws Exception {
220-
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this
221-
.getClass());
228+
ConfigurableApplicationContext ac =
229+
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
222230
DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class);
223231
final Method bazMethod = Foo.class.getMethod("baz", String.class);
224232
final AtomicBoolean called = new AtomicBoolean();
225233
MessageHandler handler = message -> {
226234
assertThat(message.getHeaders().get("name"), equalTo("overrideGlobal"));
227235
assertThat(message.getHeaders().get("string"),
228-
equalTo("public abstract void org.springframework.integration.gateway.GatewayInterfaceTests$Foo.baz(java.lang.String)"));
236+
equalTo("public abstract void org.springframework.integration.gateway." +
237+
"GatewayInterfaceTests$Foo.baz(java.lang.String)"));
229238
assertThat(message.getHeaders().get("object"), equalTo(bazMethod));
230239
assertThat(message.getPayload(), equalTo("hello"));
231240
called.set(true);
@@ -239,15 +248,16 @@ public void testWithServiceSuperclassUnAnnotatedMethod() throws Exception {
239248

240249
@Test
241250
public void testWithServiceUnAnnotatedMethodGlobalHeaderDoesntOverride() throws Exception {
242-
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this
243-
.getClass());
251+
ConfigurableApplicationContext ac =
252+
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
244253
DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class);
245254
final Method quxMethod = Bar.class.getMethod("qux", String.class, String.class);
246255
final AtomicBoolean called = new AtomicBoolean();
247256
MessageHandler handler = message -> {
248257
assertThat(message.getHeaders().get("name"), equalTo("arg1"));
249258
assertThat(message.getHeaders().get("string"),
250-
equalTo("public abstract void org.springframework.integration.gateway.GatewayInterfaceTests$Bar.qux(java.lang.String,java.lang.String)"));
259+
equalTo("public abstract void org.springframework.integration.gateway." +
260+
"GatewayInterfaceTests$Bar.qux(java.lang.String,java.lang.String)"));
251261
assertThat(message.getHeaders().get("object"), equalTo(quxMethod));
252262
assertThat(message.getPayload(), equalTo("hello"));
253263
called.set(true);
@@ -261,8 +271,8 @@ public void testWithServiceUnAnnotatedMethodGlobalHeaderDoesntOverride() throws
261271

262272
@Test
263273
public void testWithServiceCastAsSuperclassAnnotatedMethod() {
264-
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this
265-
.getClass());
274+
ConfigurableApplicationContext ac =
275+
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
266276
DirectChannel channel = ac.getBean("requestChannelFoo", DirectChannel.class);
267277
MessageHandler handler = mock(MessageHandler.class);
268278
channel.subscribe(handler);
@@ -274,8 +284,8 @@ public void testWithServiceCastAsSuperclassAnnotatedMethod() {
274284

275285
@Test
276286
public void testWithServiceCastAsSuperclassUnAnnotatedMethod() {
277-
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this
278-
.getClass());
287+
ConfigurableApplicationContext ac =
288+
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
279289
DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class);
280290
MessageHandler handler = mock(MessageHandler.class);
281291
channel.subscribe(handler);
@@ -287,8 +297,8 @@ public void testWithServiceCastAsSuperclassUnAnnotatedMethod() {
287297

288298
@Test
289299
public void testWithServiceHashcode() {
290-
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this
291-
.getClass());
300+
ConfigurableApplicationContext ac =
301+
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
292302
DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class);
293303
MessageHandler handler = mock(MessageHandler.class);
294304
channel.subscribe(handler);
@@ -300,8 +310,8 @@ public void testWithServiceHashcode() {
300310

301311
@Test
302312
public void testWithServiceToString() {
303-
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this
304-
.getClass());
313+
ConfigurableApplicationContext ac =
314+
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
305315
DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class);
306316
MessageHandler handler = mock(MessageHandler.class);
307317
channel.subscribe(handler);
@@ -313,29 +323,29 @@ public void testWithServiceToString() {
313323

314324
@Test
315325
public void testWithServiceEquals() throws Exception {
316-
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this
317-
.getClass());
326+
ConfigurableApplicationContext ac =
327+
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
318328
DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class);
319329
MessageHandler handler = mock(MessageHandler.class);
320330
channel.subscribe(handler);
321331
Bar bar = ac.getBean(Bar.class);
322-
assertTrue(bar.equals(ac.getBean(Bar.class)));
332+
assertSame(bar, ac.getBean(Bar.class));
323333
GatewayProxyFactoryBean fb = new GatewayProxyFactoryBean(Bar.class);
324334
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
325335
bf.registerSingleton("requestChannelBar", channel);
326336
bf.registerSingleton("requestChannelBaz", channel);
327337
bf.registerSingleton("requestChannelFoo", channel);
328338
fb.setBeanFactory(bf);
329339
fb.afterPropertiesSet();
330-
assertFalse(bar.equals(fb.getObject()));
340+
assertNotSame(bar, fb.getObject());
331341
verify(handler, times(0)).handleMessage(Mockito.any(Message.class));
332342
ac.close();
333343
}
334344

335345
@Test
336346
public void testWithServiceGetClass() {
337-
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this
338-
.getClass());
347+
ConfigurableApplicationContext ac =
348+
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
339349
DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class);
340350
MessageHandler handler = mock(MessageHandler.class);
341351
channel.subscribe(handler);
@@ -352,12 +362,12 @@ public void testWithServiceAsNotAnInterface() {
352362

353363
@Test
354364
public void testWithCustomMapper() {
355-
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this
356-
.getClass());
365+
ConfigurableApplicationContext ac =
366+
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
357367
DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class);
358368
final AtomicBoolean called = new AtomicBoolean();
359369
MessageHandler handler = message -> {
360-
assertThat((String) message.getPayload(), equalTo("fizbuz"));
370+
assertThat(message.getPayload(), equalTo("fizbuz"));
361371
called.set(true);
362372
};
363373
channel.subscribe(handler);
@@ -369,8 +379,13 @@ public void testWithCustomMapper() {
369379

370380
@Test
371381
public void testLateReply() {
372-
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml",
373-
this.getClass());
382+
ConfigurableApplicationContext ac =
383+
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
384+
385+
DelayHandler delayHandler = ac.getBean(DelayHandler.class);
386+
delayHandler.setMaxAttempts(2);
387+
delayHandler.setRetryDelay(10);
388+
374389
Bar baz = ac.getBean(Bar.class);
375390
String reply = baz.lateReply("hello", 1000, 0);
376391
assertNull(reply);
@@ -448,14 +463,15 @@ public void testAutoCreateChannelGateway() {
448463
@SuppressWarnings("rawtypes")
449464
public void testAnnotationGatewayProxyFactoryBean() {
450465
assertNotNull(this.gatewayByAnnotationGPFB);
466+
assertNull(this.notActivatedByProfileGateway);
451467

452468
assertSame(this.exec, this.annotationGatewayProxyFactoryBean.getAsyncExecutor());
453-
assertEquals(1111L, TestUtils
454-
.getPropertyValue(this.annotationGatewayProxyFactoryBean, "defaultRequestTimeout", Expression.class)
455-
.getValue());
456-
assertEquals(222L, TestUtils
457-
.getPropertyValue(this.annotationGatewayProxyFactoryBean, "defaultReplyTimeout", Expression.class)
458-
.getValue());
469+
assertEquals(1111L,
470+
TestUtils.getPropertyValue(this.annotationGatewayProxyFactoryBean,
471+
"defaultRequestTimeout", Expression.class).getValue());
472+
assertEquals(222L,
473+
TestUtils.getPropertyValue(this.annotationGatewayProxyFactoryBean,
474+
"defaultReplyTimeout", Expression.class).getValue());
459475

460476
Collection<MessagingGatewaySupport> messagingGateways =
461477
this.annotationGatewayProxyFactoryBean.getGateways().values();
@@ -563,7 +579,7 @@ public interface NoArgumentsGateway {
563579
public static class BazMapper implements MethodArgsMessageMapper {
564580

565581
@Override
566-
public Message<?> toMessage(MethodArgsHolder object, @Nullable Map<String, Object> headers) throws Exception {
582+
public Message<?> toMessage(MethodArgsHolder object, @Nullable Map<String, Object> headers) {
567583
return MessageBuilder.withPayload("fizbuz")
568584
.copyHeadersIfAbsent(headers)
569585
.build();
@@ -652,6 +668,7 @@ public GatewayProxyFactoryBean annotationGatewayProxyFactoryBean() {
652668

653669
@MessagingGateway
654670
@TestMessagingGateway
671+
@Profile("gatewayTest")
655672
public interface Int2634Gateway {
656673

657674
@Gateway(requestChannel = "gatewayChannel", payloadExpression = "#args[0]")
@@ -665,6 +682,15 @@ public interface Int2634Gateway {
665682

666683
}
667684

685+
@MessagingGateway(defaultRequestChannel = "errorChannel")
686+
@TestMessagingGateway
687+
@Profile("notActiveProfile")
688+
public interface NotActivatedByProfileGateway {
689+
690+
void send(String payload);
691+
692+
}
693+
668694
@MessagingGateway(asyncExecutor = "exec")
669695
@TestMessagingGateway
670696
public interface ExecGateway {

0 commit comments

Comments
 (0)