diff --git a/core/src/main/java/org/springframework/ws/client/core/WebServiceTemplate.java b/core/src/main/java/org/springframework/ws/client/core/WebServiceTemplate.java index 125947a0..42270857 100644 --- a/core/src/main/java/org/springframework/ws/client/core/WebServiceTemplate.java +++ b/core/src/main/java/org/springframework/ws/client/core/WebServiceTemplate.java @@ -74,23 +74,27 @@ import org.springframework.ws.transport.support.TransportUtils; * FaultMessageResolver} can be defined with with {@link #setFaultMessageResolver(FaultMessageResolver) * faultMessageResolver} property. If this property is set to null, no fault resolving is performed. *

- * This template uses the following algorithm for sending and receiving.

  1. Call to {@link #createConnection(URI) - * createConnection()}.
  2. Call to {@link WebServiceMessageFactory#createWebServiceMessage() + * This template uses the following algorithm for sending and receiving.
    1. Call {@link #createConnection(URI) + * createConnection()}.
    2. Call {@link WebServiceMessageFactory#createWebServiceMessage() * createWebServiceMessage()} on the registered message factory to create a request message.
    3. Invoke {@link * WebServiceMessageCallback#doWithMessage(WebServiceMessage) doWithMessage()} on the request callback, if any. This - * step stores content in the request message, based on Source, marshalling, etc.
    4. Call {@link + * step stores content in the request message, based on Source, marshalling, etc.
    5. Invoke {@link + * ClientInterceptor#handleRequest(MessageContext) handleRequest()} on the registered {@link + * #setInterceptors(ClientInterceptor[]) interceptors}. Interceptors are executed in order. If any of the interceptors + * creates a response message in the message context, skip to step 7.
    6. Call {@link * WebServiceConnection#send(WebServiceMessage) send()} on the connection.
    7. Call {@link * #hasError(WebServiceConnection,WebServiceMessage) hasError()} to check if the connection has an error. For an HTTP * transport, a status code other than 2xx indicates an error. However, since a status code of 500 can also * indicate a SOAP fault, the template verifies whether the error is not a fault.
      • If the connection has an * error, call the {@link #handleError handleError()} method, which by default throws a {@link - * WebServiceTransportException}.
      • If the connection has no error, continue with the next step.
    8. Invoke - * {@link WebServiceConnection#receive(WebServiceMessageFactory) receive} on the connection to read the response - * message, if any.
      • If no response was received, return null or false
      • - *
      • Call {@link #hasFault(WebServiceConnection,WebServiceMessage) hasFault()} to determine whether the response has a - * fault. If it has, call the {@link #handleFault handleFault()} method.
      • Otherwise, invoke {@link - * WebServiceMessageExtractor#extractData(WebServiceMessage) extractData()} on the response extractor, or {@link - * WebServiceMessageCallback#doWithMessage(WebServiceMessage) doWithMessage} on the response callback.
      + * WebServiceTransportException}.
    9. If the connection has no error, continue with the next step.
    10. + *
    11. Invoke {@link WebServiceConnection#receive(WebServiceMessageFactory) receive} on the connection to read the + * response message, if any.
      • If no response was received, return null or + * false
      • Call {@link #hasFault(WebServiceConnection,WebServiceMessage) hasFault()} to determine + * whether the response has a fault. If it has, call {@link ClientInterceptor#handleFault(MessageContext)} and the + * {@link #handleFault handleFault()} method.
      • Otherwise, invoke {@link ClientInterceptor#handleResponse(MessageContext)} + * and {@link WebServiceMessageExtractor#extractData(WebServiceMessage) extractData()} on the response extractor, or + * {@link WebServiceMessageCallback#doWithMessage(WebServiceMessage) doWithMessage} on the response callback.
      *
    12. Call to {@link WebServiceConnection#close() close} on the connection.
    * * @author Arjen Poutsma @@ -482,13 +486,14 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService messageContext.setResponse(response); } logResponse(messageContext); - triggerHandleResponse(interceptorIndex, messageContext); if (messageContext.hasResponse()) { - if (hasFault(connection, messageContext.getResponse())) { - return handleFault(connection, messageContext.getRequest(), messageContext.getResponse()); + if (!hasFault(connection, messageContext.getResponse())) { + triggerHandleResponse(interceptorIndex, messageContext); + return responseExtractor.extractData(messageContext.getResponse()); } else { - return responseExtractor.extractData(messageContext.getResponse()); + triggerHandleFault(interceptorIndex, messageContext); + return handleFault(connection, messageContext); } } else { @@ -500,6 +505,19 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService } } + /** Sends the request in the given message context over the connection. */ + private void sendRequest(WebServiceConnection connection, WebServiceMessage request) throws IOException { + if (messageTracingLogger.isTraceEnabled()) { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + request.writeTo(os); + messageTracingLogger.trace("Sent request [" + os.toString("UTF-8") + "]"); + } + else if (messageTracingLogger.isDebugEnabled()) { + messageTracingLogger.debug("Sent request [" + request + "]"); + } + connection.send(request); + } + /** * Determines whether the given connection or message context has an error. *

    @@ -538,6 +556,29 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService throw new WebServiceTransportException(connection.getErrorMessage()); } + private void logResponse(MessageContext messageContext) throws IOException { + if (messageContext.hasResponse()) { + if (messageTracingLogger.isTraceEnabled()) { + ByteArrayOutputStream requestStream = new ByteArrayOutputStream(); + messageContext.getRequest().writeTo(requestStream); + ByteArrayOutputStream responseStream = new ByteArrayOutputStream(); + messageContext.getResponse().writeTo(responseStream); + messageTracingLogger.trace("Received response [" + responseStream.toString("UTF-8") + + "] for request [" + requestStream.toString("UTF-8") + "]"); + } + else if (messageTracingLogger.isDebugEnabled()) { + messageTracingLogger.debug("Received response [" + messageContext.getResponse() + "] for request [" + + messageContext.getRequest() + "]"); + } + } + else { + if (logger.isDebugEnabled()) { + messageTracingLogger + .debug("Received no response for request [" + messageContext.getRequest() + "]"); + } + } + } + /** * Determines whether the given connection or message has a fault. *

    @@ -567,68 +608,9 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService } /** - * Handles an fault in the given response message. The default implementation invokes the {@link - * FaultMessageResolver fault resolver} if registered, or invokes {@link #handleError(WebServiceConnection, - * WebServiceMessage)} otherwise. - * - * @param connection the erronous connection - * @param request the corresponding request message - * @param response the fault response message - * @return the object to be returned from {@link #sendAndReceive(String,WebServiceMessageCallback, - * WebServiceMessageExtractor)}, if any - */ - protected Object handleFault(WebServiceConnection connection, WebServiceMessage request, WebServiceMessage response) - throws IOException { - if (getFaultMessageResolver() != null) { - logger.debug("Received Fault message for request [" + request + "]"); - getFaultMessageResolver().resolveFault(response); - return null; - } - else { - return handleError(connection, request); - } - } - - /** Sends the request in the given message context over the connection. */ - private void sendRequest(WebServiceConnection connection, WebServiceMessage request) throws IOException { - if (messageTracingLogger.isTraceEnabled()) { - ByteArrayOutputStream os = new ByteArrayOutputStream(); - request.writeTo(os); - messageTracingLogger.trace("Sent request [" + os.toString("UTF-8") + "]"); - } - else if (messageTracingLogger.isDebugEnabled()) { - messageTracingLogger.debug("Sent request [" + request + "]"); - } - connection.send(request); - } - - private void logResponse(MessageContext messageContext) throws IOException { - if (messageContext.hasResponse()) { - if (messageTracingLogger.isTraceEnabled()) { - ByteArrayOutputStream requestStream = new ByteArrayOutputStream(); - messageContext.getRequest().writeTo(requestStream); - ByteArrayOutputStream responseStream = new ByteArrayOutputStream(); - messageContext.getResponse().writeTo(responseStream); - messageTracingLogger.trace("Received response [" + responseStream.toString("UTF-8") + - "] for request [" + requestStream.toString("UTF-8") + "]"); - } - else if (messageTracingLogger.isDebugEnabled()) { - messageTracingLogger.debug("Received response [" + messageContext.getResponse() + "] for request [" + - messageContext.getRequest() + "]"); - } - } - else { - if (logger.isDebugEnabled()) { - messageTracingLogger - .debug("Received no response for request [" + messageContext.getRequest() + "]"); - } - } - } - - /** - * Trigger handleResponse or handleFault on the defined ClientInterceptors. Will just invoke said method on all - * interceptors whose handleRequest invocation returned true, in addition to the last interceptor who - * returned false. + * Trigger handleResponse on the defined ClientInterceptors. Will just invoke said method on all interceptors whose + * handleRequest invocation returned true, in addition to the last interceptor who returned + * false. * * @param interceptorIndex index of last interceptor that was called * @param messageContext the message context, whose request and response are filled @@ -636,24 +618,56 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService * @see ClientInterceptor#handleFault(MessageContext) */ private void triggerHandleResponse(int interceptorIndex, MessageContext messageContext) { - if (messageContext.hasResponse() && !ObjectUtils.isEmpty(interceptors)) { - boolean hasFault = false; - WebServiceMessage response = messageContext.getResponse(); - if (response instanceof FaultAwareWebServiceMessage) { - hasFault = ((FaultAwareWebServiceMessage) response).hasFault(); - } - boolean resume = true; - for (int i = interceptorIndex; resume && i >= 0; i--) { - if (!hasFault) { - resume = interceptors[i].handleResponse(messageContext); - } - else { - resume = interceptors[i].handleFault(messageContext); + if (messageContext.hasResponse() && interceptors != null) { + for (int i = interceptorIndex; i >= 0; i--) { + if (!interceptors[i].handleResponse(messageContext)) { + break; } } } } + /** + * Trigger handleFault on the defined ClientInterceptors. Will just invoke said method on all interceptors whose + * handleRequest invocation returned true, in addition to the last interceptor who returned + * false. + * + * @param interceptorIndex index of last interceptor that was called + * @param messageContext the message context, whose request and response are filled + * @see ClientInterceptor#handleResponse(MessageContext) + * @see ClientInterceptor#handleFault(MessageContext) + */ + private void triggerHandleFault(int interceptorIndex, MessageContext messageContext) { + if (messageContext.hasResponse() && interceptors != null) { + for (int i = interceptorIndex; i >= 0; i--) { + if (!interceptors[i].handleFault(messageContext)) { + break; + } + } + } + } + + /** + * Handles an fault in the given response message. The default implementation invokes the {@link + * FaultMessageResolver fault resolver} if registered, or invokes {@link #handleError(WebServiceConnection, + * WebServiceMessage)} otherwise. + * + * @param connection the erronous connection + * @param messageContext the message context + * @return the object to be returned from {@link #sendAndReceive(String,WebServiceMessageCallback, + * WebServiceMessageExtractor)}, if any + */ + protected Object handleFault(WebServiceConnection connection, MessageContext messageContext) throws IOException { + if (getFaultMessageResolver() != null) { + logger.debug("Received Fault message for request [" + messageContext.getRequest() + "]"); + getFaultMessageResolver().resolveFault(messageContext.getResponse()); + return null; + } + else { + return handleError(connection, messageContext.getRequest()); + } + } + /** Adapter to enable use of a WebServiceMessageCallback inside a WebServiceMessageExtractor. */ private static class WebServiceMessageCallbackMessageExtractor implements WebServiceMessageExtractor {