diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/MessagingGatewayRegistrar.java b/spring-integration-core/src/main/java/org/springframework/integration/config/MessagingGatewayRegistrar.java index 55b530b9b5..e75ee047a0 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/MessagingGatewayRegistrar.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/MessagingGatewayRegistrar.java @@ -143,13 +143,13 @@ public class MessagingGatewayRegistrar implements ImportBeanDefinitionRegistrar, if (StringUtils.hasText(defaultRequestChannel)) { - gatewayProxyBuilder.addPropertyReference("defaultRequestChannel", defaultRequestChannel); + gatewayProxyBuilder.addPropertyValue("defaultRequestChannelName", defaultRequestChannel); } if (StringUtils.hasText(defaultReplyChannel)) { - gatewayProxyBuilder.addPropertyReference("defaultReplyChannel", defaultReplyChannel); + gatewayProxyBuilder.addPropertyValue("defaultReplyChannelName", defaultReplyChannel); } if (StringUtils.hasText(errorChannel)) { - gatewayProxyBuilder.addPropertyReference("errorChannel", errorChannel); + gatewayProxyBuilder.addPropertyValue("errorChannelName", errorChannel); } if (asyncExecutor == null || AnnotationConstants.NULL.equals(asyncExecutor)) { gatewayProxyBuilder.addPropertyValue("asyncExecutor", null); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java b/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java index 6216f53d5c..09aee99740 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java @@ -92,10 +92,16 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint private volatile MessageChannel defaultRequestChannel; + private volatile String defaultRequestChannelName; + private volatile MessageChannel defaultReplyChannel; + private volatile String defaultReplyChannelName; + private volatile MessageChannel errorChannel; + private volatile String errorChannelName; + private volatile Long defaultRequestTimeout; private volatile Long defaultReplyTimeout; @@ -160,7 +166,6 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint /** * Set the default request channel. - * * @param defaultRequestChannel the channel to which request messages will * be sent if no request channel has been configured with an annotation. */ @@ -168,11 +173,20 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint this.defaultRequestChannel = defaultRequestChannel; } + /** + * Set the default request channel bean name. + * @param defaultRequestChannelName the channel name to which request messages will + * be sent if no request channel has been configured with an annotation. + * @since 4.2.9 + */ + public void setDefaultRequestChannelName(String defaultRequestChannelName) { + this.defaultRequestChannelName = defaultRequestChannelName; + } + /** * Set the default reply channel. If no default reply channel is provided, * and no reply channel is configured with annotations, an anonymous, * temporary channel will be used for handling replies. - * * @param defaultReplyChannel the channel from which reply messages will be * received if no reply channel has been configured with an annotation */ @@ -180,17 +194,39 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint this.defaultReplyChannel = defaultReplyChannel; } + /** + * Set the default reply channel bean name. If no default reply channel is provided, + * and no reply channel is configured with annotations, an anonymous, + * temporary channel will be used for handling replies. + * @param defaultReplyChannelName the channel name from which reply messages will be + * received if no reply channel has been configured with an annotation + * @since 4.2.9 + */ + public void setDefaultReplyChannelName(String defaultReplyChannelName) { + this.defaultReplyChannelName = defaultReplyChannelName; + } + /** * Set the error channel. If no error channel is provided, this gateway will * propagate Exceptions to the caller. To completely suppress Exceptions, provide * a reference to the "nullChannel" here. - * * @param errorChannel The error channel. */ public void setErrorChannel(MessageChannel errorChannel) { this.errorChannel = errorChannel; } + /** + * Set the error channel name. If no error channel is provided, this gateway will + * propagate Exceptions to the caller. To completely suppress Exceptions, provide + * a reference to the "nullChannel" here. + * @param errorChannelName The error channel bean name. + * @since 4.2.9 + */ + public void setErrorChannelName(String errorChannelName) { + this.errorChannelName = errorChannelName; + } + /** * Set the default timeout value for sending request messages. If not * explicitly configured with an annotation, this value will be used. @@ -451,13 +487,12 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint private MethodInvocationGateway createGatewayForMethod(Method method) { Gateway gatewayAnnotation = method.getAnnotation(Gateway.class); - MessageChannel requestChannel = this.defaultRequestChannel; String requestChannelName = null; - MessageChannel replyChannel = this.defaultReplyChannel; String replyChannelName = null; Long requestTimeout = this.defaultRequestTimeout; Long replyTimeout = this.defaultReplyTimeout; - String payloadExpression = this.globalMethodMetadata != null ? this.globalMethodMetadata.getPayloadExpression() + String payloadExpression = this.globalMethodMetadata != null + ? this.globalMethodMetadata.getPayloadExpression() : null; Map headerExpressions = new HashMap(); if (gatewayAnnotation != null) { @@ -487,7 +522,7 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint String name = gatewayHeader.name(); boolean hasValue = StringUtils.hasText(value); - if (!(hasValue ^ StringUtils.hasText(expression))) { + if (hasValue == StringUtils.hasText(expression)) { throw new BeanDefinitionStoreException("exactly one of 'value' or 'expression' " + "is required on a gateway's header."); } @@ -526,25 +561,41 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint if (StringUtils.hasText(payloadExpression)) { messageMapper.setPayloadExpression(payloadExpression); } - messageMapper.setBeanFactory(this.getBeanFactory()); - MethodInvocationGateway gateway = new MethodInvocationGateway(messageMapper); - gateway.setErrorChannel(this.errorChannel); + messageMapper.setBeanFactory(this.getBeanFactory()); + MethodInvocationGateway gateway = new MethodInvocationGateway(messageMapper); + + if (this.errorChannel != null) { + gateway.setErrorChannel(this.errorChannel); + } + else if (StringUtils.hasText(this.errorChannelName)) { + gateway.setErrorChannelName(this.errorChannelName); + } + if (this.getTaskScheduler() != null) { gateway.setTaskScheduler(this.getTaskScheduler()); } gateway.setBeanName(this.getComponentName()); + if (StringUtils.hasText(requestChannelName)) { gateway.setRequestChannelName(requestChannelName); } - else { - gateway.setRequestChannel(requestChannel); + else if (StringUtils.hasText(this.defaultRequestChannelName)) { + gateway.setRequestChannelName(this.defaultRequestChannelName); } + else { + gateway.setRequestChannel(this.defaultRequestChannel); + } + if (StringUtils.hasText(replyChannelName)) { gateway.setReplyChannelName(replyChannelName); } - else { - gateway.setReplyChannel(replyChannel); + else if (StringUtils.hasText(this.defaultReplyChannelName)) { + gateway.setReplyChannelName(this.defaultReplyChannelName); } + else { + gateway.setReplyChannel(this.defaultReplyChannel); + } + if (requestTimeout == null) { gateway.setRequestTimeout(-1); } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/ChainParserTests.java b/spring-integration-core/src/test/java/org/springframework/integration/config/ChainParserTests.java index 2120f9d35f..3310d120ef 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/config/ChainParserTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/ChainParserTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -387,8 +387,8 @@ public class ChainParserTests { //INT-3117 GatewayProxyFactoryBean gatewayProxyFactoryBean = this.beanFactory.getBean("&subComponentsIdSupport1$child.gatewayWithinChain.handler", GatewayProxyFactoryBean.class); - assertSame(this.strings, TestUtils.getPropertyValue(gatewayProxyFactoryBean, "defaultRequestChannel", MessageChannel.class)); - assertSame(this.numbers, TestUtils.getPropertyValue(gatewayProxyFactoryBean, "defaultReplyChannel", MessageChannel.class)); + assertEquals("strings", TestUtils.getPropertyValue(gatewayProxyFactoryBean, "defaultRequestChannelName")); + assertEquals("numbers", TestUtils.getPropertyValue(gatewayProxyFactoryBean, "defaultReplyChannelName")); assertEquals(new Long(1000), TestUtils.getPropertyValue(gatewayProxyFactoryBean, "defaultRequestTimeout", Long.class)); assertEquals(new Long(100), TestUtils.getPropertyValue(gatewayProxyFactoryBean, "defaultReplyTimeout", Long.class)); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests.java b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests.java index ac0a7534ca..75e76c6d64 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests.java @@ -50,7 +50,9 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.ConfigurableApplicationContext; 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.support.ClassPathXmlApplicationContext; import org.springframework.core.task.AsyncTaskExecutor; import org.springframework.core.task.SimpleAsyncTaskExecutor; @@ -59,8 +61,10 @@ import org.springframework.integration.annotation.BridgeTo; import org.springframework.integration.annotation.Gateway; import org.springframework.integration.annotation.IntegrationComponentScan; import org.springframework.integration.annotation.MessagingGateway; +import org.springframework.integration.annotation.ServiceActivator; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.config.EnableIntegration; +import org.springframework.integration.handler.BridgeHandler; import org.springframework.integration.support.MessageBuilder; import org.springframework.integration.support.utils.IntegrationUtils; import org.springframework.integration.test.util.TestUtils; @@ -73,6 +77,7 @@ import org.springframework.messaging.handler.annotation.Header; import org.springframework.messaging.handler.annotation.Payload; 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.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -83,6 +88,7 @@ import org.springframework.util.concurrent.ListenableFutureCallback; * @author Oleg Zhurakousky * @author Gunnar Hillert * @author Gary Russell + * @author Artem Bilan */ @ContextConfiguration(classes = GatewayInterfaceTests.TestConfig.class) @RunWith(SpringJUnit4ClassRunner.class) @@ -109,6 +115,9 @@ public class GatewayInterfaceTests { @Autowired private SimpleAsyncTaskExecutor exec; + @Autowired + private AutoCreateChannelService autoCreateChannelService; + @Test public void testWithServiceSuperclassAnnotatedMethod() throws Exception { @@ -395,6 +404,10 @@ public class GatewayInterfaceTests { assertThat(result2.get().getName(), startsWith("exec-")); } + @Test + public void testAutoCreateChannelGateway() { + assertEquals("foo", this.autoCreateChannelService.service("foo")); + } public interface Foo { @@ -432,9 +445,23 @@ public class GatewayInterfaceTests { } + @Component + public static class AutoCreateChannelService { + + @Autowired + private AutoCreateChannelGateway gateway; + + public String service(String request) { + return this.gateway.foo(request); + } + + } + @Configuration - @EnableIntegration + @ComponentScan(includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, + classes = AutoCreateChannelService.class)) @IntegrationComponentScan + @EnableIntegration public static class TestConfig { @Bean @@ -475,6 +502,12 @@ public class GatewayInterfaceTests { return simpleAsyncTaskExecutor; } + @Bean + @ServiceActivator(inputChannel = "autoCreateChannel") + public MessageHandler autoCreateServiceActivator() { + return new BridgeHandler(); + } + } @MessagingGateway @@ -510,4 +543,12 @@ public class GatewayInterfaceTests { } + + @MessagingGateway(defaultRequestChannel = "autoCreateChannel") + public interface AutoCreateChannelGateway { + + String foo(String payload); + + } + }