HeaderMapper refactoring
INT-2083 added outbound namespace support for XMPP header mapper INT-2083 added inbound namespace support for XMPP header mapper INT-2083 polished XMPP inbound/outbound header mappings, added namespace support for AMQP inbound adapter/gateway header mappings INT-2083 added support and tests for AMQP outbound gateways and adapters INT-2083 polishing and adding more tests for AMQP support for header mappings INT-2083 polishing AMQP and XMPP header mappings, generalized headerMapper configuration in IntegrationNamespaceUtils.configureHeaderMapper(..) method INT-2803 added headermapping support to WS outbound gateways INT-2803 polishing INT-2083 refactored SimpleWebServiceOutboundGateway, added full request/reply test INT-2083 polished MarshallingWebServiceOutboundGateway to add marshalling callback handlers, added test for marshalling call INT-2083 polishing based on PR comments INT-2083 interim commit INT-2083 added RequestReplyHeaderMapper startegy and migrated AMQP Header Mapper to use it INT-2083 migrated WS and XMPP to use a new RequestReplyHeaderMapper strategy INT-2083 polishing with PR comments INT-2083 polishing removed introspection method, simplified things INT-2083 polishing based on recent PR comments INT-2083 interim commit INT-2083 polishing WS module INT-2083 refactored to make sure that Soap action header is set within HeaderMapper INT-2083 polishing ensured the Soap header is set to default value if not provided INT-2083 polishing, putting tests back
This commit is contained in:
@@ -21,14 +21,12 @@ import org.springframework.expression.ExpressionException;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.gateway.MessagingGatewaySupport;
|
||||
import org.springframework.integration.mapping.HeaderMapper;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.server.endpoint.MessageEndpoint;
|
||||
import org.springframework.ws.soap.SoapHeader;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
|
||||
/**
|
||||
@@ -37,13 +35,13 @@ import org.springframework.ws.soap.SoapMessage;
|
||||
*/
|
||||
abstract public class AbstractWebServiceInboundGateway extends MessagingGatewaySupport implements MessageEndpoint {
|
||||
|
||||
protected volatile HeaderMapper<SoapHeader> headerMapper = new DefaultSoapHeaderMapper();
|
||||
protected volatile SoapHeaderMapper headerMapper = new DefaultSoapHeaderMapper();
|
||||
|
||||
public String getComponentType() {
|
||||
return "ws:outbound-gateway";
|
||||
return "ws:inbound-gateway";
|
||||
}
|
||||
|
||||
public void setHeaderMapper(HeaderMapper<SoapHeader> headerMapper) {
|
||||
public void setHeaderMapper(SoapHeaderMapper headerMapper) {
|
||||
Assert.notNull(headerMapper, "headerMapper must not be null");
|
||||
this.headerMapper = headerMapper;
|
||||
}
|
||||
@@ -73,7 +71,7 @@ abstract public class AbstractWebServiceInboundGateway extends MessagingGatewayS
|
||||
}
|
||||
if (request instanceof SoapMessage) {
|
||||
SoapMessage soapMessage = (SoapMessage) request;
|
||||
Map<String, ?> headers = this.headerMapper.toHeaders(soapMessage.getSoapHeader());
|
||||
Map<String, ?> headers = this.headerMapper.toHeadersFromRequest(soapMessage);
|
||||
if (!CollectionUtils.isEmpty(headers)) {
|
||||
builder.copyHeaders(headers);
|
||||
}
|
||||
@@ -82,8 +80,8 @@ abstract public class AbstractWebServiceInboundGateway extends MessagingGatewayS
|
||||
|
||||
protected void toSoapHeaders(WebServiceMessage response, Message<?> replyMessage){
|
||||
if (response instanceof SoapMessage) {
|
||||
this.headerMapper.fromHeaders(
|
||||
replyMessage.getHeaders(), ((SoapMessage) response).getSoapHeader());
|
||||
this.headerMapper.fromHeadersToReply(
|
||||
replyMessage.getHeaders(), (SoapMessage) response);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ 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;
|
||||
@@ -33,8 +35,8 @@ 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.integration.support.MessageBuilder;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.UriTemplate;
|
||||
@@ -43,12 +45,13 @@ import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.ws.WebServiceMessageFactory;
|
||||
import org.springframework.ws.client.core.FaultMessageResolver;
|
||||
import org.springframework.ws.client.core.WebServiceMessageCallback;
|
||||
import org.springframework.ws.client.core.WebServiceMessageExtractor;
|
||||
import org.springframework.ws.client.core.WebServiceTemplate;
|
||||
import org.springframework.ws.client.support.destination.DestinationProvider;
|
||||
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
import org.springframework.ws.soap.client.core.SoapActionCallback;
|
||||
import org.springframework.ws.transport.WebServiceMessageSender;
|
||||
import org.springframework.xml.transform.TransformerObjectSupport;
|
||||
|
||||
/**
|
||||
* Base class for outbound Web Service-invoking Messaging Gateways.
|
||||
@@ -71,7 +74,8 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
|
||||
private volatile WebServiceMessageCallback requestCallback;
|
||||
|
||||
private volatile boolean ignoreEmptyResponses = true;
|
||||
|
||||
|
||||
protected volatile SoapHeaderMapper headerMapper = new DefaultSoapHeaderMapper();
|
||||
|
||||
public AbstractWebServiceOutboundGateway(String uri, WebServiceMessageFactory messageFactory) {
|
||||
Assert.hasText(uri, "URI must not be empty");
|
||||
@@ -92,6 +96,9 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
|
||||
this.uriTemplate = null;
|
||||
}
|
||||
|
||||
public void setHeaderMapper(SoapHeaderMapper headerMapper) {
|
||||
this.headerMapper = headerMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Map of URI variable expressions to evaluate against the outbound message
|
||||
@@ -160,13 +167,13 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Object handleRequestMessage(Message<?> message) {
|
||||
URI uri = prepareUri(message);
|
||||
public final Object handleRequestMessage(Message<?> requestMessage) {
|
||||
URI uri = prepareUri(requestMessage);
|
||||
if (uri == null) {
|
||||
throw new MessageDeliveryException(message, "Failed to determine URI for " +
|
||||
throw new MessageDeliveryException(requestMessage, "Failed to determine URI for " +
|
||||
"Web Service request in outbound gateway: " + this.getComponentName());
|
||||
}
|
||||
Object responsePayload = this.doHandle(uri.toString(), message.getPayload(), this.getRequestCallback(message));
|
||||
Object responsePayload = this.doHandle(uri.toString(), requestMessage, this.requestCallback);
|
||||
if (responsePayload != null) {
|
||||
boolean shouldIgnore = (this.ignoreEmptyResponses
|
||||
&& responsePayload instanceof String && !StringUtils.hasText((String) responsePayload));
|
||||
@@ -177,7 +184,7 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract Object doHandle(String uri, Object requestPayload, WebServiceMessageCallback requestCallback);
|
||||
protected abstract Object doHandle(String uri, Message<?> requestMessage, WebServiceMessageCallback requestCallback);
|
||||
|
||||
|
||||
private URI prepareUri(Message<?> requestMessage) {
|
||||
@@ -191,39 +198,51 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
|
||||
}
|
||||
return this.uriTemplate.expand(uriVariables);
|
||||
}
|
||||
|
||||
private WebServiceMessageCallback getRequestCallback(Message<?> requestMessage) {
|
||||
String soapAction = requestMessage.getHeaders().get(WebServiceHeaders.SOAP_ACTION, String.class);
|
||||
return (soapAction != null) ?
|
||||
new TypeCheckingSoapActionCallback(soapAction, this.requestCallback) : this.requestCallback;
|
||||
}
|
||||
|
||||
|
||||
private static class TypeCheckingSoapActionCallback extends SoapActionCallback {
|
||||
|
||||
private final WebServiceMessageCallback callbackDelegate;
|
||||
|
||||
TypeCheckingSoapActionCallback(String soapAction, WebServiceMessageCallback callbackDelegate) {
|
||||
super(soapAction);
|
||||
this.callbackDelegate = callbackDelegate;
|
||||
|
||||
protected abstract class RequestMessageCallback extends TransformerObjectSupport implements WebServiceMessageCallback {
|
||||
|
||||
private final WebServiceMessageCallback requestCallback;
|
||||
private final Message<?> requestMessage;
|
||||
|
||||
public RequestMessageCallback(WebServiceMessageCallback requestCallback, Message<?> requestMessage){
|
||||
this.requestCallback = requestCallback;
|
||||
this.requestMessage = requestMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWithMessage(WebServiceMessage message) throws IOException {
|
||||
if (message instanceof SoapMessage) {
|
||||
super.doWithMessage(message);
|
||||
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (this.callbackDelegate != null) {
|
||||
try {
|
||||
this.callbackDelegate.doWithMessage(message);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new MessagingException("error occurred in WebServiceMessageCallback", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public abstract void doWithMessageInternal(WebServiceMessage message, Object payload) throws IOException, TransformerException;
|
||||
}
|
||||
|
||||
protected abstract class ResponseMessageExtractor extends TransformerObjectSupport implements WebServiceMessageExtractor<Object> {
|
||||
|
||||
public Object extractData(WebServiceMessage message)
|
||||
throws IOException, TransformerException {
|
||||
|
||||
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;
|
||||
}
|
||||
else {
|
||||
return message.getPayloadSource();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Object doExtractData(WebServiceMessage message) throws IOException, TransformerException;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* HTTP-specific subclass of UriTemplate, overriding the encode method.
|
||||
|
||||
@@ -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,19 +16,21 @@
|
||||
|
||||
package org.springframework.integration.ws;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import org.springframework.integration.MessageHeaders;
|
||||
import org.springframework.integration.mapping.AbstractHeaderMapper;
|
||||
import org.springframework.integration.mapping.HeaderMapper;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.ws.soap.SoapHeader;
|
||||
import org.springframework.ws.soap.SoapHeaderElement;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
import org.springframework.xml.namespace.QNameUtils;
|
||||
|
||||
/**
|
||||
@@ -41,85 +43,77 @@ import org.springframework.xml.namespace.QNameUtils;
|
||||
* one should implement the HeaderMapper interface directly.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
public class DefaultSoapHeaderMapper implements HeaderMapper<SoapHeader> {
|
||||
public class DefaultSoapHeaderMapper extends AbstractHeaderMapper<SoapMessage> implements SoapHeaderMapper {
|
||||
|
||||
private static final List<String> STANDARD_HEADER_NAMES = new ArrayList<String>();
|
||||
|
||||
private volatile String[] outboundHeaderNames = new String[0];
|
||||
|
||||
private volatile String[] inboundHeaderNames = new String[] { "*" };
|
||||
|
||||
|
||||
public void setOutboundHeaderNames(String[] outboundHeaderNames) {
|
||||
this.outboundHeaderNames = (outboundHeaderNames != null) ? outboundHeaderNames : new String[0];
|
||||
static {
|
||||
STANDARD_HEADER_NAMES.add(WebServiceHeaders.SOAP_ACTION);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> extractStandardHeaders(SoapMessage source) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
public void setInboundHeaderNames(String[] inboundHeaderNames) {
|
||||
this.inboundHeaderNames = (inboundHeaderNames != null) ? inboundHeaderNames : new String[0];
|
||||
}
|
||||
|
||||
public void fromHeaders(MessageHeaders headers, SoapHeader target) {
|
||||
if (target != null && !CollectionUtils.isEmpty(headers)) {
|
||||
for (String headerName : headers.keySet()) {
|
||||
if (this.shouldMapOutboundHeader(headerName)) {
|
||||
Object value = headers.get(headerName);
|
||||
if (value instanceof String) {
|
||||
QName qname = QNameUtils.parseQNameString(headerName);
|
||||
target.addAttribute(qname, (String) value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> toHeaders(SoapHeader source) {
|
||||
@Override
|
||||
protected Map<String, Object> extractUserDefinedHeaders(SoapMessage source) {
|
||||
SoapHeader soapHeader = source.getSoapHeader();
|
||||
Map<String, Object> headers = new HashMap<String, Object>();
|
||||
if (source != null) {
|
||||
Iterator<?> attributeIter = source.getAllAttributes();
|
||||
Iterator<?> attributeIter = soapHeader.getAllAttributes();
|
||||
while (attributeIter.hasNext()) {
|
||||
Object name = attributeIter.next();
|
||||
if (name instanceof QName) {
|
||||
String qnameString = QNameUtils.toQualifiedName((QName) name);
|
||||
if (this.shouldMapInboundHeader(qnameString)) {
|
||||
String value = source.getAttributeValue((QName) name);
|
||||
if (value != null) {
|
||||
headers.put(qnameString, value);
|
||||
}
|
||||
String value = soapHeader.getAttributeValue((QName) name);
|
||||
if (value != null) {
|
||||
headers.put(qnameString, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
Iterator<?> elementIter = source.examineAllHeaderElements();
|
||||
Iterator<?> elementIter = soapHeader.examineAllHeaderElements();
|
||||
while (elementIter.hasNext()) {
|
||||
Object element = elementIter.next();
|
||||
if (element instanceof SoapHeaderElement) {
|
||||
QName qname = ((SoapHeaderElement) element).getName();
|
||||
String qnameString = QNameUtils.toQualifiedName(qname);
|
||||
if (this.shouldMapInboundHeader(qnameString)) {
|
||||
headers.put(qnameString, element);
|
||||
}
|
||||
headers.put(qnameString, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
private boolean shouldMapInboundHeader(String headerName) {
|
||||
return matchesAny(this.inboundHeaderNames, headerName);
|
||||
@Override
|
||||
protected void populateStandardHeaders(Map<String, Object> headers, SoapMessage target) {
|
||||
String soapAction = getHeaderIfAvailable(headers, WebServiceHeaders.SOAP_ACTION, String.class);
|
||||
if (!StringUtils.hasText(soapAction)) {
|
||||
soapAction = "\"\"";
|
||||
}
|
||||
target.setSoapAction(soapAction);
|
||||
}
|
||||
|
||||
private boolean shouldMapOutboundHeader(String headerName) {
|
||||
return matchesAny(this.outboundHeaderNames, headerName);
|
||||
}
|
||||
|
||||
private static boolean matchesAny(String[] patterns, String candidate) {
|
||||
if (!ObjectUtils.isEmpty(patterns) && QNameUtils.validateQName(candidate)) {
|
||||
for (String pattern : patterns) {
|
||||
if (PatternMatchUtils.simpleMatch(pattern, candidate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void populateUserDefinedHeader(String headerName, Object headerValue, SoapMessage target) {
|
||||
SoapHeader soapHeader = target.getSoapHeader();
|
||||
if (headerValue instanceof String) {
|
||||
QName qname = QNameUtils.parseQNameString(headerName);
|
||||
soapHeader.addAttribute(qname, (String) headerValue);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getStandardRequestHeaderNames() {
|
||||
return STANDARD_HEADER_NAMES;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getStandardHeaderPrefix() {
|
||||
return WebServiceHeaders.PREFIX;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,22 +16,31 @@
|
||||
|
||||
package org.springframework.integration.ws;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.oxm.Marshaller;
|
||||
import org.springframework.oxm.Unmarshaller;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.ws.WebServiceMessageFactory;
|
||||
import org.springframework.ws.client.core.WebServiceMessageCallback;
|
||||
import org.springframework.ws.client.support.destination.DestinationProvider;
|
||||
import org.springframework.ws.support.MarshallingUtils;
|
||||
|
||||
/**
|
||||
* An outbound Messaging Gateway for invoking Web Services that also supports
|
||||
* marshalling and unmarshalling of the request and response messages.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @see Marshaller
|
||||
* @see Unmarshaller
|
||||
*/
|
||||
public class MarshallingWebServiceOutboundGateway extends AbstractWebServiceOutboundGateway {
|
||||
|
||||
private volatile Marshaller marshaller;
|
||||
private volatile Unmarshaller unmarshaller;
|
||||
|
||||
public MarshallingWebServiceOutboundGateway(DestinationProvider destinationProvider, Marshaller marshaller, Unmarshaller unmarshaller, WebServiceMessageFactory messageFactory) {
|
||||
super(destinationProvider, messageFactory);
|
||||
@@ -43,8 +52,7 @@ public class MarshallingWebServiceOutboundGateway extends AbstractWebServiceOutb
|
||||
}
|
||||
|
||||
public MarshallingWebServiceOutboundGateway(DestinationProvider destinationProvider, Marshaller marshaller, WebServiceMessageFactory messageFactory) {
|
||||
super(destinationProvider, messageFactory);
|
||||
this.configureMarshallers(marshaller);
|
||||
this(destinationProvider, marshaller, null, messageFactory);
|
||||
}
|
||||
|
||||
public MarshallingWebServiceOutboundGateway(DestinationProvider destinationProvider, Marshaller marshaller) {
|
||||
@@ -61,8 +69,7 @@ public class MarshallingWebServiceOutboundGateway extends AbstractWebServiceOutb
|
||||
}
|
||||
|
||||
public MarshallingWebServiceOutboundGateway(String uri, Marshaller marshaller, WebServiceMessageFactory messageFactory) {
|
||||
super(uri, messageFactory);
|
||||
this.configureMarshallers(marshaller);
|
||||
this(uri, marshaller, null, messageFactory);
|
||||
}
|
||||
|
||||
public MarshallingWebServiceOutboundGateway(String uri, Marshaller marshaller) {
|
||||
@@ -76,28 +83,43 @@ public class MarshallingWebServiceOutboundGateway extends AbstractWebServiceOutb
|
||||
*/
|
||||
private void configureMarshallers(Marshaller marshaller, Unmarshaller unmarshaller) {
|
||||
Assert.notNull(marshaller, "marshaller must not be null");
|
||||
if (unmarshaller == 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.");
|
||||
unmarshaller = (Unmarshaller) marshaller;
|
||||
}
|
||||
|
||||
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);
|
||||
this.marshaller = marshaller;
|
||||
this.unmarshaller = unmarshaller;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doHandle(String uri, Object requestPayload, WebServiceMessageCallback requestCallback) {
|
||||
return this.getWebServiceTemplate().marshalSendAndReceive(uri, requestPayload, requestCallback);
|
||||
protected Object doHandle(String uri, Message<?> requestMessage, WebServiceMessageCallback requestCallback) {
|
||||
Object reply = this.getWebServiceTemplate().sendAndReceive(uri,
|
||||
new MarshallingRequestMessageCallback(requestCallback, requestMessage), new MarshallingResponseMessageExtractor());
|
||||
return reply;
|
||||
}
|
||||
|
||||
private class MarshallingRequestMessageCallback extends RequestMessageCallback {
|
||||
|
||||
public MarshallingRequestMessageCallback(WebServiceMessageCallback requestCallback, Message<?> requestMessage){
|
||||
super(requestCallback, requestMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWithMessageInternal(WebServiceMessage message, Object payload) throws IOException{
|
||||
MarshallingUtils.marshal(marshaller, payload, message);
|
||||
}
|
||||
}
|
||||
|
||||
private class MarshallingResponseMessageExtractor extends ResponseMessageExtractor {
|
||||
|
||||
@Override
|
||||
public Object doExtractData(WebServiceMessage message) throws IOException{
|
||||
return MarshallingUtils.unmarshal(unmarshaller, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.integration.ws;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
@@ -25,7 +26,10 @@ import javax.xml.transform.dom.DOMSource;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.ws.WebServiceMessageFactory;
|
||||
import org.springframework.ws.client.core.SourceExtractor;
|
||||
import org.springframework.ws.client.core.WebServiceMessageCallback;
|
||||
@@ -41,10 +45,9 @@ import org.springframework.xml.transform.TransformerObjectSupport;
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public class SimpleWebServiceOutboundGateway extends AbstractWebServiceOutboundGateway {
|
||||
|
||||
|
||||
private final SourceExtractor<?> sourceExtractor;
|
||||
|
||||
|
||||
public SimpleWebServiceOutboundGateway(DestinationProvider destinationProvider) {
|
||||
this(destinationProvider, null, null);
|
||||
}
|
||||
@@ -73,30 +76,92 @@ public class SimpleWebServiceOutboundGateway extends AbstractWebServiceOutboundG
|
||||
|
||||
|
||||
@Override
|
||||
protected Object doHandle(String uri, Object requestPayload, WebServiceMessageCallback requestCallback) {
|
||||
if (requestPayload instanceof Source) {
|
||||
return this.getWebServiceTemplate().sendSourceAndReceive(
|
||||
uri, (Source) requestPayload, requestCallback, this.sourceExtractor);
|
||||
}
|
||||
protected Object doHandle(String uri, final Message<?> requestMessage, final WebServiceMessageCallback requestCallback) {
|
||||
Object requestPayload = requestMessage.getPayload();
|
||||
Result responseResultInstance = null;
|
||||
if (requestPayload instanceof String) {
|
||||
StringResult result = new StringResult();
|
||||
this.getWebServiceTemplate().sendSourceAndReceiveToResult(
|
||||
uri, new StringSource((String) requestPayload), requestCallback, result);
|
||||
return result.toString();
|
||||
responseResultInstance = new StringResult();
|
||||
}
|
||||
if (requestPayload instanceof Document) {
|
||||
DOMResult result = new DOMResult();
|
||||
this.getWebServiceTemplate().sendSourceAndReceiveToResult(
|
||||
uri, new DOMSource((Document) requestPayload), requestCallback, result);
|
||||
return result.getNode();
|
||||
else if (requestPayload instanceof Document) {
|
||||
responseResultInstance = new DOMResult();
|
||||
}
|
||||
throw new MessagingException("Unsupported payload type '" + requestPayload.getClass() +
|
||||
"'. " + this.getClass().getName() + " only supports 'java.lang.String', '" + Source.class.getName() +
|
||||
"', and '" + Document.class.getName() + "'. Consider either using the '"
|
||||
+ MarshallingWebServiceOutboundGateway.class.getName() + "' or a Message Transformer.");
|
||||
Object reply = this.getWebServiceTemplate().sendAndReceive(uri,
|
||||
new SimpleRequestMessageCallback(requestCallback, requestMessage), new SimpleResponseMessageExtractor(responseResultInstance));
|
||||
return reply;
|
||||
}
|
||||
|
||||
private class SimpleRequestMessageCallback extends RequestMessageCallback {
|
||||
|
||||
public SimpleRequestMessageCallback(WebServiceMessageCallback requestCallback, Message<?> requestMessage){
|
||||
super(requestCallback, requestMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWithMessageInternal(WebServiceMessage message, Object payload) throws IOException, TransformerException {
|
||||
Source source = this.extractSource(payload);
|
||||
this.transform(source, message.getPayloadResult());
|
||||
}
|
||||
|
||||
private Source extractSource(Object requestPayload) throws IOException, TransformerException{
|
||||
Source source = null;
|
||||
|
||||
if (requestPayload instanceof Source) {
|
||||
source = (Source) requestPayload;
|
||||
Object o = sourceExtractor.extractData(source);
|
||||
Assert.isInstanceOf(Source.class, o);
|
||||
source = (Source) o;
|
||||
}
|
||||
else if (requestPayload instanceof String) {
|
||||
source = new StringSource((String) requestPayload);
|
||||
}
|
||||
else if (requestPayload instanceof Document) {
|
||||
source = new DOMSource((Document) requestPayload);
|
||||
}
|
||||
else {
|
||||
throw new MessagingException("Unsupported payload type '" + requestPayload.getClass() +
|
||||
"'. " + this.getClass().getName() + " only supports 'java.lang.String', '" + Source.class.getName() +
|
||||
"', and '" + Document.class.getName() + "'. Consider either using the '"
|
||||
+ MarshallingWebServiceOutboundGateway.class.getName() + "' or a Message Transformer.");
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
}
|
||||
|
||||
private class SimpleResponseMessageExtractor extends ResponseMessageExtractor {
|
||||
|
||||
private final Result result;
|
||||
|
||||
public SimpleResponseMessageExtractor(Result result){
|
||||
super();
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object doExtractData(WebServiceMessage message) throws IOException, TransformerException{
|
||||
Source payloadSource = message.getPayloadSource();
|
||||
Object payload = null;
|
||||
|
||||
if (this.result != null){
|
||||
this.transform(payloadSource, this.result);
|
||||
if (this.result instanceof StringResult){
|
||||
payload = this.result.toString();
|
||||
}
|
||||
else if (this.result instanceof DOMResult){
|
||||
payload = ((DOMResult)this.result).getNode();
|
||||
}
|
||||
else {
|
||||
payload = this.result;
|
||||
}
|
||||
}
|
||||
else {
|
||||
payload = payloadSource;
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class DefaultSourceExtractor extends TransformerObjectSupport implements SourceExtractor<DOMSource> {
|
||||
|
||||
public DOMSource extractData(Source source) throws IOException, TransformerException {
|
||||
@@ -108,5 +173,4 @@ public class SimpleWebServiceOutboundGateway extends AbstractWebServiceOutboundG
|
||||
return new DOMSource(result.getNode());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package org.springframework.integration.ws;
|
||||
|
||||
import org.springframework.integration.mapping.HeaderMapper;
|
||||
import org.springframework.integration.mapping.RequestReplyHeaderMapper;
|
||||
import org.springframework.ws.soap.SoapHeader;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
|
||||
/**
|
||||
* A convenience interface that extends {@link HeaderMapper}
|
||||
* but parameterized with {@link SoapHeader}.
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.1
|
||||
*/
|
||||
public interface SoapHeaderMapper extends RequestReplyHeaderMapper<SoapMessage>{
|
||||
|
||||
}
|
||||
@@ -16,14 +16,15 @@
|
||||
|
||||
package org.springframework.integration.ws.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractInboundGatewayParser;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.ws.DefaultSoapHeaderMapper;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* @author Iwein Fuld
|
||||
@@ -66,12 +67,10 @@ public class WebServiceInboundGatewayParser extends AbstractInboundGatewayParser
|
||||
logger.warn("Setting 'extract-payload' attribute has no effect when used with a marshalling Web Service Inbound Gateway.");
|
||||
}
|
||||
}
|
||||
String headerMapperRef = element.getAttribute("header-mapper");
|
||||
if (StringUtils.hasText(headerMapperRef)) {
|
||||
Assert.isTrue(!StringUtils.hasText(marshallerRef),
|
||||
"The 'header-mapper' attribute cannot be used when a 'marshaller' is provided.");
|
||||
builder.addPropertyReference("headerMapper", headerMapperRef);
|
||||
}
|
||||
}
|
||||
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
super.doParse(element, parserContext, builder);
|
||||
IntegrationNamespaceUtils.configureHeaderMapper(element, builder, parserContext, DefaultSoapHeaderMapper.class, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.ExpressionFactoryBean;
|
||||
import org.springframework.integration.config.xml.AbstractOutboundGatewayParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.ws.DefaultSoapHeaderMapper;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
@@ -84,6 +85,9 @@ public class WebServiceOutboundGatewayParser extends AbstractOutboundGatewayPars
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "ignore-empty-responses");
|
||||
this.postProcessGateway(builder, element, parserContext);
|
||||
|
||||
IntegrationNamespaceUtils.configureHeaderMapper(element, builder, parserContext, DefaultSoapHeaderMapper.class, null);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
@@ -204,6 +204,38 @@
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="order" type="xsd:string"/>
|
||||
<xsd:attribute name="auto-startup" type="xsd:string" default="true"/>
|
||||
<xsd:attribute name="header-mapper">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Reference to a HeaderMapper<SoapHeader> implementation
|
||||
that this gateway will use to map between Spring Integration
|
||||
MessageHeaders and the SoapHeader.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.mapping.HeaderMapper"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="mapped-request-headers" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Comma-separated list of names of SOAP Headers to be mapped from the SOAP request into the MessageHeaders.
|
||||
This can only be provided if the 'header-mapper' reference is not being set directly. The values in
|
||||
this list can also be simple patterns to be matched against the header names (e.g. "foo*" or "*foo").
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="mapped-reply-headers" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Comma-separated list of names of MessageHeaders to be mapped into the SOAP Headers of the SOAP reply.
|
||||
This can only be provided if the 'header-mapper' reference is not being set directly. The values in
|
||||
this list can also be simple patterns to be matched against the header names (e.g. "foo*" or "*foo").
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
@@ -295,8 +327,7 @@
|
||||
<xsd:documentation>
|
||||
Reference to a HeaderMapper<SoapHeader> implementation
|
||||
that this gateway will use to map between Spring Integration
|
||||
MessageHeaders and the SoapHeader. This strategy can only be
|
||||
applied when a 'marshaller' is not being configured.
|
||||
MessageHeaders and the SoapHeader.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
@@ -305,6 +336,24 @@
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="mapped-request-headers" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Comma-separated list of names of SOAP Headers to be mapped from the SOAP request into the MessageHeaders.
|
||||
This can only be provided if the 'header-mapper' reference is not being set directly. The values in
|
||||
this list can also be simple patterns to be matched against the header names (e.g. "foo*" or "*foo").
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="mapped-reply-headers" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Comma-separated list of names of MessageHeaders to be mapped into the SOAP Headers of the SOAP reply.
|
||||
This can only be provided if the 'header-mapper' reference is not being set directly. The values in
|
||||
this list can also be simple patterns to be matched against the header names (e.g. "foo*" or "*foo").
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -25,6 +25,7 @@ import javax.xml.transform.Source;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
@@ -33,17 +34,17 @@ import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.MessageHeaders;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.history.MessageHistory;
|
||||
import org.springframework.integration.mapping.HeaderMapper;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.integration.ws.MarshallingWebServiceInboundGateway;
|
||||
import org.springframework.integration.ws.SimpleWebServiceInboundGateway;
|
||||
import org.springframework.integration.ws.SoapHeaderMapper;
|
||||
import org.springframework.oxm.Unmarshaller;
|
||||
import org.springframework.oxm.support.AbstractMarshaller;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.ws.context.DefaultMessageContext;
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.soap.SoapHeader;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
@@ -149,7 +150,7 @@ public class WebServiceInboundGatewayParserTests {
|
||||
assertNotNull(history);
|
||||
Properties componentHistoryRecord = TestUtils.locateComponentInHistory(history, "marshalling", 0);
|
||||
assertNotNull(componentHistoryRecord);
|
||||
assertEquals("ws:outbound-gateway", componentHistoryRecord.get("type"));
|
||||
assertEquals("ws:inbound-gateway", componentHistoryRecord.get("type"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -162,14 +163,14 @@ public class WebServiceInboundGatewayParserTests {
|
||||
Properties componentHistoryRecord = TestUtils.locateComponentInHistory(history, "extractsPayload", 0);
|
||||
System.out.println(componentHistoryRecord);
|
||||
assertNotNull(componentHistoryRecord);
|
||||
assertEquals("ws:outbound-gateway", componentHistoryRecord.get("type"));
|
||||
assertEquals("ws:inbound-gateway", componentHistoryRecord.get("type"));
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private SimpleWebServiceInboundGateway headerMappingGateway;
|
||||
|
||||
@Autowired
|
||||
private HeaderMapper<SoapHeader> testHeaderMapper;
|
||||
private SoapHeaderMapper testHeaderMapper;
|
||||
|
||||
@Test
|
||||
public void testHeaderMapperReference() throws Exception {
|
||||
@@ -180,12 +181,20 @@ public class WebServiceInboundGatewayParserTests {
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class TestHeaderMapper implements HeaderMapper<SoapHeader> {
|
||||
|
||||
public void fromHeaders(MessageHeaders headers, SoapHeader target) {
|
||||
private static class TestHeaderMapper implements SoapHeaderMapper {
|
||||
|
||||
public void fromHeadersToRequest(MessageHeaders headers,
|
||||
SoapMessage target) {
|
||||
}
|
||||
|
||||
public Map<String, ?> toHeaders(SoapHeader source) {
|
||||
public void fromHeadersToReply(MessageHeaders headers, SoapMessage target) {
|
||||
}
|
||||
|
||||
public Map<String, Object> toHeadersFromRequest(SoapMessage source) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
public Map<String, Object> toHeadersFromReply(SoapMessage source) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.integration.ws.config;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
@@ -28,6 +25,7 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.endpoint.AbstractEndpoint;
|
||||
import org.springframework.integration.endpoint.EventDrivenConsumer;
|
||||
import org.springframework.integration.endpoint.PollingConsumer;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.integration.ws.MarshallingWebServiceOutboundGateway;
|
||||
import org.springframework.integration.ws.SimpleWebServiceOutboundGateway;
|
||||
import org.springframework.oxm.Marshaller;
|
||||
@@ -40,6 +38,9 @@ import org.springframework.ws.client.core.WebServiceMessageCallback;
|
||||
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
|
||||
import org.springframework.ws.transport.WebServiceMessageSender;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@@ -261,14 +262,10 @@ public class WebServiceOutboundGatewayParserTests {
|
||||
"marshallingWebServiceOutboundGatewayParserTests.xml", this.getClass());
|
||||
AbstractEndpoint endpoint = (AbstractEndpoint) context.getBean("gatewayWithAllInOneMarshaller");
|
||||
assertEquals(EventDrivenConsumer.class, endpoint.getClass());
|
||||
Object gateway = new DirectFieldAccessor(endpoint).getPropertyValue("handler");
|
||||
assertEquals(MarshallingWebServiceOutboundGateway.class, gateway.getClass());
|
||||
DirectFieldAccessor gatewayAccessor = new DirectFieldAccessor(gateway);
|
||||
DirectFieldAccessor templateAccessor = new DirectFieldAccessor(
|
||||
gatewayAccessor.getPropertyValue("webServiceTemplate"));
|
||||
MarshallingWebServiceOutboundGateway gateway = (MarshallingWebServiceOutboundGateway) new DirectFieldAccessor(endpoint).getPropertyValue("handler");
|
||||
Marshaller marshaller = (Marshaller) context.getBean("marshallerAndUnmarshaller");
|
||||
assertEquals(marshaller, templateAccessor.getPropertyValue("marshaller"));
|
||||
assertEquals(marshaller, templateAccessor.getPropertyValue("unmarshaller"));
|
||||
assertEquals(marshaller, TestUtils.getPropertyValue(gateway, "marshaller", Marshaller.class));
|
||||
assertEquals(marshaller, TestUtils.getPropertyValue(gateway, "unmarshaller", Unmarshaller.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -277,15 +274,11 @@ public class WebServiceOutboundGatewayParserTests {
|
||||
"marshallingWebServiceOutboundGatewayParserTests.xml", this.getClass());
|
||||
AbstractEndpoint endpoint = (AbstractEndpoint) context.getBean("gatewayWithSeparateMarshallerAndUnmarshaller");
|
||||
assertEquals(EventDrivenConsumer.class, endpoint.getClass());
|
||||
Object gateway = new DirectFieldAccessor(endpoint).getPropertyValue("handler");
|
||||
assertEquals(MarshallingWebServiceOutboundGateway.class, gateway.getClass());
|
||||
DirectFieldAccessor gatewayAccessor = new DirectFieldAccessor(gateway);
|
||||
DirectFieldAccessor templateAccessor = new DirectFieldAccessor(
|
||||
gatewayAccessor.getPropertyValue("webServiceTemplate"));
|
||||
MarshallingWebServiceOutboundGateway gateway = (MarshallingWebServiceOutboundGateway) new DirectFieldAccessor(endpoint).getPropertyValue("handler");
|
||||
Marshaller marshaller = (Marshaller) context.getBean("marshaller");
|
||||
Unmarshaller unmarshaller = (Unmarshaller) context.getBean("unmarshaller");
|
||||
assertEquals(marshaller, templateAccessor.getPropertyValue("marshaller"));
|
||||
assertEquals(unmarshaller, templateAccessor.getPropertyValue("unmarshaller"));
|
||||
assertEquals(marshaller, TestUtils.getPropertyValue(gateway, "marshaller", Marshaller.class));
|
||||
assertEquals(unmarshaller, TestUtils.getPropertyValue(gateway, "unmarshaller", Unmarshaller.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -307,16 +300,13 @@ public class WebServiceOutboundGatewayParserTests {
|
||||
"marshallingWebServiceOutboundGatewayParserTests.xml", this.getClass());
|
||||
AbstractEndpoint endpoint = (AbstractEndpoint) context.getBean("gatewayWithAllInOneMarshallerAndMessageFactory");
|
||||
assertEquals(EventDrivenConsumer.class, endpoint.getClass());
|
||||
Object gateway = new DirectFieldAccessor(endpoint).getPropertyValue("handler");
|
||||
assertEquals(MarshallingWebServiceOutboundGateway.class, gateway.getClass());
|
||||
DirectFieldAccessor gatewayAccessor = new DirectFieldAccessor(gateway);
|
||||
DirectFieldAccessor templateAccessor = new DirectFieldAccessor(
|
||||
gatewayAccessor.getPropertyValue("webServiceTemplate"));
|
||||
MarshallingWebServiceOutboundGateway gateway = (MarshallingWebServiceOutboundGateway) new DirectFieldAccessor(endpoint).getPropertyValue("handler");
|
||||
Marshaller marshaller = (Marshaller) context.getBean("marshallerAndUnmarshaller");
|
||||
assertEquals(marshaller, templateAccessor.getPropertyValue("marshaller"));
|
||||
assertEquals(marshaller, templateAccessor.getPropertyValue("unmarshaller"));
|
||||
assertEquals(marshaller, TestUtils.getPropertyValue(gateway, "marshaller", Marshaller.class));
|
||||
assertEquals(marshaller, TestUtils.getPropertyValue(gateway, "unmarshaller", Unmarshaller.class));
|
||||
|
||||
WebServiceMessageFactory messageFactory = (WebServiceMessageFactory) context.getBean("messageFactory");
|
||||
assertEquals(messageFactory, templateAccessor.getPropertyValue("messageFactory"));
|
||||
assertEquals(messageFactory, TestUtils.getPropertyValue(gateway, "webServiceTemplate.messageFactory"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -325,17 +315,14 @@ public class WebServiceOutboundGatewayParserTests {
|
||||
"marshallingWebServiceOutboundGatewayParserTests.xml", this.getClass());
|
||||
AbstractEndpoint endpoint = (AbstractEndpoint) context.getBean("gatewayWithSeparateMarshallerAndUnmarshallerAndMessageFactory");
|
||||
assertEquals(EventDrivenConsumer.class, endpoint.getClass());
|
||||
Object gateway = new DirectFieldAccessor(endpoint).getPropertyValue("handler");
|
||||
assertEquals(MarshallingWebServiceOutboundGateway.class, gateway.getClass());
|
||||
DirectFieldAccessor gatewayAccessor = new DirectFieldAccessor(gateway);
|
||||
DirectFieldAccessor templateAccessor = new DirectFieldAccessor(
|
||||
gatewayAccessor.getPropertyValue("webServiceTemplate"));
|
||||
MarshallingWebServiceOutboundGateway gateway = (MarshallingWebServiceOutboundGateway) new DirectFieldAccessor(endpoint).getPropertyValue("handler");
|
||||
|
||||
Marshaller marshaller = (Marshaller) context.getBean("marshaller");
|
||||
Unmarshaller unmarshaller = (Unmarshaller) context.getBean("unmarshaller");
|
||||
assertEquals(marshaller, templateAccessor.getPropertyValue("marshaller"));
|
||||
assertEquals(unmarshaller, templateAccessor.getPropertyValue("unmarshaller"));
|
||||
assertEquals(marshaller, TestUtils.getPropertyValue(gateway, "marshaller", Marshaller.class));
|
||||
assertEquals(unmarshaller, TestUtils.getPropertyValue(gateway, "unmarshaller", Unmarshaller.class));
|
||||
WebServiceMessageFactory messageFactory = (WebServiceMessageFactory) context.getBean("messageFactory");
|
||||
assertEquals(messageFactory, templateAccessor.getPropertyValue("messageFactory"));
|
||||
assertEquals(messageFactory, TestUtils.getPropertyValue(gateway, "webServiceTemplate.messageFactory"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* 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 java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.integration.ws.AbstractWebServiceOutboundGateway;
|
||||
import org.springframework.integration.ws.DefaultSoapHeaderMapper;
|
||||
import org.springframework.integration.ws.SimpleWebServiceOutboundGateway;
|
||||
import org.springframework.integration.ws.WebServiceHeaders;
|
||||
import org.springframework.oxm.Unmarshaller;
|
||||
import org.springframework.oxm.XmlMappingException;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.ws.WebServiceMessageFactory;
|
||||
import org.springframework.ws.soap.SoapHeader;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
import org.springframework.ws.soap.SoapMessageFactory;
|
||||
import org.springframework.ws.transport.WebServiceConnection;
|
||||
import org.springframework.ws.transport.WebServiceMessageSender;
|
||||
import org.springframework.xml.namespace.QNameUtils;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*/
|
||||
public class WebServiceOutboundGatewayWithHeaderMapperTests {
|
||||
|
||||
String responseMessage = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> " +
|
||||
"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"> " +
|
||||
"<SOAP-ENV:Header/>" +
|
||||
"<SOAP-ENV:Body> " +
|
||||
"<root><name>jane</name></root>" +
|
||||
"</SOAP-ENV:Body> " +
|
||||
"</SOAP-ENV:Envelope>";
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void headerMapperParserTest() throws Exception{
|
||||
ApplicationContext context = new ClassPathXmlApplicationContext("ws-outbound-gateway-with-headermappers.xml", this.getClass());
|
||||
SimpleWebServiceOutboundGateway gateway = TestUtils.getPropertyValue(context.getBean("withHeaderMapper"), "handler", SimpleWebServiceOutboundGateway.class);
|
||||
DefaultSoapHeaderMapper headerMapper = TestUtils.getPropertyValue(gateway, "headerMapper", DefaultSoapHeaderMapper.class);
|
||||
assertNotNull(headerMapper);
|
||||
|
||||
List<String> requestHeaderNames = TestUtils.getPropertyValue(headerMapper, "requestHeaderNames", List.class);
|
||||
assertEquals(2, requestHeaderNames.size());
|
||||
assertEquals("foo*", requestHeaderNames.get(0));
|
||||
assertEquals("*baz*", requestHeaderNames.get(1));
|
||||
|
||||
List<String> responseHeaderNames = TestUtils.getPropertyValue(headerMapper, "replyHeaderNames", List.class);
|
||||
assertEquals(1, responseHeaderNames.size());
|
||||
assertEquals("bar*", responseHeaderNames.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withHeaderMapperString() throws Exception{
|
||||
String payload = "<root><name>bill</name></root>";
|
||||
this.process(payload, "withHeaderMapper", "inputChannel");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withHeaderMapperSource() throws Exception{
|
||||
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
|
||||
Document document = docBuilder.parse(new ByteArrayInputStream("<root><name>bill</name></root>".getBytes()));
|
||||
DOMSource payload = new DOMSource(document);
|
||||
this.process(payload, "withHeaderMapper", "inputChannel");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withHeaderMapperDocument() throws Exception{
|
||||
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
|
||||
Document payload = docBuilder.parse(new ByteArrayInputStream("<root><name>bill</name></root>".getBytes()));
|
||||
this.process(payload, "withHeaderMapper", "inputChannel");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withHeaderMapperAndMarshaller() throws Exception{
|
||||
Person person = new Person();
|
||||
person.setName("Bill Clinton");
|
||||
this.process(person, "marshallingWithHeaderMapper", "inputMarshallingChannel");
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void process(Object payload, String gatewayName, String channelName) throws Exception{
|
||||
ApplicationContext context = new ClassPathXmlApplicationContext("ws-outbound-gateway-with-headermappers.xml", this.getClass());
|
||||
AbstractWebServiceOutboundGateway gateway = TestUtils.getPropertyValue(context.getBean(gatewayName), "handler", AbstractWebServiceOutboundGateway.class);
|
||||
|
||||
WebServiceMessageSender messageSender = Mockito.mock(WebServiceMessageSender.class);
|
||||
WebServiceConnection wsConnection = Mockito.mock(WebServiceConnection.class);
|
||||
Mockito.when(messageSender.createConnection(Mockito.any(URI.class))).thenReturn(wsConnection);
|
||||
Mockito.when(messageSender.supports(Mockito.any(URI.class))).thenReturn(true);
|
||||
|
||||
Mockito.doAnswer(new Answer() {
|
||||
public Object answer(InvocationOnMock invocation) {
|
||||
Object[] args = invocation.getArguments();
|
||||
SoapMessage soapMessage = (SoapMessage) args[0];
|
||||
// try { // uncomment if you want to see a pretty-print of SOAP message
|
||||
// Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
||||
// transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
// transformer.transform(new DOMSource(soapMessage.getDocument()), new StreamResult(System.out));
|
||||
// } catch (Exception e) {
|
||||
// // ignore
|
||||
// }
|
||||
SoapHeader soapHeader = soapMessage.getSoapHeader();
|
||||
assertNotNull(soapHeader.getAttributeValue(QNameUtils.parseQNameString("foo")));
|
||||
assertNotNull(soapHeader.getAttributeValue(QNameUtils.parseQNameString("foobar")));
|
||||
assertNotNull(soapHeader.getAttributeValue(QNameUtils.parseQNameString("abaz")));
|
||||
assertNull(soapHeader.getAttributeValue(QNameUtils.parseQNameString("bar")));
|
||||
return null;
|
||||
}})
|
||||
.when(wsConnection).send(Mockito.any(WebServiceMessage.class));
|
||||
|
||||
Mockito.doAnswer(new Answer() {
|
||||
public Object answer(InvocationOnMock invocation) throws Exception{
|
||||
Object[] args = invocation.getArguments();
|
||||
SoapMessageFactory factory = (SoapMessageFactory) args[0];
|
||||
SoapMessage soapMessage = factory.createWebServiceMessage(new ByteArrayInputStream(responseMessage.getBytes()));
|
||||
soapMessage.getSoapHeader().addAttribute(QNameUtils.parseQNameString("bar"), "bar");
|
||||
soapMessage.getSoapHeader().addAttribute(QNameUtils.parseQNameString("baz"), "baz");
|
||||
// try { // uncomment if you want to see a pretty-print of SOAP message
|
||||
// Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
||||
// transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
// transformer.transform(new DOMSource(soapMessage.getDocument()), new StreamResult(System.out));
|
||||
// } catch (Exception e) {
|
||||
// // ignore
|
||||
// }
|
||||
return soapMessage;
|
||||
}})
|
||||
.when(wsConnection).receive(Mockito.any(WebServiceMessageFactory.class));
|
||||
|
||||
gateway.setMessageSender(messageSender);
|
||||
|
||||
MessageChannel inputChannel = context.getBean(channelName, MessageChannel.class);
|
||||
Message<?> message =
|
||||
MessageBuilder.withPayload(payload).
|
||||
setHeader("foo", "foo").setHeader("foobar", "foobar").setHeader("abaz", "abaz").setHeader("bar", "bar").
|
||||
setHeader(WebServiceHeaders.SOAP_ACTION, "someAction").build();
|
||||
inputChannel.send(message);
|
||||
QueueChannel outputChannel = context.getBean("outputChannel", QueueChannel.class);
|
||||
Message<?> replyMessage = outputChannel.receive(0);
|
||||
assertEquals("bar", replyMessage.getHeaders().get("bar"));
|
||||
assertNull(replyMessage.getHeaders().get("baz"));
|
||||
}
|
||||
|
||||
public static class Person{
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SampleUnmarshaller implements Unmarshaller {
|
||||
|
||||
public boolean supports(Class<?> clazz) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Object unmarshal(Source source) throws IOException, XmlMappingException {
|
||||
Element documentElement = (Element) ((DOMSource) source).getNode();
|
||||
|
||||
String name = DomUtils.getChildElementValueByTagName(documentElement, "name");
|
||||
Person person = new Person();
|
||||
person.setName(name);
|
||||
return person;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?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:int-ws="http://www.springframework.org/schema/integration/ws"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration/ws http://www.springframework.org/schema/integration/ws/spring-integration-ws-2.1.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
|
||||
<int:channel id="inputChannel"/>
|
||||
<int:channel id="inputMarshallingChannel"/>
|
||||
|
||||
<int-ws:outbound-gateway id="withHeaderMapper"
|
||||
request-channel="inputChannel"
|
||||
reply-channel="outputChannel"
|
||||
uri="http://example.org"
|
||||
mapped-request-headers="foo*, *baz*"
|
||||
mapped-reply-headers="bar*"/>
|
||||
|
||||
<int-ws:outbound-gateway id="marshallingWithHeaderMapper"
|
||||
request-channel="inputMarshallingChannel"
|
||||
reply-channel="outputChannel"
|
||||
uri="http://example.org"
|
||||
marshaller="marshaller"
|
||||
unmarshaller="ubmarshaller"
|
||||
mapped-request-headers="foo*, *baz*"
|
||||
mapped-reply-headers="bar*"/>
|
||||
|
||||
<bean id="marshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"/>
|
||||
|
||||
<bean id="ubmarshaller" class="org.springframework.integration.ws.config.WebServiceOutboundGatewayWithHeaderMapperTests.SampleUnmarshaller"/>
|
||||
|
||||
<int:channel id="outputChannel">
|
||||
<int:queue/>
|
||||
</int:channel>
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user