SWS-465: Optional WS-Addressing request headers being treated as mandatory
This commit is contained in:
@@ -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 <code>true</code> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() + "]");
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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 <a href="http://msdn.microsoft.com/ws/2004/08/ws-addressing/">Web Services Addressing, August 2004</a>
|
||||
* @see <a href="http://www.w3.org/Submission/2004/SUBM-ws-addressing-20040810/">Web Services Addressing, August
|
||||
* 2004</a>
|
||||
* @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";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,9 +56,17 @@ public interface AddressingVersion {
|
||||
*/
|
||||
boolean understands(SoapHeaderElement headerElement);
|
||||
|
||||
/*
|
||||
* Address URIs
|
||||
/**
|
||||
* Indicates whether the given {@link MessageAddressingProperties} has all required properties.
|
||||
*
|
||||
* @return <code>true</code> 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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing">
|
||||
<S:Header>
|
||||
<wsa:Action>http://example.com/fabrikam/mail/Delete</wsa:Action>
|
||||
<wsa:MessageID>http://example.com/someuniquestring</wsa:MessageID>
|
||||
</S:Header>
|
||||
<S:Body>
|
||||
<f:Delete xmlns:f="http://example.com/fabrikam">
|
||||
<f:maxCount>42</f:maxCount>
|
||||
</f:Delete>
|
||||
</S:Body>
|
||||
</S:Envelope>
|
||||
Reference in New Issue
Block a user