INT-2720: UriTemplate Support for S-WS Transports

Remove deprecation in the WS module

JIRA: https://jira.springsource.org/browse/INT-2720
      https://jira.springsource.org/browse/INT-2530

INT-2720: Polishing after rebase

INT-2720: Add a note to the Reference Manual

Polishing <authorgroup> to avoid extra whitespace before name

INT-2720: Pr comments & polishing

* Revert removed public API
* Revert tabs in What's new
* Change real URL to fake to allow for tests to work off-line
* Add smackx dependency to avoid error messages in logs
This commit is contained in:
Artem Bilan
2012-08-27 17:59:06 +03:00
committed by Gary Russell
parent 7d99a9a07a
commit 6b7ae6ceed
11 changed files with 332 additions and 166 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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,31 +17,24 @@
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 javax.xml.transform.TransformerException;
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.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.expression.ExpressionUtils;
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
import org.springframework.integration.support.MessageBuilder;
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;
@@ -61,6 +54,7 @@ import org.springframework.xml.transform.TransformerObjectSupport;
* @author Jonas Partner
* @author Oleg Zhurakousky
* @author Gary Russell
* @author Artem Bilan
*/
public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyProducingMessageHandler {
@@ -72,7 +66,7 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
private final Map<String, Expression> uriVariableExpressions = new HashMap<String, Expression>();
private final StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
private volatile StandardEvaluationContext evaluationContext;
private volatile WebServiceMessageCallback requestCallback;
@@ -82,30 +76,14 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
public AbstractWebServiceOutboundGateway(final String uri, WebServiceMessageFactory messageFactory) {
Assert.hasText(uri, "URI must not be empty");
this.webServiceTemplate = (messageFactory != null) ?
new WebServiceTemplate(messageFactory) : new WebServiceTemplate();
if (uri.toLowerCase().startsWith("http")) {
this.uriTemplate = new HttpUrlTemplate(uri);
this.destinationProvider = null;
}
else {
this.uriTemplate = null;
this.destinationProvider = new DestinationProvider() {
private volatile URI cachedUri;
public URI getDestination() {
if (this.cachedUri == null) {
this.cachedUri = URI.create(uri);
}
return this.cachedUri;
}
};
}
this.webServiceTemplate = new WebServiceTemplate(messageFactory);
this.destinationProvider = null;
this.uriTemplate = new UriTemplate(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.webServiceTemplate = new WebServiceTemplate(messageFactory);
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:
@@ -157,29 +135,25 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
this.webServiceTemplate.setMessageSender(messageSender);
}
public void setMessageSenders(WebServiceMessageSender[] messageSenders) {
public void setMessageSenders(WebServiceMessageSender... messageSenders) {
this.webServiceTemplate.setMessageSenders(messageSenders);
}
public void setInterceptors(ClientInterceptor[] interceptors) {
public void setInterceptors(ClientInterceptor... interceptors) {
this.webServiceTemplate.setInterceptors(interceptors);
}
@Override
public void onInit() {
super.onInit();
BeanFactory beanFactory = this.getBeanFactory();
if (beanFactory != null) {
this.evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
if (this.getBeanFactory() != null) {
this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(this.getBeanFactory());
}
ConversionService conversionService = this.getConversionService();
if (conversionService != null) {
this.evaluationContext.setTypeConverter(new StandardTypeConverter(conversionService));
else {
this.evaluationContext = ExpressionUtils.createStandardEvaluationContext();
}
this.evaluationContext.addPropertyAccessor(new MapAccessor());
Assert.state(this.destinationProvider != null ? CollectionUtils.isEmpty(this.uriVariableExpressions) : true,
"uri variables are not supported when a DestinationProvider is supplied, or the uri " +
"scheme is not http: or https:");
Assert.state(this.destinationProvider == null || CollectionUtils.isEmpty(this.uriVariableExpressions),
"uri variables are not supported when a DestinationProvider is supplied.");
}
protected WebServiceTemplate getWebServiceTemplate() {
@@ -188,7 +162,7 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
@Override
public final Object handleRequestMessage(Message<?> requestMessage) {
URI uri = prepareUri(requestMessage);
URI uri = this.prepareUri(requestMessage);
if (uri == null) {
throw new MessageDeliveryException(requestMessage, "Failed to determine URI for " +
"Web Service request in outbound gateway: " + this.getComponentName());
@@ -222,6 +196,7 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
protected abstract class RequestMessageCallback extends TransformerObjectSupport implements WebServiceMessageCallback {
private final WebServiceMessageCallback requestCallback;
private final Message<?> requestMessage;
public RequestMessageCallback(WebServiceMessageCallback requestCallback, Message<?> requestMessage){
@@ -233,15 +208,17 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
Object payload = this.requestMessage.getPayload();
if (message instanceof SoapMessage){
this.doWithMessageInternal(message, payload);
headerMapper.fromHeadersToRequest(this.requestMessage.getHeaders(), (SoapMessage)message);
if (requestCallback != null) {
requestCallback.doWithMessage(message);
}
AbstractWebServiceOutboundGateway.this.headerMapper.fromHeadersToRequest(this.requestMessage.getHeaders(),
(SoapMessage) message);
if (this.requestCallback != null) {
this.requestCallback.doWithMessage(message);
}
}
}
public abstract void doWithMessageInternal(WebServiceMessage message, Object payload) throws IOException, TransformerException;
}
protected abstract class ResponseMessageExtractor extends TransformerObjectSupport implements WebServiceMessageExtractor<Object> {
@@ -251,10 +228,10 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
Object resultObject = this.doExtractData(message);
if (message instanceof SoapMessage){
Map<String, Object> mappedMessageHeaders = headerMapper.toHeadersFromReply((SoapMessage) message);
Message<?> siMessage = MessageBuilder.withPayload(resultObject).copyHeaders(mappedMessageHeaders).build();
return siMessage;
if (message instanceof SoapMessage){
Map<String, Object> mappedMessageHeaders =
AbstractWebServiceOutboundGateway.this.headerMapper.toHeadersFromReply((SoapMessage) message);
return MessageBuilder.withPayload(resultObject).copyHeaders(mappedMessageHeaders).build();
}
else {
return resultObject;
@@ -262,34 +239,7 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
}
public abstract Object doExtractData(WebServiceMessage message) throws IOException, TransformerException;
}
/**
* 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);
}
@SuppressWarnings("deprecation")
@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-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -20,9 +20,7 @@ import java.util.List;
import org.w3c.dom.Element;
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.ManagedMap;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.ExpressionFactoryBean;
@@ -32,6 +30,8 @@ import org.springframework.integration.ws.DefaultSoapHeaderMapper;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.springframework.integration.ws.MarshallingWebServiceOutboundGateway;
import org.springframework.integration.ws.SimpleWebServiceOutboundGateway;
/**
* Parser for the &lt;outbound-gateway/&gt; element in the 'ws' namespace.
@@ -39,18 +39,15 @@ import org.springframework.util.xml.DomUtils;
* @author Mark Fisher
* @author Jonas Partner
* @author Gunnar Hillert
* @author Artem Bilan
*
*/
public class WebServiceOutboundGatewayParser extends AbstractOutboundGatewayParser {
private static final String BASE_PACKAGE = "org.springframework.integration.ws";
@Override
protected String getGatewayClassName(Element element) {
String simpleClassName = (StringUtils.hasText(element.getAttribute("marshaller"))) ?
"MarshallingWebServiceOutboundGateway" : "SimpleWebServiceOutboundGateway";
return BASE_PACKAGE + "." + simpleClassName;
return ((StringUtils.hasText(element.getAttribute("marshaller"))) ?
MarshallingWebServiceOutboundGateway.class : SimpleWebServiceOutboundGateway.class).getName();
}
@Override
@@ -117,14 +114,9 @@ public class WebServiceOutboundGatewayParser extends AbstractOutboundGatewayPars
if (StringUtils.hasText(messageFactoryRef)) {
builder.addConstructorArgReference(messageFactoryRef);
}
String requestCallbackRef = element.getAttribute("request-callback");
if (StringUtils.hasText(requestCallbackRef)) {
builder.addPropertyReference("requestCallback", requestCallbackRef);
}
String faultMessageResolverRef = element.getAttribute("fault-message-resolver");
if (StringUtils.hasText(faultMessageResolverRef)) {
builder.addPropertyReference("faultMessageResolver", faultMessageResolverRef);
}
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "request-callback");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "fault-message-resolver");
String messageSenderRef = element.getAttribute("message-sender");
String messageSenderListRef = element.getAttribute("message-senders");
if (StringUtils.hasText(messageSenderRef) && StringUtils.hasText(messageSenderListRef)) {
@@ -144,9 +136,7 @@ public class WebServiceOutboundGatewayParser extends AbstractOutboundGatewayPars
"Only one of interceptor or interceptors should be specified.", element);
}
if (StringUtils.hasText(interceptorRef)) {
ManagedList<RuntimeBeanReference> interceptors = new ManagedList<RuntimeBeanReference>();
interceptors.add(new RuntimeBeanReference(interceptorRef));
builder.addPropertyValue("interceptors", interceptors);
builder.addPropertyReference("interceptors", interceptorRef);
}
if (StringUtils.hasText(interceptorListRef)) {
builder.addPropertyReference("interceptors", interceptorListRef);