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 # Conflicts: # spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests.java # src/reference/asciidoc/gateway.adoc # Conflicts: # spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests.java
This commit is contained in:
@@ -24,9 +24,11 @@ import java.util.Set;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
@@ -40,15 +42,19 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public class IntegrationComponentScanRegistrar implements ImportBeanDefinitionRegistrar,
|
||||
ResourceLoaderAware {
|
||||
ResourceLoaderAware, EnvironmentAware {
|
||||
|
||||
private final Map<TypeFilter, ImportBeanDefinitionRegistrar> componentRegistrars = new HashMap<TypeFilter, ImportBeanDefinitionRegistrar>();
|
||||
private final Map<TypeFilter, ImportBeanDefinitionRegistrar> componentRegistrars =
|
||||
new HashMap<TypeFilter, ImportBeanDefinitionRegistrar>();
|
||||
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
private Environment environment;
|
||||
|
||||
public IntegrationComponentScanRegistrar() {
|
||||
this.componentRegistrars.put(new AnnotationTypeFilter(MessagingGateway.class, true), new MessagingGatewayRegistrar());
|
||||
}
|
||||
@@ -58,6 +64,11 @@ public class IntegrationComponentScanRegistrar implements ImportBeanDefinitionRe
|
||||
this.resourceLoader = resourceLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
|
||||
Map<String, Object> componentScan = importingClassMetadata
|
||||
@@ -82,14 +93,16 @@ public class IntegrationComponentScanRegistrar implements ImportBeanDefinitionRe
|
||||
basePackages.add(ClassUtils.getPackageName(importingClassMetadata.getClassName()));
|
||||
}
|
||||
|
||||
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false) {
|
||||
ClassPathScanningCandidateComponentProvider scanner =
|
||||
new ClassPathScanningCandidateComponentProvider(false, this.environment) {
|
||||
|
||||
@Override
|
||||
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
|
||||
return beanDefinition.getMetadata().isIndependent()
|
||||
&& !beanDefinition.getMetadata().isAnnotation();
|
||||
}
|
||||
};
|
||||
@Override
|
||||
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
|
||||
return beanDefinition.getMetadata().isIndependent()
|
||||
&& !beanDefinition.getMetadata().isAnnotation();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
for (TypeFilter typeFilter : this.componentRegistrars.keySet()) {
|
||||
scanner.addIncludeFilter(typeFilter);
|
||||
|
||||
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
@@ -54,6 +55,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
@@ -70,6 +72,7 @@ import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.context.IntegrationProperties;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.integration.handler.BridgeHandler;
|
||||
import org.springframework.integration.handler.DelayHandler;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
@@ -84,6 +87,7 @@ import org.springframework.messaging.support.ChannelInterceptorAdapter;
|
||||
import org.springframework.scheduling.annotation.AsyncResult;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.concurrent.ListenableFuture;
|
||||
@@ -98,6 +102,7 @@ import org.springframework.util.concurrent.ListenableFutureCallback;
|
||||
@ContextConfiguration(classes = GatewayInterfaceTests.TestConfig.class)
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@DirtiesContext
|
||||
@ActiveProfiles("gatewayTest")
|
||||
public class GatewayInterfaceTests {
|
||||
|
||||
private static final String IGNORE_HEADER = "ignoreHeader";
|
||||
@@ -131,9 +136,13 @@ public class GatewayInterfaceTests {
|
||||
@Autowired
|
||||
private IgnoredHeaderGateway ignoredHeaderGateway;
|
||||
|
||||
@Autowired(required = false)
|
||||
private NotActivatedByProfileGateway notActivatedByProfileGateway;
|
||||
|
||||
@Test
|
||||
public void testWithServiceSuperclassAnnotatedMethod() throws Exception {
|
||||
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this.getClass());
|
||||
ConfigurableApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
|
||||
DirectChannel channel = ac.getBean("requestChannelFoo", DirectChannel.class);
|
||||
final Method fooMethod = Foo.class.getMethod("foo", String.class);
|
||||
final AtomicBoolean called = new AtomicBoolean();
|
||||
@@ -161,7 +170,8 @@ public class GatewayInterfaceTests {
|
||||
|
||||
@Test
|
||||
public void testWithServiceSuperclassAnnotatedMethodOverridePE() throws Exception {
|
||||
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests2-context.xml", this.getClass());
|
||||
ConfigurableApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("GatewayInterfaceTests2-context.xml", getClass());
|
||||
DirectChannel channel = ac.getBean("requestChannelFoo", DirectChannel.class);
|
||||
final Method fooMethod = Foo.class.getMethod("foo", String.class);
|
||||
final AtomicBoolean called = new AtomicBoolean();
|
||||
@@ -187,7 +197,8 @@ public class GatewayInterfaceTests {
|
||||
|
||||
@Test
|
||||
public void testWithServiceAnnotatedMethod() {
|
||||
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this.getClass());
|
||||
ConfigurableApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
|
||||
DirectChannel channel = ac.getBean("requestChannelBar", DirectChannel.class);
|
||||
MessageHandler handler = mock(MessageHandler.class);
|
||||
channel.subscribe(handler);
|
||||
@@ -199,7 +210,8 @@ public class GatewayInterfaceTests {
|
||||
|
||||
@Test
|
||||
public void testWithServiceSuperclassUnAnnotatedMethod() throws Exception {
|
||||
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this.getClass());
|
||||
ConfigurableApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
|
||||
DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class);
|
||||
final Method bazMethod = Foo.class.getMethod("baz", String.class);
|
||||
final AtomicBoolean called = new AtomicBoolean();
|
||||
@@ -225,7 +237,8 @@ public class GatewayInterfaceTests {
|
||||
|
||||
@Test
|
||||
public void testWithServiceUnAnnotatedMethodGlobalHeaderDoesntOverride() throws Exception {
|
||||
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this.getClass());
|
||||
ConfigurableApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
|
||||
DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class);
|
||||
final Method quxMethod = Bar.class.getMethod("qux", String.class, String.class);
|
||||
final AtomicBoolean called = new AtomicBoolean();
|
||||
@@ -251,7 +264,8 @@ public class GatewayInterfaceTests {
|
||||
|
||||
@Test
|
||||
public void testWithServiceCastAsSuperclassAnnotatedMethod() {
|
||||
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this.getClass());
|
||||
ConfigurableApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
|
||||
DirectChannel channel = ac.getBean("requestChannelFoo", DirectChannel.class);
|
||||
MessageHandler handler = mock(MessageHandler.class);
|
||||
channel.subscribe(handler);
|
||||
@@ -263,7 +277,8 @@ public class GatewayInterfaceTests {
|
||||
|
||||
@Test
|
||||
public void testWithServiceCastAsSuperclassUnAnnotatedMethod() {
|
||||
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this.getClass());
|
||||
ConfigurableApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
|
||||
DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class);
|
||||
MessageHandler handler = mock(MessageHandler.class);
|
||||
channel.subscribe(handler);
|
||||
@@ -274,8 +289,9 @@ public class GatewayInterfaceTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithServiceHashcode() throws Exception {
|
||||
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this.getClass());
|
||||
public void testWithServiceHashcode() {
|
||||
ConfigurableApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
|
||||
DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class);
|
||||
MessageHandler handler = mock(MessageHandler.class);
|
||||
channel.subscribe(handler);
|
||||
@@ -287,7 +303,8 @@ public class GatewayInterfaceTests {
|
||||
|
||||
@Test
|
||||
public void testWithServiceToString() {
|
||||
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this.getClass());
|
||||
ConfigurableApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
|
||||
DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class);
|
||||
MessageHandler handler = mock(MessageHandler.class);
|
||||
channel.subscribe(handler);
|
||||
@@ -299,12 +316,13 @@ public class GatewayInterfaceTests {
|
||||
|
||||
@Test
|
||||
public void testWithServiceEquals() throws Exception {
|
||||
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this.getClass());
|
||||
ConfigurableApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
|
||||
DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class);
|
||||
MessageHandler handler = mock(MessageHandler.class);
|
||||
channel.subscribe(handler);
|
||||
Bar bar = ac.getBean(Bar.class);
|
||||
assertTrue(bar.equals(ac.getBean(Bar.class)));
|
||||
assertSame(bar, ac.getBean(Bar.class));
|
||||
GatewayProxyFactoryBean fb = new GatewayProxyFactoryBean(Bar.class);
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerSingleton("requestChannelBar", channel);
|
||||
@@ -312,14 +330,15 @@ public class GatewayInterfaceTests {
|
||||
bf.registerSingleton("requestChannelFoo", channel);
|
||||
fb.setBeanFactory(bf);
|
||||
fb.afterPropertiesSet();
|
||||
assertFalse(bar.equals(fb.getObject()));
|
||||
assertNotSame(bar, fb.getObject());
|
||||
verify(handler, times(0)).handleMessage(Mockito.any(Message.class));
|
||||
ac.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithServiceGetClass() {
|
||||
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this.getClass());
|
||||
ConfigurableApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
|
||||
DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class);
|
||||
MessageHandler handler = mock(MessageHandler.class);
|
||||
channel.subscribe(handler);
|
||||
@@ -336,7 +355,8 @@ public class GatewayInterfaceTests {
|
||||
|
||||
@Test
|
||||
public void testWithCustomMapper() {
|
||||
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this.getClass());
|
||||
ConfigurableApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", getClass());
|
||||
DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class);
|
||||
final AtomicBoolean called = new AtomicBoolean();
|
||||
MessageHandler handler = new MessageHandler() {
|
||||
@@ -577,6 +597,7 @@ public class GatewayInterfaceTests {
|
||||
}
|
||||
|
||||
@MessagingGateway
|
||||
@Profile("gatewayTest")
|
||||
public interface Int2634Gateway {
|
||||
|
||||
@Gateway(requestChannel = "gatewayChannel", payloadExpression = "#args[0]")
|
||||
@@ -590,6 +611,15 @@ public class GatewayInterfaceTests {
|
||||
|
||||
}
|
||||
|
||||
@MessagingGateway(defaultRequestChannel = "errorChannel")
|
||||
@TestMessagingGateway
|
||||
@Profile("notActiveProfile")
|
||||
public interface NotActivatedByProfileGateway {
|
||||
|
||||
void send(String payload);
|
||||
|
||||
}
|
||||
|
||||
@MessagingGateway(asyncExecutor = "exec")
|
||||
public interface ExecGateway {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user