This commit is contained in:
Oleg Zhurakousky
2009-09-29 01:19:36 +00:00
parent 42a5155d50
commit f2603a9559
6 changed files with 229 additions and 9 deletions

View File

@@ -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<Element> elements = DomUtils.getChildElementsByTagName(element, "method");
ManagedMap<String, GatewayMethodDefinition> methodToChannelMap = null;
if (elements != null && elements.size() > 0){
methodToChannelMap = new ManagedMap<String, GatewayMethodDefinition>();
}
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) {

View File

@@ -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 <br>
* <si:method name="echo" request-channel="inputA" reply-timeout="2" request-timeout="200"/>
*
* @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;
}
}

View File

@@ -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<String, GatewayMethodDefinition> 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<String, GatewayMethodDefinition> getMethodToChannelMap() {
return methodToChannelMap;
}
public void setMethodToChannelMap(Map<String, GatewayMethodDefinition> methodToChannelMap) {
this.methodToChannelMap = methodToChannelMap;
}
}

View File

@@ -304,6 +304,17 @@
Defines a Messaging Gateway.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="method" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="request-channel" type="xsd:string" />
<xsd:attribute name="reply-channel" type="xsd:string" />
<xsd:attribute name="request-timeout" type="xsd:string" />
<xsd:attribute name="reply-timeout" type="xsd:string" />
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:ID" use="required" />
<xsd:attribute name="service-interface" type="xsd:string" use="required">
<xsd:annotation>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd"
xmlns:si="http://www.springframework.org/schema/integration">
<si:gateway id="myGateway" service-interface="org.springframework.integration.gateway.MultiMethodGatewayConfig$TestGateway"
default-request-channel="inputC">
<si:method name="echo" request-channel="inputA" reply-timeout="2" request-timeout="200"/>
<si:method name="echoUpperCase" request-channel="inputB"/>
<si:method name="echoViaDefault"/>
</si:gateway>
<si:channel id="inputA"/>
<si:service-activator input-channel="inputA" method="echo">
<bean class="org.springframework.integration.gateway.MultiMethodGatewayConfig$TestBeanA"/>
</si:service-activator>
<!-- -->
<si:channel id="inputB"/>
<si:service-activator input-channel="inputB" method="echo">
<bean class="org.springframework.integration.gateway.MultiMethodGatewayConfig$TestBeanB"/>
</si:service-activator>
<si:channel id="inputC"/>
<si:service-activator input-channel="inputC" method="echo">
<bean class="org.springframework.integration.gateway.MultiMethodGatewayConfig$TestBeanC"/>
</si:service-activator>
</beans>

View File

@@ -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);
}
}