I'm currently writing a new set of web services using JAX-WS but I'm having difficulties deciding on the best way to validate the inputs. I can do some validation in my implementation classes but some input errors fail silently. For example character data in a numeric element will result in a null Integer in the JAXB object.
These are the designs I've come across.
@SchemaValidation
I could add this annotation to the endpoint class and JAX-WS will take care of the validation. This worked locally in tomcat but there are concerns that it won't work on some servers. My main gripe is that I have to surrender control of how the errors are output in the response.
All inputs as strings
I hate this approach but I've seen other web services where all inputs are defined as strings. This would catch the case of character data in a numeric element as I could check it where I call our API although you'd still miss any incorrectly named xml elements.
I really want the errors to come back in the same manner as the API errors rather than as a soap fault. Any ideas? I've seen a few sites talking about intercepting the request with a kind of filter. Not sure how this would work with different responses for different operations though.
E.G.
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<myOperationResponse>
<return>
<success>false</success>
<errors>
<error>
<code>UNIQUECODE</code>
<message>Message text</message>
</error>
</errors>
</return>
</myOperationResponse>
</S:Body>
</S:Envelope>
Maybe I'm asking too much but thought I'd see if I'd missed anything. TIA.
Found this article which explains one possible way.
http://one-size-doesnt-fit-all.blogspot.co.uk/2009/04/jax-ws-schemavalidation-custom-handler.html
I have it returning the parse error message in my standard response layout. i just need to test it will work on the customers machine. (Some people say they've had issues with @SchemaValidation)
If you insist on control (something like you usually need to relinquish when doing Jax-WS...), you could implement a Provider and Validator validating against an XSD Schema.
The XSD Schema will take care of validating the input (type and potentially enumerations, pattern matching, etc...)
To implement the javax.xml.ws.Provider
as your SOAP Endpoint, create a class looking like
@javax.xml.ws.ServiceMode(value = javax.xml.ws.Service.Mode.MESSAGE)
@javax.xml.ws.WebServiceProvider(
wsdlLocation = "WEB-INF/wsdl/MyService.wsdl",
targetNamespace = "urn-com-acme-webservice",
serviceName = "ProcessPurchaseOrderService",
portName = "ProcessPurchaseOrderPort"
)
public class ProcessPurchaseOrder implements Provider<SOAPMessage> {
@override
public SOAPMessage invoke(final SOAPMessage request) {
//see below
}
}
A SOAPMessage
will be passed to the invoke
method which expects in return a valid response or SOAPFault wrapped in a SOAPMessage;
To validate agains an XSD, use a javax.xml.validator
:
URL url = this.getClass().getResource(xsdSchemaLocation);
String language = XMLConstants.W3C_XML_SCHEMA_NS_URI;
SchemaFactory factory = SchemaFactory.newInstance(language);
Schema schema = factory.newSchema(url);
validator = schema.newValidator();
Extract the SOAPBody
xml and validate it against the Validator
using the validate()
method.
Catch Exceptions around the validation and build your own SOAP Fault:
//Build the SOAP Fault Response
MessageFactory factory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
SOAPMessage response = factory.createMessage();
SOAPFault fault = response.getSOAPBody().addFault();
fault.setFaultString(myCustomErrorString);
fault.addDetail().addChildElement("exception").addTextNode(myCustomErrorId);
then return the SOAPMessage containing the fault.
(no, I do not like SOAP Web Services)
In the scenario you are trying to achieve, there wont be any SOAP fault. The validation logic (which will be part of the code which handles the request eventually ), has to make sure that all the validation scenarios are handled.
We had faced this scenarios where in the third party integrating our web services could not decipher much from the SOAP faults and we went by creating an error-response just like the way you have conceived. I would suggest the following approach.
myOperationResponse
). If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With