From f2603a9559de415364b1d3466fdc330c0f7c4bd7 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Tue, 29 Sep 2009 01:19:36 +0000 Subject: [PATCH] INT-707 --- .../integration/config/xml/GatewayParser.java | 25 +++++++ .../gateway/GatewayMethodDefinition.java | 57 +++++++++++++++ .../gateway/GatewayProxyFactoryBean.java | 46 ++++++++++--- .../config/xml/spring-integration-2.0.xsd | 11 +++ .../MultiMethodGatewayConfig-context.xml | 30 ++++++++ .../gateway/MultiMethodGatewayConfig.java | 69 +++++++++++++++++++ 6 files changed, 229 insertions(+), 9 deletions(-) create mode 100644 org.springframework.integration/src/main/java/org/springframework/integration/gateway/GatewayMethodDefinition.java create mode 100644 org.springframework.integration/src/test/java/org/springframework/integration/gateway/MultiMethodGatewayConfig-context.xml create mode 100644 org.springframework.integration/src/test/java/org/springframework/integration/gateway/MultiMethodGatewayConfig.java diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/GatewayParser.java b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/GatewayParser.java index 65edbd451b..cfec968ed2 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/GatewayParser.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/GatewayParser.java @@ -16,11 +16,18 @@ package org.springframework.integration.config.xml; +import java.util.List; + import org.w3c.dom.Element; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.integration.gateway.GatewayMethodDefinition; import org.springframework.util.ObjectUtils; +import org.springframework.util.xml.DomUtils; /** * Parser for the <gateway/> element. @@ -33,6 +40,24 @@ public class GatewayParser extends AbstractSimpleBeanDefinitionParser { "default-request-channel", "default-reply-channel", "message-mapper" }; + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + super.doParse(element, builder); + List elements = DomUtils.getChildElementsByTagName(element, "method"); + ManagedMap methodToChannelMap = null; + if (elements != null && elements.size() > 0){ + methodToChannelMap = new ManagedMap(); + } + for (Element methodElement : elements) { + String methodName = methodElement.getAttribute("name"); + GatewayMethodDefinition gatewayDefinition = new GatewayMethodDefinition(); + gatewayDefinition.setRequestChannelName(methodElement.getAttribute("request-channel")); + gatewayDefinition.setReplyChannelName(methodElement.getAttribute("reply-channel")); + gatewayDefinition.setRequestTimeout(methodElement.getAttribute("request-timeout")); + gatewayDefinition.setReplyTimeout(methodElement.getAttribute("reply-timeout")); + methodToChannelMap.put(methodName, gatewayDefinition); + } + builder.addPropertyValue("methodToChannelMap", methodToChannelMap); + } @Override protected String getBeanClassName(Element element) { diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/gateway/GatewayMethodDefinition.java b/org.springframework.integration/src/main/java/org/springframework/integration/gateway/GatewayMethodDefinition.java new file mode 100644 index 0000000000..edef9f6914 --- /dev/null +++ b/org.springframework.integration/src/main/java/org/springframework/integration/gateway/GatewayMethodDefinition.java @@ -0,0 +1,57 @@ +/* + * Copyright 2002-2008 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 + * + * http://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.integration.gateway; + +/** + * Represents the definition of Gateway methods, when using multiple methos per + * Gateway interface
+ * + * + * @author Oleg Zhurakousky + * @since 2.0.M1 + */ +public class GatewayMethodDefinition { + + private String requestChannelName; + private String replyChannelName; + private String requestTimeout; + private String replyTimeout; + public String getRequestChannelName() { + return requestChannelName; + } + public void setRequestChannelName(String requestChannelName) { + this.requestChannelName = requestChannelName; + } + public String getReplyChannelName() { + return replyChannelName; + } + public void setReplyChannelName(String replyChannelName) { + this.replyChannelName = replyChannelName; + } + public String getRequestTimeout() { + return requestTimeout; + } + public void setRequestTimeout(String requestTimeout) { + this.requestTimeout = requestTimeout; + } + public String getReplyTimeout() { + return replyTimeout; + } + public void setReplyTimeout(String replyTimeout) { + this.replyTimeout = replyTimeout; + } + +} diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java b/org.springframework.integration/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java index 78ab474794..bf7e45ede3 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java @@ -46,6 +46,7 @@ import org.springframework.util.StringUtils; * with messaging components without application code being aware of them. * * @author Mark Fisher + * @author Oleg Zhurakousky */ public class GatewayProxyFactoryBean extends AbstractEndpoint implements FactoryBean, MethodInterceptor, BeanClassLoaderAware { @@ -70,7 +71,7 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint implements Factory private volatile boolean initialized; private final Object initializationMonitor = new Object(); - + private Map methodToChannelMap; public void setServiceInterface(Class serviceInterface) { if (serviceInterface != null && !serviceInterface.isInterface()) { @@ -236,17 +237,28 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint implements Factory if (gatewayAnnotation != null) { Assert.state(this.getChannelResolver() != null, "ChannelResolver is required"); String requestChannelName = gatewayAnnotation.requestChannel(); - if (StringUtils.hasText(requestChannelName)) { - requestChannel = this.getChannelResolver().resolveChannelName(requestChannelName); - Assert.notNull(requestChannel, "failed to resolve request channel '" + requestChannelName + "'"); - } + requestChannel = this.resolveChannel(requestChannel, requestChannelName); String replyChannelName = gatewayAnnotation.replyChannel(); - if (StringUtils.hasText(replyChannelName)) { - replyChannel = this.getChannelResolver().resolveChannelName(replyChannelName); - Assert.notNull(replyChannel, "failed to resolve reply channel '" + replyChannelName + "'"); - } + replyChannel = this.resolveChannel(replyChannel, replyChannelName); requestTimeout = gatewayAnnotation.requestTimeout(); replyTimeout = gatewayAnnotation.replyTimeout(); + } else if (methodToChannelMap != null && methodToChannelMap.size() > 0) { + Assert.state(this.getChannelResolver() != null, "ChannelResolver is required"); + GatewayMethodDefinition gatewayDefinition = methodToChannelMap.get(method.getName()); + if (gatewayDefinition != null){ + String requestChannelName = gatewayDefinition.getRequestChannelName(); + requestChannel = this.resolveChannel(requestChannel, requestChannelName); + String replyChannelName = gatewayDefinition.getReplyChannelName(); + replyChannel = this.resolveChannel(replyChannel, replyChannelName); + String reqTimeout = gatewayDefinition.getRequestTimeout(); + if (StringUtils.hasText(reqTimeout)){ + requestTimeout = typeConverter.convertIfNecessary(reqTimeout, Long.class); + } + String repTimeout = gatewayDefinition.getReplyTimeout(); + if (StringUtils.hasText(repTimeout)){ + replyTimeout = typeConverter.convertIfNecessary(repTimeout, Long.class); + } + } } gateway.setRequestChannel(requestChannel); gateway.setReplyChannel(replyChannel); @@ -257,6 +269,14 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint implements Factory } return gateway; } + + private MessageChannel resolveChannel(MessageChannel channel, String channelName) { + if (StringUtils.hasText(channelName)) { + channel = this.getChannelResolver().resolveChannelName(channelName); + Assert.notNull(channel, "failed to resolve channel '" + channelName + "'"); + } + return channel; + } // Lifecycle implementation @@ -277,5 +297,13 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint implements Factory } } } + + public Map getMethodToChannelMap() { + return methodToChannelMap; + } + + public void setMethodToChannelMap(Map methodToChannelMap) { + this.methodToChannelMap = methodToChannelMap; + } } diff --git a/org.springframework.integration/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd b/org.springframework.integration/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd index 01305a10f3..7df039ec1a 100644 --- a/org.springframework.integration/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd +++ b/org.springframework.integration/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd @@ -304,6 +304,17 @@ Defines a Messaging Gateway. + + + + + + + + + + + diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/gateway/MultiMethodGatewayConfig-context.xml b/org.springframework.integration/src/test/java/org/springframework/integration/gateway/MultiMethodGatewayConfig-context.xml new file mode 100644 index 0000000000..bca409befd --- /dev/null +++ b/org.springframework.integration/src/test/java/org/springframework/integration/gateway/MultiMethodGatewayConfig-context.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/gateway/MultiMethodGatewayConfig.java b/org.springframework.integration/src/test/java/org/springframework/integration/gateway/MultiMethodGatewayConfig.java new file mode 100644 index 0000000000..9c967cbf4d --- /dev/null +++ b/org.springframework.integration/src/test/java/org/springframework/integration/gateway/MultiMethodGatewayConfig.java @@ -0,0 +1,69 @@ +/* + * Copyright 2002-2008 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 + * + * http://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.integration.gateway; + +import junit.framework.Assert; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Oleg Zhurakousky + * @since 2.0.M1 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class MultiMethodGatewayConfig { + + @Autowired + private ApplicationContext applicationContext; + @Test + public void validateGatewayMethods(){ + TestGateway gateway = (TestGateway) applicationContext.getBean("myGateway"); + Assert.assertEquals(gateway.echo("oleg"), + "org.springframework.integration.gateway.MultiMethodGatewayConfig$TestBeanA:oleg"); + Assert.assertEquals(gateway.echoUpperCase("oleg"), + "org.springframework.integration.gateway.MultiMethodGatewayConfig$TestBeanB:oleg"); + Assert.assertEquals(gateway.echoViaDefault("oleg"), + "org.springframework.integration.gateway.MultiMethodGatewayConfig$TestBeanC:oleg"); + } + + public static class TestBeanA{ + public String echo(String str){ + return this.getClass().getName() + ":" + str; + } + } + public static class TestBeanB{ + public String echo(String str){ + return this.getClass().getName() + ":" + str; + } + } + public static class TestBeanC{ + public String echo(String str){ + return this.getClass().getName() + ":" + str; + } + } + + public static interface TestGateway{ + public String echo(String str); + public String echoViaDefault(String str); + public String echoUpperCase(String str); + } +}