How best to validate JAX-WS inputs?
Asked Answered
G

4

11

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.

  1. @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.

  2. 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.

Gulf answered 4/7, 2013 at 11:12 Comment(0)
G
8

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)

Gulf answered 4/7, 2013 at 13:16 Comment(1)
The upvote just reminded me of this. This is now in production for several projects and we've had no issues.Gulf
F
7

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)

Frazzle answered 4/7, 2013 at 12:3 Comment(2)
lol me neither but sometimes we don't get to choose ;) I'm trying to keep the development as simple as possible so I think this might confuse some people.Gulf
Can this be used with Axis?Sterner
C
2

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.

  • Write your own validation logic
  • Create an appropriate object structure. You already have one in XML format. Just need to objectify it.
  • Call this validation logic and pass the input objects to it. The validation logic will validate all the inputs and populate appropriate response object (myOperationResponse).
  • On return of the validation method, check for the status or error objects. If there are errors then return the response object OR proceed with processing the request further and then return the success response.
Conceal answered 4/7, 2013 at 12:38 Comment(3)
This sounds like what's already happening but the problem is if it can't map an element to the jaxb object then it just fails silently.Gulf
You are right. Just curious to know if the null value of JAXB element is sufficient indicator for validation failure in your case.Conceal
Not really. How can you tell if there was an error or if it was an optional element which they didn't pass?Gulf
J
0

Im not sure if i understand u right, but maby this helps u:

http://blog.bdoughan.com/2010/12/jaxb-and-marshalunmarshal-schema.html

Jody answered 4/7, 2013 at 11:38 Comment(1)
Had a look but this assumes I have the raw xml to work with. By the time my endpoint gets the request it's been mapped to a pojo.Gulf

© 2022 - 2024 — McMap. All rights reserved.