diff --git a/core/src/main/java/org/springframework/ws/soap/addressing/core/MessageAddressingProperties.java b/core/src/main/java/org/springframework/ws/soap/addressing/core/MessageAddressingProperties.java index 6853205f..f8e7a2d6 100644 --- a/core/src/main/java/org/springframework/ws/soap/addressing/core/MessageAddressingProperties.java +++ b/core/src/main/java/org/springframework/ws/soap/addressing/core/MessageAddressingProperties.java @@ -153,23 +153,4 @@ public final class MessageAddressingProperties { public MessageAddressingProperties getReplyProperties(EndpointReference epr, URI action, URI messageId) { return new MessageAddressingProperties(epr, action, messageId, this.messageId); } - - /** - * Indicates whether is {@link MessageAddressingProperties} has all required properties. - * - * @return true if the to and action properties have been set, and - if a reply or fault endpoint has - * been set - also checks for the message id - */ - public boolean hasRequiredProperties() { - if (to == null) { - return false; - } - if (action == null) { - return false; - } - if (replyTo != null || faultTo != null) { - return messageId != null; - } - return true; - } } diff --git a/core/src/main/java/org/springframework/ws/soap/addressing/server/AddressingEndpointInterceptor.java b/core/src/main/java/org/springframework/ws/soap/addressing/server/AddressingEndpointInterceptor.java index 3ceeaba4..6e0d8473 100644 --- a/core/src/main/java/org/springframework/ws/soap/addressing/server/AddressingEndpointInterceptor.java +++ b/core/src/main/java/org/springframework/ws/soap/addressing/server/AddressingEndpointInterceptor.java @@ -74,7 +74,7 @@ class AddressingEndpointInterceptor implements SoapEndpointInterceptor { Assert.isInstanceOf(SoapMessage.class, messageContext.getRequest()); SoapMessage request = (SoapMessage) messageContext.getRequest(); MessageAddressingProperties requestMap = version.getMessageAddressingProperties(request); - if (!requestMap.hasRequiredProperties()) { + if (!version.hasRequiredProperties(requestMap)) { version.addMessageAddressingHeaderRequiredFault((SoapMessage) messageContext.getResponse()); return false; } @@ -119,8 +119,9 @@ class AddressingEndpointInterceptor implements SoapEndpointInterceptor { private boolean handleNoneAddress(MessageContext messageContext, EndpointReference replyEpr) { if (replyEpr == null || version.hasNoneAddress(replyEpr)) { if (logger.isDebugEnabled()) { - logger.debug("Request " + messageContext.getRequest() + "] has [" + replyEpr + - "] reply address; reply [" + messageContext.getResponse() + "] discarded"); + logger.debug( + "Request [" + messageContext.getRequest() + "] has [" + replyEpr + "] reply address; reply [" + + messageContext.getResponse() + "] discarded"); } messageContext.clearResponse(); return true; @@ -131,7 +132,7 @@ class AddressingEndpointInterceptor implements SoapEndpointInterceptor { private boolean handleAnonymousAddress(MessageContext messageContext, EndpointReference replyEpr) { if (version.hasAnonymousAddress(replyEpr)) { if (logger.isDebugEnabled()) { - logger.debug("Request " + messageContext.getRequest() + "] has [" + replyEpr + + logger.debug("Request [" + messageContext.getRequest() + "] has [" + replyEpr + "] reply address; sending in-band reply [" + messageContext.getResponse() + "]"); } return true; @@ -141,7 +142,7 @@ class AddressingEndpointInterceptor implements SoapEndpointInterceptor { private void sendOutOfBand(MessageContext messageContext, EndpointReference replyEpr) throws IOException { if (logger.isDebugEnabled()) { - logger.debug("Request " + messageContext.getRequest() + "] has [" + replyEpr + + logger.debug("Request [" + messageContext.getRequest() + "] has [" + replyEpr + "] reply address; sending out-of-band reply [" + messageContext.getResponse() + "]"); } diff --git a/core/src/main/java/org/springframework/ws/soap/addressing/version/AbstractAddressingVersion.java b/core/src/main/java/org/springframework/ws/soap/addressing/version/AbstractAddressingVersion.java index cfdaeae5..79149475 100644 --- a/core/src/main/java/org/springframework/ws/soap/addressing/version/AbstractAddressingVersion.java +++ b/core/src/main/java/org/springframework/ws/soap/addressing/version/AbstractAddressingVersion.java @@ -123,6 +123,9 @@ public abstract class AbstractAddressingVersion extends TransformerObjectSupport public MessageAddressingProperties getMessageAddressingProperties(SoapMessage message) { Element headerElement = getSoapHeaderElement(message); URI to = getUri(headerElement, toExpression); + if (to == null) { + to = getDefaultTo(); + } EndpointReference from = getEndpointReference(fromExpression.evaluateAsNode(headerElement)); EndpointReference replyTo = getEndpointReference(replyToExpression.evaluateAsNode(headerElement)); if (replyTo == null) { @@ -392,6 +395,9 @@ public abstract class AbstractAddressingVersion extends TransformerObjectSupport return QNameUtils.createQName(getNamespaceUri(), "Address", getNamespacePrefix()); } + /** Returns the default To URI. */ + protected abstract URI getDefaultTo(); + /** Returns the default ReplyTo EPR. Can be based on the From EPR, or the anonymous URI. */ protected abstract EndpointReference getDefaultReplyTo(EndpointReference from); diff --git a/core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing10.java b/core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing10.java index 20052ecf..fa2b16ce 100644 --- a/core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing10.java +++ b/core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing10.java @@ -43,6 +43,17 @@ public class Addressing10 extends AbstractAddressingVersion { super.addAddressingHeaders(message, map); } + public boolean hasRequiredProperties(MessageAddressingProperties map) { + if (map.getAction() == null) { + return false; + } + if (map.getReplyTo() != null || map.getFaultTo() != null) { + return map.getMessageId() != null; + } + return true; + + } + protected String getNamespaceUri() { return NAMESPACE_URI; } @@ -51,6 +62,10 @@ public class Addressing10 extends AbstractAddressingVersion { return null; } + protected URI getDefaultTo() { + return getAnonymous(); + } + protected EndpointReference getDefaultReplyTo(EndpointReference from) { return new EndpointReference(getAnonymous()); } diff --git a/core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing200408.java b/core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing200408.java index b8f7a75f..b30584a8 100644 --- a/core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing200408.java +++ b/core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing200408.java @@ -30,7 +30,8 @@ import org.springframework.xml.namespace.QNameUtils; * Microsoft's Web Services Enhancements (WSE) 3.0, and supported by Axis 1 and 2, and XFire. * * @author Arjen Poutsma - * @see Web Services Addressing, August 2004 + * @see Web Services Addressing, August + * 2004 * @since 1.5.0 */ public class Addressing200408 extends AbstractAddressingVersion { @@ -38,11 +39,24 @@ public class Addressing200408 extends AbstractAddressingVersion { private static final String NAMESPACE_URI = "http://schemas.xmlsoap.org/ws/2004/08/addressing"; public void addAddressingHeaders(SoapMessage message, MessageAddressingProperties map) { - Assert.notNull(map.getAction(), "'Action' must not be null"); - Assert.notNull(map.getTo(), "'Action' must not be null"); + Assert.notNull(map.getAction(), "'Action' is required"); + Assert.notNull(map.getTo(), "'To' is required"); super.addAddressingHeaders(message, map); } + public boolean hasRequiredProperties(MessageAddressingProperties map) { + if (map.getTo() == null) { + return false; + } + if (map.getAction() == null) { + return false; + } + if (map.getReplyTo() != null || map.getFaultTo() != null) { + return map.getMessageId() != null; + } + return true; + } + protected final URI getAnonymous() { return URI.create(NAMESPACE_URI + "/role/anonymous"); } @@ -67,6 +81,10 @@ public class Addressing200408 extends AbstractAddressingVersion { return NAMESPACE_URI; } + protected URI getDefaultTo() { + return null; + } + protected final EndpointReference getDefaultReplyTo(EndpointReference from) { return from; } @@ -76,6 +94,6 @@ public class Addressing200408 extends AbstractAddressingVersion { } public String toString() { - return "Ws-Addressing August 2004"; + return "WS-Addressing August 2004"; } } diff --git a/core/src/main/java/org/springframework/ws/soap/addressing/version/AddressingVersion.java b/core/src/main/java/org/springframework/ws/soap/addressing/version/AddressingVersion.java index 528f5d26..af4a1317 100644 --- a/core/src/main/java/org/springframework/ws/soap/addressing/version/AddressingVersion.java +++ b/core/src/main/java/org/springframework/ws/soap/addressing/version/AddressingVersion.java @@ -56,9 +56,17 @@ public interface AddressingVersion { */ boolean understands(SoapHeaderElement headerElement); - /* - * Address URIs + /** + * Indicates whether the given {@link MessageAddressingProperties} has all required properties. + * + * @return true if the to and action properties have been set, and - if a reply or fault endpoint has + * been set - also checks for the message id */ + boolean hasRequiredProperties(MessageAddressingProperties map); + + /* + * Address URIs + */ /** * Indicates whether the given endpoint reference has a Anonymous address. This address is used to indicate that a diff --git a/core/src/test/java/org/springframework/ws/soap/addressing/server/AbstractAddressingInterceptorTestCase.java b/core/src/test/java/org/springframework/ws/soap/addressing/server/AbstractAddressingInterceptorTestCase.java index 369b18af..6a409a40 100644 --- a/core/src/test/java/org/springframework/ws/soap/addressing/server/AbstractAddressingInterceptorTestCase.java +++ b/core/src/test/java/org/springframework/ws/soap/addressing/server/AbstractAddressingInterceptorTestCase.java @@ -36,11 +36,11 @@ import org.springframework.ws.transport.WebServiceMessageSender; public abstract class AbstractAddressingInterceptorTestCase extends AbstractWsAddressingTestCase { - private AddressingEndpointInterceptor interceptor; + protected AddressingEndpointInterceptor interceptor; - private MockControl strategyControl; + protected MockControl strategyControl; - private MessageIdStrategy strategyMock; + protected MessageIdStrategy strategyMock; protected final void onSetUp() throws Exception { strategyControl = MockControl.createControl(MessageIdStrategy.class); @@ -148,8 +148,9 @@ public abstract class AbstractAddressingInterceptorTestCase extends AbstractWsAd URI replyAction = new URI("urn:replyAction"); URI faultAction = new URI("urn:replyAction"); - interceptor = new AddressingEndpointInterceptor(getVersion(), strategyMock, - new WebServiceMessageSender[]{senderMock}, replyAction, faultAction); + interceptor = + new AddressingEndpointInterceptor(getVersion(), strategyMock, new WebServiceMessageSender[]{senderMock}, + replyAction, faultAction); MockControl connectionControl = MockControl.createControl(WebServiceConnection.class); WebServiceConnection connectionMock = (WebServiceConnection) connectionControl.getMock(); diff --git a/core/src/test/java/org/springframework/ws/soap/addressing/server/AddressingInterceptor10Test.java b/core/src/test/java/org/springframework/ws/soap/addressing/server/AddressingInterceptor10Test.java index 45c83827..66b1c4f6 100644 --- a/core/src/test/java/org/springframework/ws/soap/addressing/server/AddressingInterceptor10Test.java +++ b/core/src/test/java/org/springframework/ws/soap/addressing/server/AddressingInterceptor10Test.java @@ -16,8 +16,15 @@ package org.springframework.ws.soap.addressing.server; +import java.net.URI; + +import org.springframework.ws.context.DefaultMessageContext; +import org.springframework.ws.context.MessageContext; +import org.springframework.ws.soap.SoapMessage; import org.springframework.ws.soap.addressing.version.Addressing10; import org.springframework.ws.soap.addressing.version.AddressingVersion; +import org.springframework.ws.soap.saaj.SaajSoapMessage; +import org.springframework.ws.soap.saaj.SaajSoapMessageFactory; public class AddressingInterceptor10Test extends AbstractAddressingInterceptorTestCase { @@ -28,4 +35,20 @@ public class AddressingInterceptor10Test extends AbstractAddressingInterceptorTe protected String getTestPath() { return "10"; } + + public void testNoTo() throws Exception { + SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/request-no-to.xml"); + MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory)); + URI messageId = new URI("uid:1234"); + strategyControl.expectAndReturn(strategyMock.newMessageId((SoapMessage) context.getResponse()), messageId); + strategyControl.replay(); + boolean result = interceptor.handleResponse(context, null); + assertTrue("Request with no To not handled", result); + assertTrue("Message Context has no response", context.hasResponse()); + SaajSoapMessage expectedResponse = loadSaajMessage(getTestPath() + "/response-anonymous.xml"); + assertXMLEqual("Invalid response for message with invalid MAP", expectedResponse, + (SaajSoapMessage) context.getResponse()); + strategyControl.verify(); + } + } \ No newline at end of file diff --git a/core/src/test/resources/org/springframework/ws/soap/addressing/10/request-no-to.xml b/core/src/test/resources/org/springframework/ws/soap/addressing/10/request-no-to.xml new file mode 100644 index 00000000..e7515513 --- /dev/null +++ b/core/src/test/resources/org/springframework/ws/soap/addressing/10/request-no-to.xml @@ -0,0 +1,11 @@ + + + http://example.com/fabrikam/mail/Delete + http://example.com/someuniquestring + + + + 42 + + +