diff --git a/core/src/main/java/org/springframework/ws/WebServiceMessage.java b/core/src/main/java/org/springframework/ws/WebServiceMessage.java
index 3a10bd5f..19079510 100644
--- a/core/src/main/java/org/springframework/ws/WebServiceMessage.java
+++ b/core/src/main/java/org/springframework/ws/WebServiceMessage.java
@@ -62,4 +62,9 @@ public interface WebServiceMessage {
*/
boolean hasFault();
+ /**
+ * Returns the fault reason message, if any. Returns null when no fault is present.
+ */
+ String getFaultReason();
+
}
diff --git a/core/src/main/java/org/springframework/ws/client/core/FaultResolver.java b/core/src/main/java/org/springframework/ws/client/core/FaultResolver.java
new file mode 100644
index 00000000..ff893914
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/client/core/FaultResolver.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2007 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ws.client.core;
+
+import org.springframework.ws.WebServiceMessage;
+
+/**
+ * Defines the interface for objects than can resolve received {@link org.springframework.ws.WebServiceMessage}.
+ *
+ * @author Arjen Poutsma
+ */
+public interface FaultResolver {
+
+ /**
+ * Try to resolve the given fault message that got received.
+ *
+ * @param message the fault message
+ */
+ void resolveFault(WebServiceMessage message);
+
+}
diff --git a/core/src/main/java/org/springframework/ws/client/core/SimpleFaultResolver.java b/core/src/main/java/org/springframework/ws/client/core/SimpleFaultResolver.java
new file mode 100644
index 00000000..7d868c58
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/client/core/SimpleFaultResolver.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2007 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ws.client.core;
+
+import org.springframework.ws.WebServiceMessage;
+
+/**
+ * Simple fault resolver that simply throws a {@link WebServiceFaultException} when a fault occurs.
+ *
+ * @author Arjen Poutsma
+ * @see WebServiceFaultException
+ */
+public class SimpleFaultResolver implements FaultResolver {
+
+ /**
+ * Throws a new WebServiceFaultException.
+ */
+ public void resolveFault(WebServiceMessage message) {
+ throw new WebServiceFaultException(message.getFaultReason());
+ }
+}
diff --git a/core/src/main/java/org/springframework/ws/client/core/WebServiceFaultException.java b/core/src/main/java/org/springframework/ws/client/core/WebServiceFaultException.java
new file mode 100644
index 00000000..d2396446
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/client/core/WebServiceFaultException.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2007 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ws.client.core;
+
+import org.springframework.ws.client.WebServiceClientException;
+
+/**
+ * Thrown by SimpleFaultResolver when the response message has a fault.
+ *
+ * @author Arjen Poutsma
+ */
+public class WebServiceFaultException extends WebServiceClientException {
+
+ public WebServiceFaultException(String msg) {
+ super(msg);
+ }
+
+ public WebServiceFaultException(String msg, Throwable ex) {
+ super(msg, ex);
+ }
+}
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 dd8876e4..008dcacc 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
@@ -24,6 +24,7 @@ import javax.xml.transform.TransformerException;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
+import org.springframework.util.Assert;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.WebServiceClientException;
@@ -37,6 +38,8 @@ import org.springframework.ws.transport.WebServiceMessageSender;
*
WebServiceTemplate.
*
@@ -97,6 +102,21 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService
this.unmarshaller = unmarshaller;
}
+ /**
+ * Returns the fault resolver for this template.
+ */
+ public FaultResolver getFaultResolver() {
+ return faultResolver;
+ }
+
+ /**
+ * Sets the fault resolver for this template.
+ */
+ public void setFaultResolver(FaultResolver faultResolver) {
+ Assert.notNull(faultResolver, "faultResolver must not be null");
+ this.faultResolver = faultResolver;
+ }
+
public Object marshalSendAndReceive(final Object requestPayload) throws IOException {
return marshalSendAndReceive(requestPayload, null);
}
@@ -173,12 +193,15 @@ public class WebServiceTemplate extends WebServiceAccessor implements WebService
requestCallback.doInMessage(messageContext.getRequest());
}
getMessageSender().sendAndReceive(messageContext);
- if (messageContext.hasResponse()) {
- return messageContext.getResponse();
- }
- else {
+ if (!messageContext.hasResponse()) {
return null;
}
+ WebServiceMessage response = messageContext.getResponse();
+ if (response.hasFault()) {
+ getFaultResolver().resolveFault(response);
+ return null;
+ }
+ return response;
}
private void checkMarshallerAndUnmarshaller() throws IllegalStateException {
diff --git a/core/src/main/java/org/springframework/ws/pox/dom/DomPoxMessage.java b/core/src/main/java/org/springframework/ws/pox/dom/DomPoxMessage.java
index 0c57aa18..5cefbff0 100644
--- a/core/src/main/java/org/springframework/ws/pox/dom/DomPoxMessage.java
+++ b/core/src/main/java/org/springframework/ws/pox/dom/DomPoxMessage.java
@@ -73,6 +73,10 @@ public class DomPoxMessage implements PoxMessage {
return false;
}
+ public String getFaultReason() {
+ return null;
+ }
+
public void writeTo(OutputStream outputStream) throws IOException {
try {
if (outputStream instanceof TransportOutputStream) {
diff --git a/core/src/main/java/org/springframework/ws/soap/AbstractSoapMessage.java b/core/src/main/java/org/springframework/ws/soap/AbstractSoapMessage.java
index e1305057..395b5eab 100644
--- a/core/src/main/java/org/springframework/ws/soap/AbstractSoapMessage.java
+++ b/core/src/main/java/org/springframework/ws/soap/AbstractSoapMessage.java
@@ -63,6 +63,18 @@ public abstract class AbstractSoapMessage implements SoapMessage {
return getSoapBody().hasFault();
}
+ /**
+ * Returns getSoapBody().getFault().getFaultStringOrReason().
+ */
+ public String getFaultReason() {
+ if (hasFault()) {
+ return getSoapBody().getFault().getFaultStringOrReason();
+ }
+ else {
+ return null;
+ }
+ }
+
public SoapVersion getVersion() {
if (version == null) {
String envelopeNamespace = getEnvelope().getName().getNamespaceURI();
diff --git a/core/src/main/java/org/springframework/ws/soap/SoapFault.java b/core/src/main/java/org/springframework/ws/soap/SoapFault.java
index 9b12ef14..4f24e297 100644
--- a/core/src/main/java/org/springframework/ws/soap/SoapFault.java
+++ b/core/src/main/java/org/springframework/ws/soap/SoapFault.java
@@ -33,6 +33,12 @@ public interface SoapFault extends SoapElement {
*/
QName getFaultCode();
+ /**
+ * Returns the fault string or reason. For SOAP 1.1, this returns the fault string. For SOAP 1.2, this returns the
+ * fault reason for the default locale.
+ */
+ String getFaultStringOrReason();
+
/**
* Returns the fault actor or role. For SOAP 1.1, this returns the actor. For SOAP 1.2, this returns the role.
*/
diff --git a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap11Fault.java b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap11Fault.java
index 893456ea..a45d4081 100644
--- a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap11Fault.java
+++ b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap11Fault.java
@@ -35,7 +35,7 @@ class AxiomSoap11Fault extends AxiomSoapFault implements Soap11Fault {
super(axiomFault, axiomFactory);
}
- public String getFaultString() {
+ public String getFaultStringOrReason() {
if (axiomFault.getReason() != null) {
SOAPFaultText soapText = axiomFault.getReason().getFirstSOAPText();
if (soapText != null) {
diff --git a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap12Fault.java b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap12Fault.java
index 3f9166c1..15691945 100644
--- a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap12Fault.java
+++ b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoap12Fault.java
@@ -117,6 +117,10 @@ class AxiomSoap12Fault extends AxiomSoapFault implements Soap12Fault {
}
}
+ public String getFaultStringOrReason() {
+ return getFaultReasonText(Locale.getDefault());
+ }
+
public String getFaultReasonText(Locale locale) {
SOAPFaultReason faultReason = axiomFault.getReason();
String language = AxiomUtils.toLanguage(locale);
diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Fault.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Fault.java
index d08497b0..4333a2d4 100644
--- a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Fault.java
+++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Fault.java
@@ -46,7 +46,7 @@ class SaajSoap11Fault extends SaajSoapFault implements Soap11Fault {
}
}
- public String getFaultString() {
+ public String getFaultStringOrReason() {
return getImplementation().getFaultString(getSaajFault());
}
diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Fault.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Fault.java
index 3da1a116..34582434 100644
--- a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Fault.java
+++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Fault.java
@@ -90,6 +90,9 @@ class SaajSoap12Fault extends SaajSoapFault implements Soap12Fault {
catch (SOAPException ex) {
throw new SaajSoapFaultException(ex);
}
+ }
+ public String getFaultStringOrReason() {
+ return getFaultReasonText(Locale.getDefault());
}
}
diff --git a/core/src/main/java/org/springframework/ws/soap/soap11/Soap11Fault.java b/core/src/main/java/org/springframework/ws/soap/soap11/Soap11Fault.java
index d64814ba..9a255fc0 100644
--- a/core/src/main/java/org/springframework/ws/soap/soap11/Soap11Fault.java
+++ b/core/src/main/java/org/springframework/ws/soap/soap11/Soap11Fault.java
@@ -28,11 +28,6 @@ import org.springframework.ws.soap.SoapFault;
*/
public interface Soap11Fault extends SoapFault {
- /**
- * Returns the fault string.
- */
- String getFaultString();
-
/**
* Returns the locale of the fault string.
*/
diff --git a/core/src/test/java/org/springframework/ws/MockWebServiceMessage.java b/core/src/test/java/org/springframework/ws/MockWebServiceMessage.java
index 6e1a80c9..82306cc1 100644
--- a/core/src/test/java/org/springframework/ws/MockWebServiceMessage.java
+++ b/core/src/test/java/org/springframework/ws/MockWebServiceMessage.java
@@ -48,6 +48,8 @@ public class MockWebServiceMessage implements WebServiceMessage {
private boolean fault = false;
+ private String faultReason;
+
public MockWebServiceMessage() {
content = new StringBuffer();
}
@@ -110,6 +112,14 @@ public class MockWebServiceMessage implements WebServiceMessage {
this.fault = fault;
}
+ public String getFaultReason() {
+ return faultReason;
+ }
+
+ public void setFaultReason(String faultReason) {
+ this.faultReason = faultReason;
+ }
+
public void writeTo(OutputStream outputStream) throws IOException {
PrintWriter writer = new PrintWriter(outputStream);
writer.write(content.toString());
diff --git a/core/src/test/java/org/springframework/ws/client/core/SimpleFaultResolverTest.java b/core/src/test/java/org/springframework/ws/client/core/SimpleFaultResolverTest.java
new file mode 100644
index 00000000..0013835d
--- /dev/null
+++ b/core/src/test/java/org/springframework/ws/client/core/SimpleFaultResolverTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2007 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ws.client.core;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+import org.springframework.ws.WebServiceMessage;
+
+public class SimpleFaultResolverTest extends TestCase {
+
+ private SimpleFaultResolver resolver;
+
+ protected void setUp() throws Exception {
+ resolver = new SimpleFaultResolver();
+ }
+
+ public void testResolveFault() throws Exception {
+ MockControl messageControl = MockControl.createControl(WebServiceMessage.class);
+ WebServiceMessage messageMock = (WebServiceMessage) messageControl.getMock();
+ String message = "message";
+ messageControl.expectAndReturn(messageMock.getFaultReason(), message);
+ messageControl.replay();
+ try {
+ resolver.resolveFault(messageMock);
+ fail("WebServiceFaultExcpetion expected");
+ }
+ catch (WebServiceFaultException ex) {
+ // expected
+ assertEquals("Invalid exception message", message, ex.getMessage());
+ }
+ messageControl.verify();
+ }
+}
\ No newline at end of file
diff --git a/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateTest.java b/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateTest.java
index 44f2644c..4da342ff 100644
--- a/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateTest.java
+++ b/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateTest.java
@@ -84,6 +84,7 @@ public class WebServiceTemplateTest extends XMLTestCase {
public void testSendAndReceiveMessageResponse() throws Exception {
factoryControl.expectAndReturn(factoryMock.createWebServiceMessage(), requestMock);
factoryControl.expectAndReturn(factoryMock.createWebServiceMessage(), responseMock);
+ messageControl.expectAndReturn(responseMock.hasFault(), false);
template.setMessageSender(new ResponseMessageSender());
replayMockControls();
WebServiceMessage response = template.sendAndReceive(new WebServiceMessageCallback() {
@@ -108,9 +109,31 @@ public class WebServiceTemplateTest extends XMLTestCase {
verifyMockControls();
}
+ public void testSendAndReceiveMessageFaultResponse() throws Exception {
+ MockControl resolverControl = MockControl.createControl(FaultResolver.class);
+ FaultResolver resolverMock = (FaultResolver) resolverControl.getMock();
+ template.setFaultResolver(resolverMock);
+ factoryControl.expectAndReturn(factoryMock.createWebServiceMessage(), requestMock);
+ factoryControl.expectAndReturn(factoryMock.createWebServiceMessage(), responseMock);
+ messageControl.expectAndReturn(responseMock.hasFault(), true);
+ resolverMock.resolveFault(responseMock);
+ template.setMessageSender(new ResponseMessageSender());
+ replayMockControls();
+ resolverControl.replay();
+ WebServiceMessage response = template.sendAndReceive(new WebServiceMessageCallback() {
+ public void doInMessage(WebServiceMessage message) throws IOException {
+ assertEquals("Invalid request message", requestMock, message);
+ }
+ });
+ assertNull("Invalid response", response);
+ verifyMockControls();
+ resolverControl.verify();
+ }
+
public void testSendAndReceiveSourceResponse() throws Exception {
factoryControl.expectAndReturn(factoryMock.createWebServiceMessage(), requestMock);
factoryControl.expectAndReturn(factoryMock.createWebServiceMessage(), responseMock);
+ messageControl.expectAndReturn(responseMock.hasFault(), false);
messageControl.expectAndReturn(requestMock.getPayloadResult(), new StringResult());
Source expected = new StringSource("