Added handleFault to EndpointInterceptor, moved SoapEndpointInterceptor and SoapEhndpointMapping to org.sfwrk.ws.soap.server package.
This commit is contained in:
@@ -24,9 +24,9 @@ import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.server.EndpointInterceptor;
|
||||
import org.springframework.ws.server.EndpointInvocationChain;
|
||||
import org.springframework.ws.server.endpoint.mapping.AbstractAnnotationMethodEndpointMapping;
|
||||
import org.springframework.ws.soap.SoapEndpointMapping;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
import org.springframework.ws.soap.server.SoapEndpointInvocationChain;
|
||||
import org.springframework.ws.soap.server.SoapEndpointMapping;
|
||||
import org.springframework.ws.soap.server.endpoint.annotation.SoapAction;
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,14 +23,15 @@ import org.springframework.ws.context.MessageContext;
|
||||
* existing or custom interceptors for certain groups of endpoints, to add common preprocessing behavior without needing
|
||||
* to modify each endpoint implementation.
|
||||
* <p/>
|
||||
* A <code>EndpointInterceptor</code> gets called before the appropriate <code>EndpointAdapter</code> triggers the
|
||||
* invocation of the endpoint itself. This mechanism can be used for a large field of preprocessing aspects, e.g. for
|
||||
* authorization checks, or message header checks. Its main purpose is to allow for factoring out repetitive endpoint
|
||||
* code.
|
||||
* A <code>EndpointInterceptor</code> gets called before the appropriate {@link EndpointAdapter} triggers the invocation
|
||||
* of the endpoint itself. This mechanism can be used for a large field of preprocessing aspects, e.g. for authorization
|
||||
* checks, or message header checks. Its main purpose is to allow for factoring out repetitive endpoint code.
|
||||
* <p/>
|
||||
* Typically an interceptor chain is defined per <code>EndpointMapping</code> bean, sharing its granularity. To be able
|
||||
* to apply a certain interceptor chain to a group of handlers, one needs to map the desired handlers via one
|
||||
* <code>EndpointMapping</code> bean.
|
||||
* Typically an interceptor chain is defined per {@link EndpointMapping} bean, sharing its granularity. To be able to
|
||||
* apply a certain interceptor chain to a group of handlers, one needs to map the desired handlers via one
|
||||
* <code>EndpointMapping</code> bean.The interceptors themselves are defined as beans in the application context,
|
||||
* referenced by the mapping bean definition via its <code>interceptors</code> property (in XML: a <list> of
|
||||
* <ref>).
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see EndpointInvocationChain#getInterceptors()
|
||||
@@ -40,23 +41,57 @@ import org.springframework.ws.context.MessageContext;
|
||||
public interface EndpointInterceptor {
|
||||
|
||||
/**
|
||||
* Processes the incoming request message.
|
||||
* Processes the incoming request message. Called after {@link EndpointMapping} determined an appropriate endpoint
|
||||
* object, but before {@link EndpointAdapter} invokes the endpoint.
|
||||
* <p/>
|
||||
* {@link MessageDispatcher} processes an endpoint in an invocation chain, consisting of any number of interceptors,
|
||||
* with the endpoint itself at the end. With this method, each interceptor can decide to abort the chain, typically
|
||||
* creating a custom response.
|
||||
*
|
||||
* @param messageContext contains the incoming request message
|
||||
* @param endpoint chosen endpoint to invoke
|
||||
* @return <code>true</code> to continue processing of the request interceptor chain; <code>false</code> to indicate
|
||||
* blocking of the request handler chain, <em>without invoking the endpoint</em>
|
||||
* blocking of the request endpoint chain, <em>without invoking the endpoint</em>
|
||||
* @throws Exception in case of errors
|
||||
* @see org.springframework.ws.context.MessageContext#getRequest()
|
||||
*/
|
||||
boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception;
|
||||
|
||||
/**
|
||||
* Processes the outgoing response message.
|
||||
* Processes the outgoing response message. Called after {@link EndpointAdapter} actually invoked the endpoint. Can
|
||||
* manipulate the response, if any, by adding new headers, etc.
|
||||
* <p/>
|
||||
* {@link MessageDispatcher} processes an endpoint in an invocation chain, consisting of any number of interceptors,
|
||||
* with the endpoint itself at the end. With this method, each interceptor can post-process an invocation, getting
|
||||
* applied in inverse order of the execution chain.
|
||||
* <p/>
|
||||
* Note: Will only be called if this interceptor's {@link #handleRequest} method has successfully completed.
|
||||
*
|
||||
* @param messageContext contains both request and response messages
|
||||
* @param endpoint chosen endpoint to invoke
|
||||
* @return <code>true</code> to continue processing of the reponse interceptor chain; <code>false</code> to indicate
|
||||
* blocking of the response handler chain.
|
||||
* blocking of the response endpoint chain.
|
||||
* @throws Exception in case of errors
|
||||
* @see org.springframework.ws.context.MessageContext#getRequest()
|
||||
* @see org.springframework.ws.context.MessageContext#hasResponse()
|
||||
* @see org.springframework.ws.context.MessageContext#getResponse()
|
||||
*/
|
||||
boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception;
|
||||
|
||||
/**
|
||||
* Processes the outgoing response fault. Called after {@link EndpointAdapter} actually invoked the endpoint. Can
|
||||
* manipulate the response, if any, by adding new headers, etc.
|
||||
* <p/>
|
||||
* {@link MessageDispatcher} processes an endpoint in an invocation chain, consisting of any number of interceptors,
|
||||
* with the endpoint itself at the end. With this method, each interceptor can post-process an invocation, getting
|
||||
* applied in inverse order of the execution chain.
|
||||
* <p/>
|
||||
* Note: Will only be called if this interceptor's {@link #handleRequest} method has successfully completed.
|
||||
*
|
||||
* @param messageContext contains both request and response messages, the response should contains a Fault
|
||||
* @param endpoint chosen endpoint to invoke
|
||||
* @return <code>true</code> to continue processing of the reponse interceptor chain; <code>false</code> to indicate
|
||||
* blocking of the response handler chain.
|
||||
*/
|
||||
boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception;
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa
|
||||
return;
|
||||
}
|
||||
// Apply handleRequest of registered interceptors
|
||||
if (!ObjectUtils.isEmpty(mappedEndpoint.getInterceptors())) {
|
||||
if (mappedEndpoint.getInterceptors() != null) {
|
||||
for (int i = 0; i < mappedEndpoint.getInterceptors().length; i++) {
|
||||
EndpointInterceptor interceptor = mappedEndpoint.getInterceptors()[i];
|
||||
interceptorIndex = i;
|
||||
@@ -303,15 +303,21 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa
|
||||
* @param messageContext the message context, whose request and response are filled
|
||||
* @see EndpointInterceptor#handleResponse(MessageContext,Object)
|
||||
*/
|
||||
protected void triggerHandleResponse(EndpointInvocationChain mappedEndpoint,
|
||||
int interceptorIndex,
|
||||
MessageContext messageContext) throws Exception {
|
||||
private void triggerHandleResponse(EndpointInvocationChain mappedEndpoint,
|
||||
int interceptorIndex,
|
||||
MessageContext messageContext) throws Exception {
|
||||
if (mappedEndpoint != null && messageContext.hasResponse() &&
|
||||
!ObjectUtils.isEmpty(mappedEndpoint.getInterceptors())) {
|
||||
boolean resume = true;
|
||||
boolean hasFault = messageContext.getResponse().hasFault();
|
||||
for (int i = interceptorIndex; resume && i >= 0; i--) {
|
||||
EndpointInterceptor interceptor = mappedEndpoint.getInterceptors()[i];
|
||||
resume = interceptor.handleResponse(messageContext, mappedEndpoint.getEndpoint());
|
||||
if (!hasFault) {
|
||||
resume = interceptor.handleResponse(messageContext, mappedEndpoint.getEndpoint());
|
||||
}
|
||||
else {
|
||||
resume = interceptor.handleFault(messageContext, mappedEndpoint.getEndpoint());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,16 +42,12 @@ public abstract class AbstractLoggingInterceptor extends TransformerObjectSuppor
|
||||
|
||||
private boolean logResponse = true;
|
||||
|
||||
/**
|
||||
* Indicates whether the request should be logged. Default is <code>true</code>.
|
||||
*/
|
||||
/** Indicates whether the request should be logged. Default is <code>true</code>. */
|
||||
public final void setLogRequest(boolean logRequest) {
|
||||
this.logRequest = logRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the response should be logged. Default is <code>true</code>.
|
||||
*/
|
||||
/** Indicates whether the response should be logged. Default is <code>true</code>. */
|
||||
public final void setLogResponse(boolean logResponse) {
|
||||
this.logResponse = logResponse;
|
||||
}
|
||||
@@ -86,6 +82,11 @@ public abstract class AbstractLoggingInterceptor extends TransformerObjectSuppor
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Does nothing by default. Faults are not logged. */
|
||||
public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
|
||||
return true;
|
||||
}
|
||||
|
||||
private Transformer createNonIndentingTransformer() throws TransformerConfigurationException {
|
||||
Transformer transformer = createTransformer();
|
||||
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
|
||||
|
||||
@@ -111,6 +111,18 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup
|
||||
this.validateResponse = validateResponse;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notEmpty(schemas, "setting either the schema or schemas property is required");
|
||||
Assert.hasLength(schemaLanguage, "schemaLanguage is required");
|
||||
for (int i = 0; i < schemas.length; i++) {
|
||||
Assert.isTrue(schemas[i].exists(), "schema [" + schemas[i] + "] does not exist");
|
||||
}
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Validating using " + StringUtils.arrayToCommaDelimitedString(schemas));
|
||||
}
|
||||
validator = XmlValidatorFactory.createValidator(schemas, schemaLanguage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the request message in the given message context. Validation only occurs if
|
||||
* <code>validateRequest</code> is set to <code>true</code>, which is the default.
|
||||
@@ -196,16 +208,9 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup
|
||||
return false;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notEmpty(schemas, "setting either the schema or schemas property is required");
|
||||
Assert.hasLength(schemaLanguage, "schemaLanguage is required");
|
||||
for (int i = 0; i < schemas.length; i++) {
|
||||
Assert.isTrue(schemas[i].exists(), "schema [" + schemas[i] + "] does not exist");
|
||||
}
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Validating using " + StringUtils.arrayToCommaDelimitedString(schemas));
|
||||
}
|
||||
validator = XmlValidatorFactory.createValidator(schemas, schemaLanguage);
|
||||
/** Does nothing by default. Faults are not validated. */
|
||||
public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -56,16 +56,12 @@ public class PayloadTransformingInterceptor implements EndpointInterceptor, Init
|
||||
|
||||
private Templates responseTemplates;
|
||||
|
||||
/**
|
||||
* Sets the XSLT stylesheet to use for transforming incoming request.
|
||||
*/
|
||||
/** Sets the XSLT stylesheet to use for transforming incoming request. */
|
||||
public void setRequestXslt(Resource requestXslt) {
|
||||
this.requestXslt = requestXslt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the XSLT stylesheet to use for transforming outgoing responses.
|
||||
*/
|
||||
/** Sets the XSLT stylesheet to use for transforming outgoing responses. */
|
||||
public void setResponseXslt(Resource responseXslt) {
|
||||
this.responseXslt = responseXslt;
|
||||
}
|
||||
@@ -106,6 +102,11 @@ public class PayloadTransformingInterceptor implements EndpointInterceptor, Init
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Does nothing by default. Faults are not transformed. */
|
||||
public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (requestXslt == null && responseXslt == null) {
|
||||
throw new IllegalArgumentException("Setting either 'requestXslt' or 'responseXslt' is required");
|
||||
|
||||
@@ -51,6 +51,13 @@ public interface SoapElement {
|
||||
*/
|
||||
void addAttribute(QName name, String value);
|
||||
|
||||
/**
|
||||
* Removes the attribute with the specified name.
|
||||
*
|
||||
* @param name the qualified name of the attribute to remove
|
||||
*/
|
||||
void removeAttribute(QName name);
|
||||
|
||||
/**
|
||||
* Returns the value of the attribute with the specified qualified name.
|
||||
*
|
||||
@@ -66,5 +73,4 @@ public interface SoapElement {
|
||||
*/
|
||||
Iterator getAllAttibutes();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -69,13 +69,4 @@ public interface SoapHeader extends SoapElement {
|
||||
*/
|
||||
Iterator examineAllHeaderElements() throws SoapHeaderException;
|
||||
|
||||
/**
|
||||
* Returns an <code>Iterator</code> over all the <code>SoapHeaderElement</code>s with the specified header.
|
||||
*
|
||||
* @param name the qualified name of header elements to look for
|
||||
* @return an iterator over all the header elements
|
||||
* @throws SoapHeaderException if the header cannot be returned
|
||||
* @see SoapHeaderElement
|
||||
*/
|
||||
Iterator examineHeaderElements(QName name) throws SoapHeaderException;
|
||||
}
|
||||
|
||||
@@ -59,9 +59,20 @@ public interface SoapHeaderElement extends SoapElement {
|
||||
*/
|
||||
void setMustUnderstand(boolean mustUnderstand) throws SoapHeaderException;
|
||||
|
||||
/**
|
||||
* Returns a <code>Result</code> that allows for writing to the <strong>contents</strong> of the header element.
|
||||
*/
|
||||
/** Returns a <code>Result</code> that allows for writing to the <strong>contents</strong> of the header element. */
|
||||
Result getResult() throws SoapHeaderException;
|
||||
|
||||
/**
|
||||
* Returns the text content of this header element, if any.
|
||||
*
|
||||
* @return the text content of this header element
|
||||
*/
|
||||
String getText();
|
||||
|
||||
/**
|
||||
* Sets the text content of this header element.
|
||||
*
|
||||
* @param content the new text content of this header element
|
||||
*/
|
||||
void setText(String content);
|
||||
}
|
||||
|
||||
@@ -79,6 +79,18 @@ class AxiomSoapElement implements SoapElement {
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAttribute(QName name) {
|
||||
try {
|
||||
OMAttribute attribute = getAxiomElement().getAttribute(name);
|
||||
if (attribute != null) {
|
||||
getAxiomElement().removeAttribute(attribute);
|
||||
}
|
||||
}
|
||||
catch (OMException ex) {
|
||||
throw new AxiomSoapElementException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public final String getAttributeValue(QName name) {
|
||||
try {
|
||||
return getAxiomElement().getAttributeValue(name);
|
||||
|
||||
@@ -57,6 +57,14 @@ class AxiomSoapHeaderElement extends AxiomSoapElement implements SoapHeaderEleme
|
||||
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return getAxiomHeaderBlock().getText();
|
||||
}
|
||||
|
||||
public void setText(String content) {
|
||||
getAxiomHeaderBlock().setText(content);
|
||||
}
|
||||
|
||||
protected SOAPHeaderBlock getAxiomHeaderBlock() {
|
||||
return (SOAPHeaderBlock) getAxiomElement();
|
||||
}
|
||||
|
||||
@@ -81,11 +81,24 @@ public class Saaj11Implementation implements SaajImplementation {
|
||||
return new SAXResult(new SaajContentHandler(element));
|
||||
}
|
||||
|
||||
public String getText(SOAPElement element) {
|
||||
return element.getValue();
|
||||
}
|
||||
|
||||
public void setText(SOAPElement element, String content) throws SOAPException {
|
||||
element.addTextNode(content);
|
||||
}
|
||||
|
||||
public void addAttribute(SOAPElement element, QName name, String value) throws SOAPException {
|
||||
Name attributeName = SaajUtils.toName(name, element);
|
||||
element.addAttribute(attributeName, value);
|
||||
}
|
||||
|
||||
public void removeAttribute(SOAPElement element, QName name) throws SOAPException {
|
||||
Name attributeName = SaajUtils.toName(name, element);
|
||||
element.removeAttribute(attributeName);
|
||||
}
|
||||
|
||||
public String getAttributeValue(SOAPElement element, QName name) throws SOAPException {
|
||||
Name attributeName = SaajUtils.toName(name, element);
|
||||
return element.getAttributeValue(attributeName);
|
||||
@@ -100,11 +113,6 @@ public class Saaj11Implementation implements SaajImplementation {
|
||||
return results.iterator();
|
||||
}
|
||||
|
||||
public Iterator getChildElements(SOAPElement element, QName name) throws SOAPException {
|
||||
Name childName = SaajUtils.toName(name, element);
|
||||
return element.getChildElements(childName);
|
||||
}
|
||||
|
||||
public QName getFaultCode(SOAPFault fault) {
|
||||
String code = fault.getFaultCode();
|
||||
int idx = code.indexOf(':');
|
||||
|
||||
@@ -109,6 +109,11 @@ public class Saaj12Implementation implements SaajImplementation {
|
||||
element.addAttribute(attributeName, value);
|
||||
}
|
||||
|
||||
public void removeAttribute(SOAPElement element, QName name) throws SOAPException {
|
||||
Name attributeName = SaajUtils.toName(name, element);
|
||||
element.removeAttribute(attributeName);
|
||||
}
|
||||
|
||||
public String getAttributeValue(SOAPElement element, QName name) throws SOAPException {
|
||||
Name attributeName = SaajUtils.toName(name, element);
|
||||
return element.getAttributeValue(attributeName);
|
||||
@@ -123,9 +128,12 @@ public class Saaj12Implementation implements SaajImplementation {
|
||||
return results.iterator();
|
||||
}
|
||||
|
||||
public Iterator getChildElements(SOAPElement element, QName name) throws SOAPException {
|
||||
Name childName = SaajUtils.toName(name, element);
|
||||
return element.getChildElements(childName);
|
||||
public String getText(SOAPElement element) {
|
||||
return element.getValue();
|
||||
}
|
||||
|
||||
public void setText(SOAPElement element, String content) {
|
||||
element.setValue(content);
|
||||
}
|
||||
|
||||
public SOAPEnvelope getEnvelope(SOAPMessage message) throws SOAPException {
|
||||
|
||||
@@ -139,10 +139,22 @@ public class Saaj13Implementation implements SaajImplementation {
|
||||
return new DOMResult(element);
|
||||
}
|
||||
|
||||
public String getText(SOAPElement element) {
|
||||
return element.getValue();
|
||||
}
|
||||
|
||||
public void setText(SOAPElement element, String content) {
|
||||
element.setValue(content);
|
||||
}
|
||||
|
||||
public void addAttribute(SOAPElement element, QName name, String value) throws SOAPException {
|
||||
element.addAttribute(name, value);
|
||||
}
|
||||
|
||||
public void removeAttribute(SOAPElement element, QName name) throws SOAPException {
|
||||
element.removeAttribute(name);
|
||||
}
|
||||
|
||||
public String getAttributeValue(SOAPElement element, QName name) throws SOAPException {
|
||||
return element.getAttributeValue(name);
|
||||
}
|
||||
@@ -151,10 +163,6 @@ public class Saaj13Implementation implements SaajImplementation {
|
||||
return element.getAllAttributesAsQNames();
|
||||
}
|
||||
|
||||
public Iterator getChildElements(SOAPElement element, QName name) throws SOAPException {
|
||||
return element.getChildElements(name);
|
||||
}
|
||||
|
||||
public SOAPEnvelope getEnvelope(SOAPMessage message) throws SOAPException {
|
||||
return message.getSOAPPart().getEnvelope();
|
||||
}
|
||||
|
||||
@@ -53,18 +53,24 @@ public interface SaajImplementation {
|
||||
/** Returns the writable <code>Result</code> of the given element. */
|
||||
Result getResult(SOAPElement element);
|
||||
|
||||
/** Returns the text of the given element */
|
||||
String getText(SOAPElement element);
|
||||
|
||||
/** Returns the text of the given element */
|
||||
void setText(SOAPElement element, String content) throws SOAPException;
|
||||
|
||||
/** Adds an attribute to the specified element. */
|
||||
void addAttribute(SOAPElement element, QName name, String value) throws SOAPException;
|
||||
|
||||
/** Removes an attribute from the specified element. */
|
||||
void removeAttribute(SOAPElement element, QName name) throws SOAPException;
|
||||
|
||||
/** Returns the attribute value * */
|
||||
String getAttributeValue(SOAPElement element, QName name) throws SOAPException;
|
||||
|
||||
/** Returns all attributes as an iterator of QNames. * */
|
||||
Iterator getAllAttibutes(SOAPElement element);
|
||||
|
||||
/** Returns an iterator over the child elements with the given name. */
|
||||
Iterator getChildElements(SOAPElement element, QName name) throws SOAPException;
|
||||
|
||||
/** Returns the envelope of the given message. */
|
||||
SOAPEnvelope getEnvelope(SOAPMessage message) throws SOAPException;
|
||||
|
||||
|
||||
@@ -57,6 +57,15 @@ class SaajSoapElement implements SoapElement {
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAttribute(QName name) {
|
||||
try {
|
||||
getImplementation().removeAttribute(element, name);
|
||||
}
|
||||
catch (SOAPException ex) {
|
||||
throw new SaajSoapElementException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public String getAttributeValue(QName name) {
|
||||
try {
|
||||
return getImplementation().getAttributeValue(element, name);
|
||||
|
||||
@@ -44,16 +44,6 @@ class SaajSoapHeader extends SaajSoapElement implements SoapHeader {
|
||||
return new SaajSoapHeaderElementIterator(iterator);
|
||||
}
|
||||
|
||||
public Iterator examineHeaderElements(QName name) throws SoapHeaderException {
|
||||
try {
|
||||
Iterator iterator = getImplementation().getChildElements(getSaajHeader(), name);
|
||||
return new SaajSoapHeaderElementIterator(iterator);
|
||||
}
|
||||
catch (SOAPException ex) {
|
||||
throw new SaajSoapHeaderException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator examineMustUnderstandHeaderElements(String actorOrRole) throws SoapHeaderException {
|
||||
Iterator iterator = getImplementation().examineMustUnderstandHeaderElements(getSaajHeader(), actorOrRole);
|
||||
return new SaajSoapHeaderElementIterator(iterator);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.ws.soap.saaj;
|
||||
|
||||
import javax.xml.soap.SOAPException;
|
||||
import javax.xml.soap.SOAPHeaderElement;
|
||||
import javax.xml.transform.Result;
|
||||
|
||||
@@ -54,6 +55,19 @@ class SaajSoapHeaderElement extends SaajSoapElement implements SoapHeaderElement
|
||||
getImplementation().setMustUnderstand(getSaajHeaderElement(), mustUnderstand);
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return getImplementation().getText(getSaajHeaderElement());
|
||||
}
|
||||
|
||||
public void setText(String content) {
|
||||
try {
|
||||
getImplementation().setText(getSaajHeaderElement(), content);
|
||||
}
|
||||
catch (SOAPException ex) {
|
||||
throw new SaajSoapHeaderException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected SOAPHeaderElement getSaajHeaderElement() {
|
||||
return (SOAPHeaderElement) getSaajElement();
|
||||
}
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.soap;
|
||||
package org.springframework.ws.soap.server;
|
||||
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.server.EndpointInterceptor;
|
||||
import org.springframework.ws.soap.SoapHeaderElement;
|
||||
|
||||
/**
|
||||
* SOAP-specific extension of the <code>EndpointInterceptor</code> interface. Allows for handling of SOAP faults, which
|
||||
@@ -27,17 +27,6 @@ import org.springframework.ws.server.EndpointInterceptor;
|
||||
*/
|
||||
public interface SoapEndpointInterceptor extends EndpointInterceptor {
|
||||
|
||||
/**
|
||||
* Processes the fault. Both request and response of the message context should be filled; the body of the response
|
||||
* message contains the fault.
|
||||
*
|
||||
* @param messageContext contains both request and response messages, the response should contains a SOAP Fault
|
||||
* @param endpoint chosen endpoint to invoke
|
||||
* @return <code>true</code> to continue processing of the reponse interceptor chain; <code>false</code> to indicate
|
||||
* blocking of the response handler chain.
|
||||
*/
|
||||
boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception;
|
||||
|
||||
/**
|
||||
* Given a <code>SoapHeaderElement</code>, return whether or not this <code>SoapEndpointInterceptor</code>
|
||||
* understands it.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.soap;
|
||||
package org.springframework.ws.soap.server;
|
||||
|
||||
import org.springframework.ws.server.EndpointMapping;
|
||||
|
||||
@@ -30,14 +30,10 @@ import org.springframework.ws.server.EndpointMapping;
|
||||
*/
|
||||
public interface SoapEndpointMapping extends EndpointMapping {
|
||||
|
||||
/**
|
||||
* Sets a single SOAP actor/actorOrRole to apply to all endpoints mapped by the delegate endpoint mapping.
|
||||
*/
|
||||
/** Sets a single SOAP actor/actorOrRole to apply to all endpoints mapped by the delegate endpoint mapping. */
|
||||
void setActorOrRole(String actorOrRole);
|
||||
|
||||
/**
|
||||
* Sets the array of SOAP actors/actorsOrRoles to apply to all endpoints mapped by the delegate endpoint mapping.
|
||||
*/
|
||||
/** Sets the array of SOAP actors/actorsOrRoles to apply to all endpoints mapped by the delegate endpoint mapping. */
|
||||
void setActorsOrRoles(String[] actorsOrRoles);
|
||||
|
||||
}
|
||||
@@ -22,14 +22,12 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.server.EndpointInterceptor;
|
||||
import org.springframework.ws.server.EndpointInvocationChain;
|
||||
import org.springframework.ws.server.MessageDispatcher;
|
||||
import org.springframework.ws.soap.SoapBody;
|
||||
import org.springframework.ws.soap.SoapEndpointInterceptor;
|
||||
import org.springframework.ws.soap.SoapFault;
|
||||
import org.springframework.ws.soap.SoapHeader;
|
||||
import org.springframework.ws.soap.SoapHeaderElement;
|
||||
@@ -43,13 +41,11 @@ import org.springframework.ws.soap.soap12.Soap12Header;
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see org.springframework.ws.soap.SoapMessage
|
||||
* @see org.springframework.ws.soap.SoapEndpointInterceptor
|
||||
* @see SoapEndpointInterceptor
|
||||
*/
|
||||
public class SoapMessageDispatcher extends MessageDispatcher {
|
||||
|
||||
/**
|
||||
* Default message used when creating a SOAP MustUnderstand fault.
|
||||
*/
|
||||
/** Default message used when creating a SOAP MustUnderstand fault. */
|
||||
public static final String DEFAULT_MUST_UNDERSTAND_FAULT =
|
||||
"One or more mandatory SOAP header blocks not understood";
|
||||
|
||||
@@ -130,7 +126,7 @@ public class SoapMessageDispatcher extends MessageDispatcher {
|
||||
* <code>SoapEndpointInterceptor</code>. If they are, returns <code>true</code>. If they are not, a SOAP fault is
|
||||
* created, and false is returned.
|
||||
*
|
||||
* @see org.springframework.ws.soap.SoapEndpointInterceptor#understands(org.springframework.ws.soap.SoapHeaderElement)
|
||||
* @see SoapEndpointInterceptor#understands(org.springframework.ws.soap.SoapHeaderElement)
|
||||
*/
|
||||
private boolean handleRequestForRole(EndpointInvocationChain mappedEndpoint,
|
||||
MessageContext messageContext,
|
||||
@@ -180,41 +176,4 @@ public class SoapMessageDispatcher extends MessageDispatcher {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger handleResponse or handleFault on the mapped EndpointInterceptors. Will just invoke said method on all
|
||||
* interceptors whose handleRequest invocation returned <code>true</code>, in addition to the last interceptor who
|
||||
* returned <code>false</code>.
|
||||
*
|
||||
* @param mappedEndpoint the mapped EndpointInvocationChain
|
||||
* @param interceptorIndex index of last interceptor that was called
|
||||
* @param messageContext the message context, whose request and response are filled
|
||||
* @see org.springframework.ws.server.EndpointInterceptor#handleResponse(org.springframework.ws.context.MessageContext,
|
||||
*Object)
|
||||
*/
|
||||
protected void triggerHandleResponse(EndpointInvocationChain mappedEndpoint,
|
||||
int interceptorIndex,
|
||||
MessageContext messageContext) throws Exception {
|
||||
if (mappedEndpoint != null && messageContext.hasResponse() &&
|
||||
!ObjectUtils.isEmpty(mappedEndpoint.getInterceptors())) {
|
||||
boolean hasFault = false;
|
||||
if (messageContext.getResponse() instanceof SoapMessage) {
|
||||
SoapMessage soapResponse = (SoapMessage) messageContext.getResponse();
|
||||
hasFault = soapResponse.getSoapBody().hasFault();
|
||||
}
|
||||
boolean resume = true;
|
||||
for (int i = interceptorIndex; resume && i >= 0; i--) {
|
||||
EndpointInterceptor interceptor = mappedEndpoint.getInterceptors()[i];
|
||||
if (hasFault) {
|
||||
if (interceptor instanceof SoapEndpointInterceptor) {
|
||||
SoapEndpointInterceptor soapEndpointInterceptor = (SoapEndpointInterceptor) interceptor;
|
||||
resume = soapEndpointInterceptor.handleFault(messageContext, mappedEndpoint.getEndpoint());
|
||||
}
|
||||
}
|
||||
else {
|
||||
resume = interceptor.handleResponse(messageContext, mappedEndpoint.getEndpoint());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@ import javax.xml.transform.Source;
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.server.endpoint.AbstractLoggingInterceptor;
|
||||
import org.springframework.ws.soap.SoapEndpointInterceptor;
|
||||
import org.springframework.ws.soap.SoapHeaderElement;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
import org.springframework.ws.soap.server.SoapEndpointInterceptor;
|
||||
|
||||
/**
|
||||
* SOAP-specific <code>EndpointInterceptor</code> that logs the complete request and response envelope of
|
||||
@@ -39,9 +39,7 @@ public class SoapEnvelopeLoggingInterceptor extends AbstractLoggingInterceptor i
|
||||
|
||||
private boolean logFault = true;
|
||||
|
||||
/**
|
||||
* Indicates whether a SOAP Fault should be logged. Default is <code>true</code>.
|
||||
*/
|
||||
/** Indicates whether a SOAP Fault should be logged. Default is <code>true</code>. */
|
||||
public void setLogFault(boolean logFault) {
|
||||
this.logFault = logFault;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.server.EndpointInvocationChain;
|
||||
import org.springframework.ws.server.EndpointMapping;
|
||||
import org.springframework.ws.soap.SoapEndpointMapping;
|
||||
import org.springframework.ws.soap.server.SoapEndpointInvocationChain;
|
||||
import org.springframework.ws.soap.server.SoapEndpointMapping;
|
||||
|
||||
/**
|
||||
* <code>EndpointMapping</code> implement that adds SOAP actors or roles to a delegate endpoint. Delegates to another
|
||||
@@ -46,9 +46,7 @@ public class DelegatingSoapEndpointMapping implements InitializingBean, SoapEndp
|
||||
|
||||
private String[] actorsOrRoles;
|
||||
|
||||
/**
|
||||
* Sets the delegate <code>EndpointMapping</code> to resolve the endpoint with.
|
||||
*/
|
||||
/** Sets the delegate <code>EndpointMapping</code> to resolve the endpoint with. */
|
||||
public void setDelegate(EndpointMapping delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@@ -22,10 +22,10 @@ import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.server.EndpointInterceptor;
|
||||
import org.springframework.ws.server.EndpointInvocationChain;
|
||||
import org.springframework.ws.server.endpoint.mapping.AbstractMapBasedEndpointMapping;
|
||||
import org.springframework.ws.soap.SoapEndpointMapping;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
import org.springframework.ws.soap.axiom.AxiomSoapMessageFactory;
|
||||
import org.springframework.ws.soap.server.SoapEndpointInvocationChain;
|
||||
import org.springframework.ws.soap.server.SoapEndpointMapping;
|
||||
|
||||
/**
|
||||
* Implementation of the <code>EndpointMapping</code> interface to map from <code>SOAPAction</code> headers to endpoint
|
||||
|
||||
@@ -307,6 +307,47 @@ public class MessageDispatcherTest extends TestCase {
|
||||
factoryControl.verify();
|
||||
}
|
||||
|
||||
public void testFaultFlow() throws Exception {
|
||||
MockControl adapterControl = MockControl.createControl(EndpointAdapter.class);
|
||||
EndpointAdapter adapterMock = (EndpointAdapter) adapterControl.getMock();
|
||||
dispatcher.setEndpointAdapters(Collections.singletonList(adapterMock));
|
||||
|
||||
Object endpoint = new Object();
|
||||
adapterControl.expectAndReturn(adapterMock.supports(endpoint), true);
|
||||
|
||||
MockControl mappingControl = MockControl.createControl(EndpointMapping.class);
|
||||
EndpointMapping mappingMock = (EndpointMapping) mappingControl.getMock();
|
||||
dispatcher.setEndpointMappings(Collections.singletonList(mappingMock));
|
||||
|
||||
MockControl interceptorControl = MockControl.createStrictControl(EndpointInterceptor.class);
|
||||
EndpointInterceptor interceptorMock = (EndpointInterceptor) interceptorControl.getMock();
|
||||
|
||||
interceptorControl.expectAndReturn(interceptorMock.handleRequest(messageContext, endpoint), true);
|
||||
adapterMock.invoke(messageContext, endpoint);
|
||||
interceptorControl.expectAndReturn(interceptorMock.handleFault(messageContext, endpoint), true);
|
||||
|
||||
EndpointInvocationChain chain =
|
||||
new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock});
|
||||
|
||||
mappingControl.expectAndReturn(mappingMock.getEndpoint(messageContext), chain);
|
||||
MockWebServiceMessage response = new MockWebServiceMessage();
|
||||
response.setFault(true);
|
||||
factoryControl.expectAndReturn(factoryMock.createWebServiceMessage(), response);
|
||||
|
||||
mappingControl.replay();
|
||||
interceptorControl.replay();
|
||||
adapterControl.replay();
|
||||
factoryControl.replay();
|
||||
// response required for interceptor invocation
|
||||
messageContext.getResponse();
|
||||
dispatcher.dispatch(messageContext);
|
||||
|
||||
mappingControl.verify();
|
||||
interceptorControl.verify();
|
||||
adapterControl.verify();
|
||||
factoryControl.verify();
|
||||
}
|
||||
|
||||
public void testNoEndpointFound() throws Exception {
|
||||
dispatcher.setEndpointMappings(Collections.EMPTY_LIST);
|
||||
try {
|
||||
|
||||
@@ -94,17 +94,6 @@ public abstract class AbstractSoapHeaderTestCase extends AbstractSoapElementTest
|
||||
assertHeaderElementEqual(headerElement, content);
|
||||
}
|
||||
|
||||
public void testExamineHeaderElements() throws Exception {
|
||||
QName qName = new QName("http://www.springframework.org", "localName", "spring");
|
||||
soapHeader.addHeaderElement(qName);
|
||||
Iterator iterator = soapHeader.examineHeaderElements(qName);
|
||||
assertNotNull("No Iterator returned", iterator);
|
||||
assertTrue("header element iterator has no elements", iterator.hasNext());
|
||||
SoapHeaderElement headerElement = (SoapHeaderElement) iterator.next();
|
||||
assertNotNull("No SoapHeaderElement returned", headerElement);
|
||||
assertEquals("Invalid qName for element", qName, headerElement.getName());
|
||||
}
|
||||
|
||||
protected void assertHeaderElementEqual(SoapHeaderElement headerElement, String expected) throws Exception {
|
||||
StringResult result = new StringResult();
|
||||
transformer.transform(headerElement.getSource(), result);
|
||||
|
||||
@@ -29,7 +29,6 @@ import org.easymock.MockControl;
|
||||
import org.springframework.ws.context.DefaultMessageContext;
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.soap.SoapBody;
|
||||
import org.springframework.ws.soap.SoapEndpointInterceptor;
|
||||
import org.springframework.ws.soap.SoapHeader;
|
||||
import org.springframework.ws.soap.SoapHeaderElement;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
|
||||
@@ -24,9 +24,9 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.soap.SoapBody;
|
||||
import org.springframework.ws.soap.SoapEndpointInterceptor;
|
||||
import org.springframework.ws.soap.SoapHeaderElement;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
import org.springframework.ws.soap.server.SoapEndpointInterceptor;
|
||||
|
||||
/**
|
||||
* Interceptor base class for interceptors that handle WS-Security.
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
</properties>
|
||||
<body>
|
||||
<release version="1.0-RC1">
|
||||
<action dev="poutsma" type="add">Pulled handleFault() from SoapEndpointInterceptor up to
|
||||
EndpointInterceptor
|
||||
</action>
|
||||
<action dev="poutsma" type="fix" issue="SWS-119">Remove IOExceptions from WebServiceTemplate. A runtime
|
||||
exception hierarchy has been created in org.springframework.ws.client.
|
||||
</action>
|
||||
|
||||
@@ -19,6 +19,16 @@ Upgrading from version 1.0-M3 to 1.0-RC1
|
||||
|
||||
The <<<WebServiceTemplate>> no longer declares an IOException for each method. Rather, an runtime exception
|
||||
hierarchy has been created in <<<org.springframework.ws.client>>>.
|
||||
|
||||
* EndpointInterceptor
|
||||
|
||||
The <<<EndpointInterceptor>>> has a <<<handleFault>>> method now, which gets invoked
|
||||
(rather than <<<handleResponse>>>) when <<<WebServiceMessage.hasFault()>>> is true for the response.
|
||||
|
||||
* SoapMessageDispatcher
|
||||
|
||||
* All of SoapMessageDispatcher's strategy interfaces (<<<SoapEndpointInterceptor>>>, <<<SoapEndpointMapping>>>)
|
||||
have been moved from <<<org.springframework.ws.soap>>> to <<<org.springframework.ws.soap.server>>>.
|
||||
|
||||
Upgrading from version 1.0-M2 to 1.0-M3
|
||||
|
||||
@@ -42,9 +52,9 @@ the project update their applications:
|
||||
|
||||
To make a clear distinction between server-side and client-side code, we had to move the various server-side classes.
|
||||
|
||||
* The <<<MessageDispatcher>>> has been moved to the <<<EndpointInvocationChain>>> to <<<org.springframework.ws.server>>> package.
|
||||
* The <<<MessageDispatcher>>> has been moved to the <<<org.springframework.ws.server>>> package.
|
||||
|
||||
* The <<<SoapMessageDispatcher>>> has been moved to the EndpointInvocationChain to <<<org.springframework.ws.soap.server>>> package.
|
||||
* The <<<SoapMessageDispatcher>>> has been moved to the <<<org.springframework.ws.soap.server>>> package.
|
||||
|
||||
* All of MessageDispatcher's strategy interfaces (<<<EndpointAdapter>>>, <<<EndpointInterceptor>>>, <<<EndpointMapping>>>, <<<EndpointExceptionResolver>>>) have been moved from <<<org.springframework.ws>>> to <<<org.springframework.ws.server>>>.
|
||||
|
||||
|
||||
@@ -46,12 +46,12 @@ public abstract class XPathExpressionFactory {
|
||||
static {
|
||||
// Check whether JAXP 1.3, or Jaxen are available
|
||||
if (JaxpVersion.getJaxpVersion() >= JaxpVersion.JAXP_13) {
|
||||
logger.info("JAXP 1.3 available");
|
||||
logger.debug("JAXP 1.3 available");
|
||||
}
|
||||
try {
|
||||
ClassUtils.forName(JAXEN_CLASS_NAME);
|
||||
jaxenAvailable = true;
|
||||
logger.info("Jaxen available");
|
||||
logger.debug("Jaxen available");
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
jaxenAvailable = false;
|
||||
|
||||
Reference in New Issue
Block a user