diff --git a/core/src/main/java/org/springframework/ws/WebServiceException.java b/core/src/main/java/org/springframework/ws/WebServiceException.java
index 703c8d44..d2c96455 100644
--- a/core/src/main/java/org/springframework/ws/WebServiceException.java
+++ b/core/src/main/java/org/springframework/ws/WebServiceException.java
@@ -16,8 +16,6 @@
package org.springframework.ws;
-import java.io.Serializable;
-
import org.springframework.core.NestedRuntimeException;
/**
@@ -26,7 +24,7 @@ import org.springframework.core.NestedRuntimeException;
* @author Arjen Poutsma
* @since 1.0.0
*/
-public abstract class WebServiceException extends NestedRuntimeException implements Serializable {
+public abstract class WebServiceException extends NestedRuntimeException {
/**
* Create a new instance of the WebServiceException class.
diff --git a/core/src/main/java/org/springframework/ws/client/support/interceptor/AbstractValidatingInterceptor.java b/core/src/main/java/org/springframework/ws/client/support/interceptor/AbstractValidatingInterceptor.java
new file mode 100644
index 00000000..7269a0b1
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/client/support/interceptor/AbstractValidatingInterceptor.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2008 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.support.interceptor;
+
+import java.io.IOException;
+import javax.xml.transform.Source;
+
+import org.xml.sax.SAXParseException;
+
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.core.io.Resource;
+import org.springframework.util.Assert;
+import org.springframework.util.ObjectUtils;
+import org.springframework.util.StringUtils;
+import org.springframework.ws.WebServiceMessage;
+import org.springframework.ws.client.WebServiceClientException;
+import org.springframework.ws.client.WebServiceIOException;
+import org.springframework.ws.context.MessageContext;
+import org.springframework.xml.transform.TransformerObjectSupport;
+import org.springframework.xml.validation.XmlValidator;
+import org.springframework.xml.validation.XmlValidatorFactory;
+import org.springframework.xml.xsd.XsdSchema;
+import org.springframework.xml.xsd.XsdSchemaCollection;
+
+/**
+ * Abstract base class for {@link ClientInterceptor} implementations that validate part of the message using a schema.
+ * The exact message part is determined by the {@link #getValidationRequestSource(WebServiceMessage)} and {@link
+ * #getValidationResponseSource(WebServiceMessage)} template methods.
+ *
validateRequest and validateResponse properties.
+ *
+ * @author Arjen Poutsma
+ * @see #getValidationRequestSource(WebServiceMessage)
+ * @see #getValidationResponseSource(WebServiceMessage)
+ * @since 1.5.4
+ */
+public abstract class AbstractValidatingInterceptor extends TransformerObjectSupport
+ implements ClientInterceptor, InitializingBean {
+
+ private String schemaLanguage = XmlValidatorFactory.SCHEMA_W3C_XML;
+
+ private Resource[] schemas;
+
+ private boolean validateRequest = true;
+
+ private boolean validateResponse = false;
+
+ private XmlValidator validator;
+
+ public String getSchemaLanguage() {
+ return schemaLanguage;
+ }
+
+ /**
+ * Sets the schema language. Default is the W3C XML Schema: http://www.w3.org/2001/XMLSchema".
+ *
+ * @see XmlValidatorFactory#SCHEMA_W3C_XML
+ * @see XmlValidatorFactory#SCHEMA_RELAX_NG
+ */
+ public void setSchemaLanguage(String schemaLanguage) {
+ this.schemaLanguage = schemaLanguage;
+ }
+
+ /** Returns the schema resources to use for validation. */
+ public Resource[] getSchemas() {
+ return schemas;
+ }
+
+ /**
+ * Sets the schema resource to use for validation. Setting this property, {@link
+ * #setXsdSchemaCollection(XsdSchemaCollection) xsdSchemaCollection}, {@link #setSchema(Resource) schema}, or {@link
+ * #setSchemas(Resource[]) schemas} is required.
+ */
+ public void setSchema(Resource schema) {
+ setSchemas(new Resource[]{schema});
+ }
+
+ /**
+ * Sets the schema resources to use for validation. Setting this property, {@link
+ * #setXsdSchemaCollection(XsdSchemaCollection) xsdSchemaCollection}, {@link #setSchema(Resource) schema}, or {@link
+ * #setSchemas(Resource[]) schemas} is required.
+ */
+ public void setSchemas(Resource[] schemas) {
+ Assert.notEmpty(schemas, "schemas must not be empty or null");
+ for (int i = 0; i < schemas.length; i++) {
+ Assert.notNull(schemas[i], "schema must not be null");
+ Assert.isTrue(schemas[i].exists(), "schema \"" + schemas[i] + "\" does not exit");
+ }
+ this.schemas = schemas;
+ }
+
+ /**
+ * Sets the {@link XsdSchema} to use for validation. Setting this property, {@link
+ * #setXsdSchemaCollection(XsdSchemaCollection) xsdSchemaCollection}, {@link #setSchema(Resource) schema}, or {@link
+ * #setSchemas(Resource[]) schemas} is required.
+ *
+ * @param schema the xsd schema to use
+ * @throws java.io.IOException in case of I/O errors
+ */
+ public void setXsdSchema(XsdSchema schema) throws IOException {
+ this.validator = schema.createValidator();
+ }
+
+ /**
+ * Sets the {@link XsdSchemaCollection} to use for validation. Setting this property, {@link
+ * #setXsdSchema(XsdSchema) xsdSchema}, {@link #setSchema(Resource) schema}, or {@link #setSchemas(Resource[])
+ * schemas} is required.
+ *
+ * @param schemaCollection the xsd schema collection to use
+ * @throws java.io.IOException in case of I/O errors
+ */
+ public void setXsdSchemaCollection(XsdSchemaCollection schemaCollection) throws IOException {
+ this.validator = schemaCollection.createValidator();
+ }
+
+ /** Indicates whether the request should be validated against the schema. Default is true. */
+ public void setValidateRequest(boolean validateRequest) {
+ this.validateRequest = validateRequest;
+ }
+
+ /** Indicates whether the response should be validated against the schema. Default is false. */
+ public void setValidateResponse(boolean validateResponse) {
+ this.validateResponse = validateResponse;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ if (validator == null && !ObjectUtils.isEmpty(schemas)) {
+ 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);
+ }
+ Assert.notNull(validator, "Setting 'schema', 'schemas', 'xsdSchema', or 'xsdSchemaCollection' is required");
+ }
+
+ /**
+ * Validates the request message in the given message context. Validation only occurs if {@link
+ * #setValidateRequest(boolean) validateRequest} is set to true, which is the default.
+ *
+ * Returns true if the request is valid, or false if it isn't.
+ *
+ * @param messageContext the message context
+ * @return true if the message is valid; false otherwise
+ * @see #setValidateRequest(boolean)
+ */
+ public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
+ if (validateRequest) {
+ Source requestSource = getValidationRequestSource(messageContext.getRequest());
+ if (requestSource != null) {
+ SAXParseException[] errors;
+ try {
+ errors = validator.validate(requestSource);
+ }
+ catch (IOException e) {
+ throw new WebServiceIOException("Could not validate response: " + e.getMessage(), e);
+ }
+ if (!ObjectUtils.isEmpty(errors)) {
+ return handleRequestValidationErrors(messageContext, errors);
+ }
+ else if (logger.isDebugEnabled()) {
+ logger.debug("Request message validated");
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Template method that is called when the request message contains validation errors.
+ *
+ * Default implementation logs all errors, and throws a {@link WebServiceValidationException}. Subclasses can
+ * override this method to customize this behavior.
+ *
+ * @param messageContext the message context
+ * @param errors the validation errors
+ * @return true to continue processing the request, false otherwise
+ */
+ protected boolean handleRequestValidationErrors(MessageContext messageContext, SAXParseException[] errors) {
+ for (int i = 0; i < errors.length; i++) {
+ logger.error("XML validation error on request: " + errors[i].getMessage());
+ }
+ throw new WebServiceValidationException(errors);
+ }
+
+ /**
+ * Validates the response message in the given message context. Validation only occurs if {@link
+ * #setValidateResponse(boolean) validateResponse} is set to true, which is not the
+ * default.
+ *
+ * Returns true if the request is valid, or false if it isn't.
+ *
+ * @param messageContext the message context.
+ * @return true if the response is valid; false otherwise
+ * @see #setValidateResponse(boolean)
+ */
+ public boolean handleResponse(MessageContext messageContext) throws WebServiceClientException {
+ if (validateResponse) {
+ Source responseSource = getValidationResponseSource(messageContext.getResponse());
+ if (responseSource != null) {
+ SAXParseException[] errors;
+ try {
+ errors = validator.validate(responseSource);
+ }
+ catch (IOException e) {
+ throw new WebServiceIOException("Could not validate response: " + e.getMessage(), e);
+ }
+ if (!ObjectUtils.isEmpty(errors)) {
+ return handleResponseValidationErrors(messageContext, errors);
+ }
+ else if (logger.isDebugEnabled()) {
+ logger.debug("Response message validated");
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Template method that is called when the response message contains validation errors.
+ *
+ * Default implementation logs all errors, and returns false, i.e. do not cot continue to process the
+ * respone interceptor chain.
+ *
+ * @param messageContext the message context
+ * @param errors the validation errors
+ * @return true to continue the reponse interceptor chain, false (the default) otherwise
+ */
+ protected boolean handleResponseValidationErrors(MessageContext messageContext, SAXParseException[] errors)
+ throws WebServiceValidationException {
+ for (int i = 0; i < errors.length; i++) {
+ logger.warn("XML validation error on response: " + errors[i].getMessage());
+ }
+ return false;
+ }
+
+ /** Does nothing by default. Faults are not validated. */
+ public boolean handleFault(MessageContext messageContext) throws WebServiceClientException {
+ return true;
+ }
+
+ /**
+ * Abstract template method that returns the part of the request message that is to be validated.
+ *
+ * @param request the request message
+ * @return the part of the message that is to validated, or null not to validate anything
+ */
+ protected abstract Source getValidationRequestSource(WebServiceMessage request);
+
+ /**
+ * Abstract template method that returns the part of the response message that is to be validated.
+ *
+ * @param response the response message
+ * @return the part of the message that is to validated, or null not to validate anything
+ */
+ protected abstract Source getValidationResponseSource(WebServiceMessage response);
+}
diff --git a/core/src/main/java/org/springframework/ws/client/support/interceptor/PayloadValidatingInterceptor.java b/core/src/main/java/org/springframework/ws/client/support/interceptor/PayloadValidatingInterceptor.java
new file mode 100644
index 00000000..65662832
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/client/support/interceptor/PayloadValidatingInterceptor.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2006 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.support.interceptor;
+
+import javax.xml.transform.Source;
+
+import org.springframework.ws.WebServiceMessage;
+
+/**
+ * Client-side interceptor that validates the contents of WebServiceMessages using a schema. Allows for
+ * both W3C XML and RELAX NG schemas.
+ *
+ * When the payload is invalid, this interceptor stops processing of the interceptor chain.
+ *
+ * The schema to validate against is set with the schema property or schemas property. By
+ * default, only the request message is validated, but this behaviour can be changed using the
+ * validateRequest and validateResponse properties. Responses that contains faults are not
+ * validated.
+ *
+ * @author Stefan Schmidt
+ * @author Arjen Poutsma
+ * @see #setSchema(org.springframework.core.io.Resource)
+ * @see #setSchemas(org.springframework.core.io.Resource[])
+ * @see #setValidateRequest(boolean)
+ * @see #setValidateResponse(boolean)
+ * @since 1.5.4
+ */
+public class PayloadValidatingInterceptor extends AbstractValidatingInterceptor {
+
+ /**
+ * Returns the part of the request message that is to be validated. Default
+ *
+ * @param request the request message
+ * @return the part of the message that is to validated, or null not to validate anything
+ */
+ protected Source getValidationRequestSource(WebServiceMessage request) {
+ return request.getPayloadSource();
+ }
+
+ /**
+ * Returns the part of the response message that is to be validated.
+ *
+ * @param response the response message
+ * @return the part of the message that is to validated, or null not to validate anything
+ */
+ protected Source getValidationResponseSource(WebServiceMessage response) {
+ return response.getPayloadSource();
+ }
+}
diff --git a/core/src/main/java/org/springframework/ws/client/support/interceptor/WebServiceValidationException.java b/core/src/main/java/org/springframework/ws/client/support/interceptor/WebServiceValidationException.java
new file mode 100644
index 00000000..1a27626d
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/client/support/interceptor/WebServiceValidationException.java
@@ -0,0 +1,41 @@
+package org.springframework.ws.client.support.interceptor;
+
+import org.xml.sax.SAXParseException;
+
+import org.springframework.ws.client.WebServiceClientException;
+
+/**
+ * Exception thrown whenever a validation error occurs on the client-side.
+ *
+ * @author Stefan Schmidt
+ * @author Arjen Poutsma
+ * @since 1.5.4
+ */
+public class WebServiceValidationException extends WebServiceClientException {
+
+ private SAXParseException[] validationErrors;
+
+ /**
+ * Create a new instance of the WebServiceValidationException class.
+ *
+ * @param msg the detail message
+ */
+ public WebServiceValidationException(SAXParseException[] validationErrors) {
+ super(createMessage(validationErrors));
+ this.validationErrors = validationErrors;
+ }
+
+ private static String createMessage(SAXParseException[] validationErrors) {
+ StringBuffer buffer = new StringBuffer("XML validation error on response: ");
+
+ for (int i = 0; i < validationErrors.length; i++) {
+ buffer.append(validationErrors[i].getMessage());
+ }
+ return buffer.toString();
+ }
+
+ /** Returns the validation errors. */
+ public SAXParseException[] getValidationErrors() {
+ return validationErrors;
+ }
+}
diff --git a/core/src/main/java/org/springframework/ws/client/support/interceptor/package.html b/core/src/main/java/org/springframework/ws/client/support/interceptor/package.html
index 11d590a6..56c1c49e 100644
--- a/core/src/main/java/org/springframework/ws/client/support/interceptor/package.html
+++ b/core/src/main/java/org/springframework/ws/client/support/interceptor/package.html
@@ -1,5 +1,5 @@
-Provides the ClientInterceptor interface.
+Provides the ClientInterceptor interface, and validating interceptors.
diff --git a/core/src/test/java/org/springframework/ws/client/support/interceptor/PayloadValidatingInterceptorTest.java b/core/src/test/java/org/springframework/ws/client/support/interceptor/PayloadValidatingInterceptorTest.java
new file mode 100644
index 00000000..ab92ca27
--- /dev/null
+++ b/core/src/test/java/org/springframework/ws/client/support/interceptor/PayloadValidatingInterceptorTest.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2006 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.support.interceptor;
+
+import java.io.InputStream;
+import javax.xml.XMLConstants;
+import javax.xml.soap.MessageFactory;
+import javax.xml.soap.SOAPConstants;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamSource;
+
+import org.custommonkey.xmlunit.XMLTestCase;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.ws.MockWebServiceMessage;
+import org.springframework.ws.MockWebServiceMessageFactory;
+import org.springframework.ws.client.WebServiceClientException;
+import org.springframework.ws.context.DefaultMessageContext;
+import org.springframework.ws.context.MessageContext;
+import org.springframework.ws.soap.SoapMessage;
+import org.springframework.ws.soap.saaj.SaajSoapMessage;
+import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
+import org.springframework.ws.soap.saaj.support.SaajUtils;
+import org.springframework.xml.xsd.SimpleXsdSchema;
+
+public class PayloadValidatingInterceptorTest extends XMLTestCase {
+
+ private PayloadValidatingInterceptor interceptor;
+
+ private MessageContext context;
+
+ private SaajSoapMessageFactory soap11Factory;
+
+ private Transformer transformer;
+
+ private static final String INVALID_MESSAGE = "invalidMessage.xml";
+
+ private static final String SCHEMA = "schema.xsd";
+
+ private static final String VALID_MESSAGE = "validMessage.xml";
+
+ private static final String PRODUCT_SCHEMA = "productSchema.xsd";
+
+ private static final String SIZE_SCHEMA = "sizeSchema.xsd";
+
+ private static final String VALID_SOAP_MESSAGE = "validSoapMessage.xml";
+
+ private static final String SCHEMA2 = "schema2.xsd";
+
+ protected void setUp() throws Exception {
+ interceptor = new PayloadValidatingInterceptor();
+ interceptor.setSchema(new ClassPathResource(SCHEMA, getClass()));
+ interceptor.setValidateRequest(true);
+ interceptor.setValidateResponse(true);
+ interceptor.afterPropertiesSet();
+
+ soap11Factory = new SaajSoapMessageFactory(MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL));
+
+ transformer = TransformerFactory.newInstance().newTransformer();
+ }
+
+ public void testHandleInvalidRequest() throws Exception {
+ SoapMessage invalidMessage = (SoapMessage) soap11Factory.createWebServiceMessage();
+ InputStream inputStream = getClass().getResourceAsStream(INVALID_MESSAGE);
+ transformer.transform(new StreamSource(inputStream), invalidMessage.getPayloadResult());
+ context = new DefaultMessageContext(invalidMessage, soap11Factory);
+
+ boolean validated;
+ try {
+ validated = interceptor.handleRequest(context);
+ }
+ catch (WebServiceClientException e) {
+ validated = false;
+ assertNotNull("No exception details provided in WebServiceClientException", e.getMessage());
+ }
+ assertFalse("Invalid response from interceptor", validated);
+ }
+
+ public void testHandlerInvalidRequest() throws Exception {
+ MockWebServiceMessage request = new MockWebServiceMessage();
+ request.setPayload(new ClassPathResource(INVALID_MESSAGE, getClass()));
+ context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
+
+ boolean validated;
+ try {
+ validated = interceptor.handleRequest(context);
+ }
+ catch (WebServiceClientException e) {
+ validated = false;
+ assertNotNull("No exception details provided in WebServiceClientException", e.getMessage());
+ }
+ assertFalse("Invalid response from interceptor", validated);
+ }
+
+ public void testHandleValidRequest() throws Exception {
+ MockWebServiceMessage request = new MockWebServiceMessage();
+ request.setPayload(new ClassPathResource(VALID_MESSAGE, getClass()));
+ context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
+ boolean result = interceptor.handleRequest(context);
+ assertTrue("Invalid response from interceptor", result);
+ assertFalse("Response set", context.hasResponse());
+ }
+
+ public void testHandleInvalidResponse() throws Exception {
+ MockWebServiceMessage request = new MockWebServiceMessage();
+ context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
+ MockWebServiceMessage response = (MockWebServiceMessage) context.getResponse();
+ response.setPayload(new ClassPathResource(INVALID_MESSAGE, getClass()));
+
+ boolean result = interceptor.handleResponse(context);
+ assertFalse("Invalid response from interceptor", result);
+ }
+
+ public void testHandleValidResponse() throws Exception {
+ MockWebServiceMessage request = new MockWebServiceMessage();
+ context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
+ MockWebServiceMessage response = (MockWebServiceMessage) context.getResponse();
+ response.setPayload(new ClassPathResource(VALID_MESSAGE, getClass()));
+ boolean result = interceptor.handleResponse(context);
+ assertTrue("Invalid response from interceptor", result);
+ }
+
+ public void testNamespacesInType() throws Exception {
+ // Make sure we use Xerces for this testcase: the JAXP implementation used internally by JDK 1.5 has a bug
+ // See http://opensource.atlassian.com/projects/spring/browse/SWS-35
+ String previousSchemaFactory =
+ System.getProperty("javax.xml.validation.SchemaFactory:" + XMLConstants.W3C_XML_SCHEMA_NS_URI, "");
+ System.setProperty("javax.xml.validation.SchemaFactory:" + XMLConstants.W3C_XML_SCHEMA_NS_URI,
+ "org.apache.xerces.jaxp.validation.XMLSchemaFactory");
+ try {
+ PayloadValidatingInterceptor interceptor = new PayloadValidatingInterceptor();
+ interceptor.setSchema(new ClassPathResource(SCHEMA2, PayloadValidatingInterceptorTest.class));
+ interceptor.afterPropertiesSet();
+ MessageFactory messageFactory = MessageFactory.newInstance();
+ SOAPMessage saajMessage =
+ SaajUtils.loadMessage(new ClassPathResource(VALID_SOAP_MESSAGE, getClass()), messageFactory);
+ context = new DefaultMessageContext(new SaajSoapMessage(saajMessage),
+ new SaajSoapMessageFactory(messageFactory));
+
+ boolean result = interceptor.handleRequest(context);
+ assertTrue("Invalid response from interceptor", result);
+ assertFalse("Response set", context.hasResponse());
+ }
+ finally {
+ // Reset the property
+ System.setProperty("javax.xml.validation.SchemaFactory:" + XMLConstants.W3C_XML_SCHEMA_NS_URI,
+ previousSchemaFactory);
+ }
+ }
+
+ public void testNonExistingSchema() throws Exception {
+ try {
+ interceptor.setSchema(new ClassPathResource("invalid"));
+ interceptor.afterPropertiesSet();
+ fail("IllegalArgumentException expected");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ public void testHandlerInvalidRequestMultipleSchemas() throws Exception {
+ interceptor.setSchemas(new Resource[]{new ClassPathResource(PRODUCT_SCHEMA, getClass()),
+ new ClassPathResource(SIZE_SCHEMA, getClass())});
+ interceptor.afterPropertiesSet();
+ MockWebServiceMessage request = new MockWebServiceMessage(new ClassPathResource(INVALID_MESSAGE, getClass()));
+ context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
+
+ boolean validated;
+ try {
+ validated = interceptor.handleRequest(context);
+ }
+ catch (WebServiceClientException e) {
+ validated = false;
+ assertNotNull("No exception details provided in WebServiceClientException", e.getMessage());
+ }
+ assertFalse("Invalid response from interceptor", validated);
+ }
+
+ public void testHandleValidRequestMultipleSchemas() throws Exception {
+ interceptor.setSchemas(new Resource[]{new ClassPathResource(PRODUCT_SCHEMA, getClass()),
+ new ClassPathResource(SIZE_SCHEMA, getClass())});
+ interceptor.afterPropertiesSet();
+ MockWebServiceMessage request = new MockWebServiceMessage(new ClassPathResource(VALID_MESSAGE, getClass()));
+ context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
+
+ boolean result = interceptor.handleRequest(context);
+ assertTrue("Invalid response from interceptor", result);
+ assertFalse("Response set", context.hasResponse());
+ }
+
+ public void testHandleInvalidResponseMultipleSchemas() throws Exception {
+ interceptor.setSchemas(new Resource[]{new ClassPathResource(PRODUCT_SCHEMA, getClass()),
+ new ClassPathResource(SIZE_SCHEMA, getClass())});
+ interceptor.afterPropertiesSet();
+ MockWebServiceMessage request = new MockWebServiceMessage();
+ context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
+ MockWebServiceMessage response = (MockWebServiceMessage) context.getResponse();
+ response.setPayload(new ClassPathResource(INVALID_MESSAGE, getClass()));
+ boolean result = interceptor.handleResponse(context);
+ assertFalse("Invalid response from interceptor", result);
+ }
+
+ public void testHandleValidResponseMultipleSchemas() throws Exception {
+ interceptor.setSchemas(new Resource[]{new ClassPathResource(PRODUCT_SCHEMA, getClass()),
+ new ClassPathResource(SIZE_SCHEMA, getClass())});
+ interceptor.afterPropertiesSet();
+ MockWebServiceMessage request = new MockWebServiceMessage();
+ context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
+ MockWebServiceMessage response = (MockWebServiceMessage) context.getResponse();
+ response.setPayload(new ClassPathResource(VALID_MESSAGE, getClass()));
+ boolean result = interceptor.handleResponse(context);
+ assertTrue("Invalid response from interceptor", result);
+ }
+
+ public void testXsdSchema() throws Exception {
+ PayloadValidatingInterceptor interceptor = new PayloadValidatingInterceptor();
+ SimpleXsdSchema schema = new SimpleXsdSchema(new ClassPathResource(SCHEMA, getClass()));
+ schema.afterPropertiesSet();
+ interceptor.setXsdSchema(schema);
+ interceptor.setValidateRequest(true);
+ interceptor.setValidateResponse(true);
+ interceptor.afterPropertiesSet();
+ MockWebServiceMessage request = new MockWebServiceMessage();
+ request.setPayload(new ClassPathResource(VALID_MESSAGE, getClass()));
+ context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
+ boolean result = interceptor.handleRequest(context);
+ assertTrue("Invalid response from interceptor", result);
+ assertFalse("Response set", context.hasResponse());
+ }
+}
diff --git a/core/src/test/resources/org/springframework/ws/client/support/interceptor/invalidMessage.xml b/core/src/test/resources/org/springframework/ws/client/support/interceptor/invalidMessage.xml
new file mode 100644
index 00000000..809bda71
--- /dev/null
+++ b/core/src/test/resources/org/springframework/ws/client/support/interceptor/invalidMessage.xml
@@ -0,0 +1,4 @@
+
+