Reputation: 9134
I have a java web service application built with jaxb and spring webservice.
I have a complex type in a xsd like this:
...
<complexType name="GetRecordsRequest">
<sequence>
<element name="maxRecords" type="int" maxOccurs="1" minOccurs="1"/>
</sequence>
</complexType>
...
Using xjc, I had the jaxb class generated from xsd:
public class GetRecordsRequest {
protected int maxRecords;
public int getMaxRecords() {
return maxRecords;
}
public void setMaxRecords(int value) {
this.maxRecords = value;
}
}
I used PayloadValidatingInterceptor in spring context.xml to make sure user can't input anything besides integer for maxRecords:
<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
<property name="interceptors">
<list>
<ref local="validatingInterceptor" />
</list>
</property>
</bean>
<bean id="validatingInterceptor" class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
<property name="schema" value="/WEB-INF/schemas/webservice.xsd" />
<property name="validateRequest" value="true" />
<property name="validateResponse" value="true" />
</bean>
When I entered this soap request xml in Soap UI:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.test.com/ns1">
<soapenv:Header/>
<soapenv:Body>
<ns1:GetRecordsRequest>
<ns1:maxRecords></ns1:maxRecords>
</ns1:GetRecordsRequest>
</soapenv:Body>
</soapenv:Envelope>
The response message I got is:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>SOAP-ENV:Client</faultcode>
<faultstring xml:lang="en">Validation error</faultstring>
<detail>
<spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-datatype-valid.1.2.1: '' is not a valid value for 'integer'.</spring-ws:ValidationError>
<spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-type.3.1.3: The value '' of element 'cis:maxRecords' is not valid.</spring-ws:ValidationError>
</detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
You can see the result is two lines cryptic message for just one field. Can I make the response message more prettier by making just one line? Is there a way to customize the validation error response message?
Upvotes: 3
Views: 10443
Reputation: 3091
You can customize the validation error response by using the methods of the AbstractValidatingInterceptor (PayloadValidatingInterceptor is an implementation of this abstract class) namely:
setDetailElementName(QName detailElementName)
setFaultStringOrReason(String faultStringOrReason)
partial example:
public final class MyPayloadValidatingInterceptor
extends PayloadValidatingInterceptor {
@Override
protected Source getValidationRequestSource(WebServiceMessage webSerMessage_) {
_source = webSerMessage_.getPayloadSource();
validateSchema(_source);
return _source;
}
private void validateSchema(Source source_) throws Exception {
SchemaFactory _schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema _schema = _schemaFactory.newSchema(getSchemas()[0].getFile());
Validator _validator = _schema.newValidator();
DOMResult _result = new DOMResult();
try {
_validator.validate(source_, _result);
} catch (SAXException _exception) {
// modify your soapfault here
}
}
}
Upvotes: 2
Reputation: 1828
You can customize the validation error message by extending PayloadValidatingInterceptor and overriding handleRequestValidationErrors. We can set the custom error message in the body of messageContext.
1) Instead of the SOAP Fault for request validation errors, you can return custom xml response with validation error message.
2) SAXParseException[] errors contains the request validation errors. You can choose to return only one error in response. (or) For some predefined errors, you can return custom error message rather than the one returned in SAXParseException.
/**
* The Class CustomValidatingInterceptor.
*/
public class CustomValidatingInterceptor extends PayloadValidatingInterceptor{
/* (non-Javadoc)
* @see org.springframework.ws.soap.server.endpoint.interceptor.AbstractFaultCreatingValidatingInterceptor#handleRequestValidationErrors(org.springframework.ws.context.MessageContext, org.xml.sax.SAXParseException[])
*/
@Override
protected boolean handleRequestValidationErrors(MessageContext messageContext, SAXParseException[] errors) throws TransformerException {
JAXBContext jaxbContext;
StringWriter stringWriter = new StringWriter();
ResponseTransactionDetail transactionDetail = null;
for (SAXParseException error : errors) {
logger.debug("XML validation error on request: " + error.getMessage());
}
if (messageContext.getResponse() instanceof SoapMessage) {
/**
* Get SOAP response body in message context (SOAP Fault)
*/
SaajSoapMessage soapMessage = (SaajSoapMessage)messageContext.getResponse();
SoapBody body = soapMessage.getSoapBody();
// marshal custom error response to stringWriter
/**
* Transform body
*/
Source source = new StreamSource(new StringReader(stringWriter.toString()));
identityTransform.transform(source, body.getPayloadResult());
stringWriter.close();
}
return false;
}
Upvotes: 3