From 18024d445f5014db2d4f1f6715e19b24d5d481bb Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Wed, 30 Apr 2008 19:19:57 +0000 Subject: [PATCH] SWS-330 --- .../ws/client/core/FaultMessageResolver.java | 2 +- .../ws/client/core/WebServiceTemplate.java | 41 +++++++++++++++---- .../http/AbstractHttpSenderConnection.java | 14 ++++++- .../WebServiceTemplateIntegrationTest.java | 1 + ...rviceMessageSenderIntegrationTestCase.java | 13 +++--- 5 files changed, 55 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/org/springframework/ws/client/core/FaultMessageResolver.java b/core/src/main/java/org/springframework/ws/client/core/FaultMessageResolver.java index 1fa5b0ec..b6f2e6b0 100644 --- a/core/src/main/java/org/springframework/ws/client/core/FaultMessageResolver.java +++ b/core/src/main/java/org/springframework/ws/client/core/FaultMessageResolver.java @@ -21,7 +21,7 @@ import java.io.IOException; import org.springframework.ws.WebServiceMessage; /** - * Defines the interface for objects than can resolve fault {@link WebServiceMessage}. + * Defines the interface for objects than can resolve fault {@link WebServiceMessage}s. * * @author Arjen Poutsma * @since 1.0.0 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 ccd6e1cc..5fb557c9 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 @@ -121,6 +121,8 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService private String defaultUri; + private boolean checkConnectionForError = true; + private boolean checkConnectionForFault = true; private ClientInterceptor[] interceptors; @@ -194,11 +196,30 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService } /** - * Indicates whether the {@link FaultAwareWebServiceConnection#hasFault() connection} should be checked for fault - * indicators (true), or whether we should rely on the {@link FaultAwareWebServiceMessage#hasFault() - * message} only (false). The default is true. + * Indicates whether the {@linkplain WebServiceConnection#hasError() connection} should be checked for error + * indicators (true), or whether these should be ignored (false). The default is + * true. *

- * When using a HTTP transport, this property defines whether to check the HTTP response status code for fault + * When using an HTTP transport, this property defines whether to check the HTTP response status code is in the 2xx + * Successful range. Both the SOAP specification and the WS-I Basic Profile define that a Web service must return a + * "200 OK" or "202 Accepted" HTTP status code for a normal response. Setting this property to false + * allows this template to deal with non-conformant services. + * + * @see #hasError(WebServiceConnection, WebServiceMessage) + * @see SOAP 1.1 specification + * @see WS-I Basic + * Profile + */ + public void setCheckConnectionForError(boolean checkConnectionForError) { + this.checkConnectionForError = checkConnectionForError; + } + + /** + * Indicates whether the {@linkplain FaultAwareWebServiceConnection#hasFault() connection} should be checked for + * fault indicators (true), or whether we should rely on the {@link + * FaultAwareWebServiceMessage#hasFault() message} only (false). The default is true. + *

+ * When using an HTTP transport, this property defines whether to check the HTTP response status code for fault * indicators. Both the SOAP specification and the WS-I Basic Profile define that a Web service must return a "500 * Internal Server Error" HTTP status code if the response envelope is a Fault. Setting this property to * false allows this template to deal with non-conformant services. @@ -540,8 +561,9 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService * @throws IOException in case of I/O errors */ protected boolean hasError(WebServiceConnection connection, WebServiceMessage request) throws IOException { - if (connection.hasError() && checkConnectionForFault) { - if (connection instanceof FaultAwareWebServiceConnection) { + if (checkConnectionForError && connection.hasError()) { + // could be a fault + if (checkConnectionForFault && connection instanceof FaultAwareWebServiceConnection) { FaultAwareWebServiceConnection faultConnection = (FaultAwareWebServiceConnection) connection; return !(faultConnection.hasFault() && request instanceof FaultAwareWebServiceMessage); } @@ -562,6 +584,9 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService * WebServiceMessageExtractor)}, if any */ protected Object handleError(WebServiceConnection connection, WebServiceMessage request) throws IOException { + if (logger.isDebugEnabled()) { + logger.debug("Received error for request [" + request + "]"); + } throw new WebServiceTransportException(connection.getErrorMessage()); } @@ -667,8 +692,10 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService * WebServiceMessageExtractor)}, if any */ protected Object handleFault(WebServiceConnection connection, MessageContext messageContext) throws IOException { - if (getFaultMessageResolver() != null) { + if (logger.isDebugEnabled()) { logger.debug("Received Fault message for request [" + messageContext.getRequest() + "]"); + } + if (getFaultMessageResolver() != null) { getFaultMessageResolver().resolveFault(messageContext.getResponse()); return null; } diff --git a/core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSenderConnection.java b/core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSenderConnection.java index b33c5665..9df2a86f 100644 --- a/core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSenderConnection.java +++ b/core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSenderConnection.java @@ -79,7 +79,7 @@ public abstract class AbstractHttpSenderConnection extends AbstractSenderConnect return isGzipResponse() ? new GZIPInputStream(inputStream) : inputStream; } - /** Determine whether the given response is a GZIP response. */ + /** Determine whether the response is a GZIP response. */ private boolean isGzipResponse() throws IOException { Iterator iterator = getResponseHeaders(HttpTransportConstants.HEADER_CONTENT_ENCODING); if (iterator.hasNext()) { @@ -106,7 +106,17 @@ public abstract class AbstractHttpSenderConnection extends AbstractSenderConnect */ public final boolean hasFault() throws IOException { - return HttpTransportConstants.STATUS_INTERNAL_SERVER_ERROR == getResponseCode(); + return HttpTransportConstants.STATUS_INTERNAL_SERVER_ERROR == getResponseCode() && isXmlResponse(); + } + + /** Determine whether the response is a XML message. */ + private boolean isXmlResponse() throws IOException { + Iterator iterator = getResponseHeaders(HttpTransportConstants.HEADER_CONTENT_TYPE); + if (iterator.hasNext()) { + String contentType = ((String) iterator.next()).toLowerCase(); + return contentType.indexOf("xml") != -1; + } + return false; } public final void setFault(boolean fault) { diff --git a/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateIntegrationTest.java b/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateIntegrationTest.java index 43fe38b2..c96368a8 100644 --- a/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateIntegrationTest.java +++ b/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateIntegrationTest.java @@ -132,6 +132,7 @@ public class WebServiceTemplateIntegrationTest extends XMLTestCase { //expected } template.setCheckConnectionForFault(false); + template.setCheckConnectionForError(false); try { template.sendSourceAndReceiveToResult("http://localhost:8888/soap/badRequestFault", new StringSource(content), result); diff --git a/core/src/test/java/org/springframework/ws/transport/http/AbstractHttpWebServiceMessageSenderIntegrationTestCase.java b/core/src/test/java/org/springframework/ws/transport/http/AbstractHttpWebServiceMessageSenderIntegrationTestCase.java index 5bf0a7dc..4bb4f2d9 100644 --- a/core/src/test/java/org/springframework/ws/transport/http/AbstractHttpWebServiceMessageSenderIntegrationTestCase.java +++ b/core/src/test/java/org/springframework/ws/transport/http/AbstractHttpWebServiceMessageSenderIntegrationTestCase.java @@ -35,6 +35,12 @@ import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; +import org.custommonkey.xmlunit.XMLTestCase; +import org.custommonkey.xmlunit.XMLUnit; +import org.mortbay.jetty.Server; +import org.mortbay.jetty.servlet.Context; +import org.mortbay.jetty.servlet.ServletHolder; + import org.springframework.util.FileCopyUtils; import org.springframework.ws.WebServiceMessage; import org.springframework.ws.WebServiceMessageFactory; @@ -45,12 +51,6 @@ import org.springframework.ws.transport.WebServiceConnection; import org.springframework.xml.transform.StringResult; import org.springframework.xml.transform.StringSource; -import org.custommonkey.xmlunit.XMLTestCase; -import org.custommonkey.xmlunit.XMLUnit; -import org.mortbay.jetty.Server; -import org.mortbay.jetty.servlet.Context; -import org.mortbay.jetty.servlet.ServletHolder; - public abstract class AbstractHttpWebServiceMessageSenderIntegrationTestCase extends XMLTestCase { private Server jettyServer; @@ -146,6 +146,7 @@ public abstract class AbstractHttpWebServiceMessageSenderIntegrationTestCase ext public void testSendAndReceiveFault() throws Exception { MyServlet servlet = new MyServlet(); servlet.setResponseStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + servlet.setResponse(true); jettyContext.addServlet(new ServletHolder(servlet), "/"); jettyServer.start(); FaultAwareWebServiceConnection connection =