Merge pull request #84 from markfisher/INT-1931

add URI variable Expressions to outbound gateway
This commit is contained in:
Mark Fisher
2011-09-27 12:52:02 -04:00
11 changed files with 411 additions and 133 deletions

View File

@@ -471,7 +471,8 @@ project('spring-integration-ws') {
compile project(":spring-integration-core")
compile "org.springframework:spring-expression:$springVersion"
compile "org.springframework:spring-oxm:$springVersion"
compile ("org.springframework.ws:spring-ws-core:$springWsVersion"){
compile "org.springframework:spring-web:$springVersion"
compile ("org.springframework.ws:spring-ws-core:$springWsVersion") {
exclude group: 'org.springframework', module: 'spring-webmvc'
exclude group: 'org.springframework', module: 'spring-web'
exclude group: 'org.springframework', module: 'spring-context-support'

View File

@@ -88,12 +88,6 @@
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-test</artifactId>
<version>2.1.0.BUILD-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sun.xml.messaging.saaj</groupId>
<artifactId>saaj-impl</artifactId>
@@ -101,6 +95,12 @@
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-test</artifactId>
<version>2.1.0.BUILD-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
@@ -119,6 +119,12 @@
<version>1.2.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
@@ -140,10 +146,10 @@
</exclusions>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2</version>
<scope>test</scope>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.0.6.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.xml.soap</groupId>
@@ -189,12 +195,6 @@
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
<version>2.1.0.BUILD-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
@@ -207,6 +207,12 @@
<version>1.8.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
<version>2.1.0.BUILD-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit-dep</artifactId>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -17,13 +17,31 @@
package org.springframework.integration.ws;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.context.expression.MapAccessor;
import org.springframework.core.convert.ConversionService;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.expression.spel.support.StandardTypeConverter;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.MessageDeliveryException;
import org.springframework.integration.MessagingException;
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.util.UriTemplate;
import org.springframework.web.util.UriUtils;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.FaultMessageResolver;
@@ -43,20 +61,58 @@ import org.springframework.ws.transport.WebServiceMessageSender;
*/
public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyProducingMessageHandler {
private static final ExpressionParser PARSER = new SpelExpressionParser();
private final WebServiceTemplate webServiceTemplate;
private final UriTemplate uriTemplate;
private final DestinationProvider destinationProvider;
private final Map<String, Expression> uriVariableExpressions = new HashMap<String, Expression>();
private final StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
private volatile WebServiceMessageCallback requestCallback;
private volatile boolean ignoreEmptyResponses = true;
public AbstractWebServiceOutboundGateway(DestinationProvider destinationProvider, WebServiceMessageFactory messageFactory) {
Assert.notNull(destinationProvider, "DestinationProvider must not be null");
this.webServiceTemplate = (messageFactory != null) ?
public AbstractWebServiceOutboundGateway(String uri, WebServiceMessageFactory messageFactory) {
Assert.hasText(uri, "URI must not be empty");
this.webServiceTemplate = (messageFactory != null) ?
new WebServiceTemplate(messageFactory) : new WebServiceTemplate();
this.webServiceTemplate.setDestinationProvider(destinationProvider);
this.destinationProvider = null;
this.uriTemplate = new HttpUrlTemplate(uri);
}
public AbstractWebServiceOutboundGateway(DestinationProvider destinationProvider, WebServiceMessageFactory messageFactory) {
Assert.notNull(destinationProvider, "DestinationProvider must not be null");
this.webServiceTemplate = (messageFactory != null) ?
new WebServiceTemplate(messageFactory) : new WebServiceTemplate();
this.destinationProvider = destinationProvider;
// we always call WebServiceTemplate methods with an explicit URI argument,
// but in case the WebServiceTemplate is accessed directly we'll set this:
this.webServiceTemplate.setDestinationProvider(destinationProvider);
this.uriTemplate = null;
}
/**
* Set the Map of URI variable expressions to evaluate against the outbound message
* when replacing the variable placeholders in a URI template.
*/
public void setUriVariableExpressions(Map<String, String> uriVariableExpressions) {
synchronized (this.uriVariableExpressions) {
this.uriVariableExpressions.clear();
if (!CollectionUtils.isEmpty(uriVariableExpressions)) {
for (Map.Entry<String, String> entry : uriVariableExpressions.entrySet()) {
this.uriVariableExpressions.put(entry.getKey(), PARSER.parseExpression(entry.getValue()));
}
}
}
}
public void setReplyChannel(MessageChannel replyChannel) {
this.setOutputChannel(replyChannel);
@@ -95,13 +151,32 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
this.webServiceTemplate.setInterceptors(interceptors);
}
@Override
public void onInit() {
super.onInit();
BeanFactory beanFactory = this.getBeanFactory();
if (beanFactory != null) {
this.evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
}
ConversionService conversionService = this.getConversionService();
if (conversionService != null) {
this.evaluationContext.setTypeConverter(new StandardTypeConverter(conversionService));
}
this.evaluationContext.addPropertyAccessor(new MapAccessor());
}
protected WebServiceTemplate getWebServiceTemplate() {
return this.webServiceTemplate;
}
@Override
public final Object handleRequestMessage(Message<?> message) {
Object responsePayload = this.doHandle(message.getPayload(), this.getRequestCallback(message));
URI uri = prepareUri(message);
if (uri == null) {
throw new MessageDeliveryException(message, "Failed to determine URI for " +
"Web Service request in outbound gateway: " + this.getComponentName());
}
Object responsePayload = this.doHandle(uri.toString(), message.getPayload(), this.getRequestCallback(message));
if (responsePayload != null) {
boolean shouldIgnore = (this.ignoreEmptyResponses
&& responsePayload instanceof String && !StringUtils.hasText((String) responsePayload));
@@ -112,9 +187,21 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
return null;
}
protected abstract Object doHandle(Object requestPayload, WebServiceMessageCallback requestCallback);
protected abstract Object doHandle(String uri, Object requestPayload, WebServiceMessageCallback requestCallback);
private URI prepareUri(Message<?> requestMessage) {
if (this.destinationProvider != null) {
return this.destinationProvider.getDestination();
}
Map<String, Object> uriVariables = new HashMap<String, Object>();
for (Map.Entry<String, Expression> entry : this.uriVariableExpressions.entrySet()) {
Object value = entry.getValue().getValue(this.evaluationContext, requestMessage, String.class);
uriVariables.put(entry.getKey(), value);
}
return this.uriTemplate.expand(uriVariables);
}
private WebServiceMessageCallback getRequestCallback(Message<?> requestMessage) {
String soapAction = requestMessage.getHeaders().get(WebServiceHeaders.SOAP_ACTION, String.class);
return (soapAction != null) ?
@@ -147,4 +234,32 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
}
}
/**
* HTTP-specific subclass of UriTemplate, overriding the encode method.
* This was copied from RestTemplate in version 3.0.6 (since it's private)
*/
@SuppressWarnings("serial")
private static class HttpUrlTemplate extends UriTemplate {
public HttpUrlTemplate(String uriTemplate) {
super(uriTemplate);
}
@Override
protected URI encodeUri(String uri) {
try {
String encoded = UriUtils.encodeHttpUrl(uri, "UTF-8");
return new URI(encoded);
}
catch (UnsupportedEncodingException ex) {
// should not happen, UTF-8 is always supported
throw new IllegalStateException(ex);
}
catch (URISyntaxException ex) {
throw new IllegalArgumentException("Could not create HTTP URL from [" + uri + "]: " + ex, ex);
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 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.
@@ -35,10 +35,7 @@ public class MarshallingWebServiceOutboundGateway extends AbstractWebServiceOutb
public MarshallingWebServiceOutboundGateway(DestinationProvider destinationProvider, Marshaller marshaller, Unmarshaller unmarshaller, WebServiceMessageFactory messageFactory) {
super(destinationProvider, messageFactory);
Assert.notNull(marshaller, "marshaller must not be null");
Assert.notNull(unmarshaller, "unmarshaller must not be null");
this.getWebServiceTemplate().setMarshaller(marshaller);
this.getWebServiceTemplate().setUnmarshaller(unmarshaller);
this.configureMarshallers(marshaller, unmarshaller);
}
public MarshallingWebServiceOutboundGateway(DestinationProvider destinationProvider, Marshaller marshaller, Unmarshaller unmarshaller) {
@@ -47,23 +44,60 @@ public class MarshallingWebServiceOutboundGateway extends AbstractWebServiceOutb
public MarshallingWebServiceOutboundGateway(DestinationProvider destinationProvider, Marshaller marshaller, WebServiceMessageFactory messageFactory) {
super(destinationProvider, messageFactory);
Assert.notNull(marshaller, "marshaller must not be null");
Assert.isInstanceOf(Unmarshaller.class, marshaller,
"Marshaller [" + marshaller + "] does not implement the Unmarshaller interface. " +
"Please set an Unmarshaller explicitly by using the " + this.getClass().getName() +
"(DestinationProvider destinationProvider, Marshaller marshaller, Unmarshaller unmarshaller) constructor.");
this.getWebServiceTemplate().setMarshaller(marshaller);
this.getWebServiceTemplate().setUnmarshaller((Unmarshaller) marshaller);
this.configureMarshallers(marshaller);
}
public MarshallingWebServiceOutboundGateway(DestinationProvider destinationProvider, Marshaller marshaller) {
this(destinationProvider, marshaller, (WebServiceMessageFactory) null);
}
public MarshallingWebServiceOutboundGateway(String uri, Marshaller marshaller, Unmarshaller unmarshaller, WebServiceMessageFactory messageFactory) {
super(uri, messageFactory);
this.configureMarshallers(marshaller, unmarshaller);
}
public MarshallingWebServiceOutboundGateway(String uri, Marshaller marshaller, Unmarshaller unmarshaller) {
this(uri, marshaller, unmarshaller, null);
}
public MarshallingWebServiceOutboundGateway(String uri, Marshaller marshaller, WebServiceMessageFactory messageFactory) {
super(uri, messageFactory);
this.configureMarshallers(marshaller);
}
public MarshallingWebServiceOutboundGateway(String uri, Marshaller marshaller) {
this(uri, marshaller, (WebServiceMessageFactory) null);
}
/**
* Sets the provided Marshaller and Unmarshaller on this gateway's WebServiceTemplate.
* Neither may be null.
*/
private void configureMarshallers(Marshaller marshaller, Unmarshaller unmarshaller) {
Assert.notNull(marshaller, "marshaller must not be null");
Assert.notNull(unmarshaller, "unmarshaller must not be null");
this.getWebServiceTemplate().setMarshaller(marshaller);
this.getWebServiceTemplate().setUnmarshaller(unmarshaller);
}
/**
* Sets the provided Marshaller on this gateway's WebServiceTemplate as both its
* Marshaller and Unmarshaller. Therefore, it must implement both, and it must not be null.
*/
private void configureMarshallers(Marshaller marshaller) {
Assert.notNull(marshaller, "marshaller must not be null");
Assert.isInstanceOf(Unmarshaller.class, marshaller,
"Marshaller [" + marshaller + "] does not implement the Unmarshaller interface. " +
"Please set an Unmarshaller explicitly by using one of the constructors that accepts " +
"both Marshaller and Unmarshaller arguments.");
this.getWebServiceTemplate().setMarshaller(marshaller);
this.getWebServiceTemplate().setUnmarshaller((Unmarshaller) marshaller);
}
@Override
protected Object doHandle(Object requestPayload, WebServiceMessageCallback requestCallback) {
return this.getWebServiceTemplate().marshalSendAndReceive(requestPayload, requestCallback);
protected Object doHandle(String uri, Object requestPayload, WebServiceMessageCallback requestCallback) {
return this.getWebServiceTemplate().marshalSendAndReceive(uri, requestPayload, requestCallback);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -58,23 +58,36 @@ public class SimpleWebServiceOutboundGateway extends AbstractWebServiceOutboundG
this.sourceExtractor = (sourceExtractor != null) ? sourceExtractor : new DefaultSourceExtractor();
}
public SimpleWebServiceOutboundGateway(String uri) {
this(uri, null, null);
}
public SimpleWebServiceOutboundGateway(String uri, SourceExtractor<?> sourceExtractor) {
this(uri, sourceExtractor, (WebServiceMessageFactory) null);
}
public SimpleWebServiceOutboundGateway(String uri, SourceExtractor<?> sourceExtractor, WebServiceMessageFactory messageFactory) {
super(uri, messageFactory);
this.sourceExtractor = (sourceExtractor != null) ? sourceExtractor : new DefaultSourceExtractor();
}
@Override
protected Object doHandle(Object requestPayload, WebServiceMessageCallback requestCallback) {
protected Object doHandle(String uri, Object requestPayload, WebServiceMessageCallback requestCallback) {
if (requestPayload instanceof Source) {
return this.getWebServiceTemplate().sendSourceAndReceive(
(Source) requestPayload, requestCallback, this.sourceExtractor);
uri, (Source) requestPayload, requestCallback, this.sourceExtractor);
}
if (requestPayload instanceof String) {
StringResult result = new StringResult();
this.getWebServiceTemplate().sendSourceAndReceiveToResult(
new StringSource((String) requestPayload), requestCallback, result);
uri, new StringSource((String) requestPayload), requestCallback, result);
return result.toString();
}
if (requestPayload instanceof Document) {
DOMResult result = new DOMResult();
this.getWebServiceTemplate().sendSourceAndReceiveToResult(
new DOMSource((Document) requestPayload), requestCallback, result);
uri, new DOMSource((Document) requestPayload), requestCallback, result);
return result.getNode();
}
throw new MessagingException("Unsupported payload type '" + requestPayload.getClass() +

View File

@@ -1,54 +0,0 @@
/*
* Copyright 2002-2009 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.ws.config;
import java.net.URI;
/**
* @author Jonas Partner
* @author Mark Fisher
* @since 1.0.3
*/
import org.springframework.util.Assert;
import org.springframework.ws.client.support.destination.DestinationProvider;
/**
* A {@link DestinationProvider} implementation that returns a fixed URI.
* This is used by the outbound gateway parser when no 'destination-provider'
* reference has been configured.
*
* @author Jonas Partner
* @author Mark Fisher
* @since 1.0.3
*/
class FixedUriDestinationProvider implements DestinationProvider {
private final URI uri;
public FixedUriDestinationProvider(String uri) {
Assert.hasText(uri, "uri must not be null or empty");
this.uri = URI.create(uri);
}
public URI getDestination() {
return this.uri;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -16,17 +16,21 @@
package org.springframework.integration.ws.config;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractOutboundGatewayParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
/**
* Parser for the &lt;outbound-gateway/&gt; element in the 'ws' namespace.
@@ -46,34 +50,41 @@ public class WebServiceOutboundGatewayParser extends AbstractOutboundGatewayPars
return BASE_PACKAGE + "." + simpleClassName;
}
@Override
@Override
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(this.getGatewayClassName(element));
this.buildDestinationProvider(builder, element, parserContext);
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(this.getGatewayClassName(element));
String uri = element.getAttribute("uri");
String destinationProvider = element.getAttribute("destination-provider");
List<Element> uriVariableElements = DomUtils.getChildElementsByTagName(element, "uri-variable");
if (!(StringUtils.hasText(destinationProvider) ^ StringUtils.hasText(uri))) {
parserContext.getReaderContext().error(
"Exactly one of 'uri' or 'destination-provider' is required.", element);
}
if (StringUtils.hasText(destinationProvider)) {
if (!CollectionUtils.isEmpty(uriVariableElements)) {
parserContext.getReaderContext().error("No 'uri-variable' sub-elements are allowed when "
+ "a 'destination-provider' reference has been provided.", element);
}
builder.addConstructorArgReference(destinationProvider);
}
else {
builder.addConstructorArgValue(uri);
if (!CollectionUtils.isEmpty(uriVariableElements)) {
Map<String, String> uriVariableExpressions = new HashMap<String, String>();
for (Element uriVariableElement : uriVariableElements) {
String name = uriVariableElement.getAttribute("name");
String expression = uriVariableElement.getAttribute("expression");
uriVariableExpressions.put(name, expression);
}
builder.addPropertyValue("uriVariableExpressions", uriVariableExpressions);
}
}
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "ignore-empty-responses");
this.postProcessGateway(builder, element, parserContext);
return builder;
}
private void buildDestinationProvider(BeanDefinitionBuilder builder, Element element, ParserContext parserContext) {
String uri = element.getAttribute("uri");
String destinationProvider = element.getAttribute("destination-provider");
if (!(StringUtils.hasText(destinationProvider) ^ StringUtils.hasText(uri))) {
parserContext.getReaderContext().error("Exactly one of 'uri' or 'destination-provider' is required.", element);
return;
}
if (StringUtils.hasText(destinationProvider)) {
builder.addConstructorArgReference(destinationProvider);
}
else {
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addGenericArgumentValue(uri);
builder.addConstructorArgValue(new RootBeanDefinition(
BASE_PACKAGE +".config.FixedUriDestinationProvider", cavs, null));
}
}
@Override
protected void postProcessGateway(BeanDefinitionBuilder builder, Element element, ParserContext parserContext) {
String marshallerRef = element.getAttribute("marshaller");

View File

@@ -26,9 +26,10 @@
Defines a Web Service based outbound Messaging Gateway.
</xsd:documentation>
</xsd:annotation>
<xsd:all>
<xsd:sequence>
<xsd:element ref="integration:poller" minOccurs="0" maxOccurs="1"/>
</xsd:all>
<xsd:element name="uri-variable" type="uriVariableType" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
@@ -64,10 +65,13 @@
</xsd:attribute>
<xsd:attribute name="uri" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
<xsd:documentation><![CDATA[
The Destination URI for this Web Service Gateway. If the URI should be determined at runtime
(e.g. registry lookup), then configure a 'destination-provider' reference instead.
</xsd:documentation>
(e.g. registry lookup), then configure a 'destination-provider' reference instead. Aternatively,
this URI may include {placeholders} whose values are determined by evaluating SpEL expressions
provided via 'uri-variable' sub-elements. The root object for those evaluations is the actual
request Message at runtime, i.e. you can access its payload or headers in the expression.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="destination-provider" type="xsd:string">
@@ -203,6 +207,31 @@
</xsd:complexType>
</xsd:element>
<xsd:complexType name="uriVariableType">
<xsd:annotation>
<xsd:documentation><![CDATA[
Expression to be evaluated against the Message to replace a URI {placeholder} with the evaluation result.
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="name" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
Name of the placeholder to be replaced.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="expression" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
Expression to be evaluated to determine the replacement value.
The Message is the root object of the expression, therefore
the 'payload' and 'headers' are available directly. Any bean
may be resolved if the bean name is preceded with '@'.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:element name="inbound-gateway">
<xsd:complexType>
<xsd:annotation>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ws="http://www.springframework.org/schema/integration/ws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/ws
http://www.springframework.org/schema/integration/ws/spring-integration-ws.xsd">
<ws:outbound-gateway id="gateway" request-channel="input" uri="http://localhost/test/{foo}/{bar}" interceptor="interceptor">
<ws:uri-variable name="foo" expression="payload.substring(1,4)"/>
<ws:uri-variable name="bar" expression="headers.bar"/>
</ws:outbound-gateway>
<bean id="interceptor" class="org.springframework.integration.ws.config.UriVariableTests$TestClientInterceptor"/>
</beans>

View File

@@ -0,0 +1,103 @@
/*
* Copyright 2002-2011 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.ws.config;
import static org.junit.Assert.assertEquals;
import java.net.URI;
import java.net.URISyntaxException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.MessageHandlingException;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.ws.client.WebServiceClientException;
import org.springframework.ws.client.WebServiceIOException;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.transport.context.TransportContext;
import org.springframework.ws.transport.context.TransportContextHolder;
import org.springframework.ws.transport.http.HttpUrlConnection;
/**
* @author Mark Fisher
* @since 2.1
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class UriVariableTests {
@Autowired
private ApplicationContext context;
@Test
public void checkUriVariables() {
MessageChannel input = context.getBean("input", MessageChannel.class);
TestClientInterceptor interceptor = context.getBean("interceptor", TestClientInterceptor.class);
Message<?> message = MessageBuilder.withPayload("<FOO/>").setHeader("bar", "BAR").build();
try {
input.send(message);
}
catch (MessageHandlingException e) {
// expected
assertEquals(WebServiceIOException.class, e.getCause().getClass());
}
assertEquals("http://localhost/test/FOO/BAR", interceptor.getLastUri().toString());
}
private static class TestClientInterceptor implements ClientInterceptor {
private URI lastUri;
private URI getLastUri() {
return this.lastUri;
}
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
TransportContext tc = TransportContextHolder.getTransportContext();
if (tc != null && tc.getConnection() instanceof HttpUrlConnection) {
try {
this.lastUri = ((HttpUrlConnection) tc.getConnection()).getUri();
}
catch (URISyntaxException e) {
throw new IllegalStateException(e);
}
}
else {
throw new IllegalStateException("expected HttpUrlConnection as TransportContext");
}
return false;
}
public boolean handleResponse(MessageContext messageContext) throws WebServiceClientException {
return false;
}
public boolean handleFault(MessageContext messageContext) throws WebServiceClientException {
return false;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -17,6 +17,7 @@
package org.springframework.integration.ws.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import org.junit.Test;
@@ -337,20 +338,22 @@ public class WebServiceOutboundGatewayParserTests {
assertEquals(messageFactory, templateAccessor.getPropertyValue("messageFactory"));
}
@Test
@Test
public void simpleGatewayWithDestinationProvider() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"simpleWebServiceOutboundGatewayParserTests.xml", this.getClass());
AbstractEndpoint endpoint = (AbstractEndpoint) context.getBean("gatewayWithDestinationProvider");
assertEquals(EventDrivenConsumer.class, endpoint.getClass());
Object gateway = new DirectFieldAccessor(endpoint).getPropertyValue("handler");
StubDestinationProvider stubProvider = (StubDestinationProvider) context.getBean("destinationProvider");
assertEquals(SimpleWebServiceOutboundGateway.class, gateway.getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(gateway);
Object destinationProviderObject = new DirectFieldAccessor(
accessor.getPropertyValue("webServiceTemplate")).getPropertyValue("destinationProvider");
StubDestinationProvider stubProvider = (StubDestinationProvider)context.getBean("destinationProvider");
assertEquals("Wrong DestinationProvider", stubProvider, destinationProviderObject );
}
assertEquals("Wrong DestinationProvider", stubProvider, accessor.getPropertyValue("destinationProvider"));
assertNull(accessor.getPropertyValue("uriTemplate"));
Object destinationProviderObject = new DirectFieldAccessor(
accessor.getPropertyValue("webServiceTemplate")).getPropertyValue("destinationProvider");
assertEquals("Wrong DestinationProvider", stubProvider,destinationProviderObject);
}
@Test(expected = BeanDefinitionParsingException.class)
public void invalidGatewayWithBothUriAndDestinationProvider() {