spring-wsaxiom

XSD validation fails with UndeclaredPrefix when using AxiomSoapMessageFactory in Spring WS


I'm building a contract-first SOAP web service with spring-ws 2.2.3. My XML Schema uses extensions, leading to xsi:type= attributes in the XML requests. Since some respones can be very large (30MB), I'm using a AxiomSoapMessageFactory instead of the default SaajSoapMessageFactory, as suggested in the Spring WS docs. I validate incoming requests with a PayloadValidatingInterceptor:

PayloadValidatingInterceptor interceptor = new PayloadValidatingInterceptor();
interceptor.setSchema(new ClassPathResource("format-service.xsd"));
interceptor.setValidateRequest(true);
interceptor.setValidateResponse(false); 

My problem is that I get spurious validation errors, depending on where in the XML the namespace is declared: if it's declared in the payload, then everything works fine:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" >
   <soapenv:Header/>
   <soapenv:Body>
      <sch:formatRequest xmlns:sch="http://example.com/springws/extension/schema">
         <sch:value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="sch:currencyType">
           <sch:amount>1000</sch:amount>
           <sch:currency>EUR</sch:currency>
         </sch:value>
      </sch:formatRequest>
   </soapenv:Body>
</soapenv:Envelope>

But as soon as I move the sch namespace declaration up to the Envelope:

<soapenv:Envelope xmlns:sch="http://example.com/springws/extension/schema" ...>

validation fails and I receive a SOAP Fault:

<faultcode>soapenv:Client</faultcode>
<faultstring xml:lang="en">Validation error</faultstring>
<detail>
    <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">UndeclaredPrefix: Cannot resolve 'sch:currencyType' as a QName: the prefix 'sch' is not declared.</spring-ws:ValidationError>
    <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-elt.4.1: The value 'sch:currencyType' of attribute 'http://www.w3.org/2001/XMLSchema-instance,type' of element 'sch:value' is not a valid QName.</spring-ws:ValidationError>
    <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-type.2: The type definition cannot be abstract for element sch:value.</spring-ws:ValidationError>
    <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">UndeclaredPrefix: Cannot resolve 'sch:currencyType' as a QName: the prefix 'sch' is not declared.</spring-ws:ValidationError>
    <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-attribute.3: The value 'sch:currencyType' of attribute 'xsi:type' on element 'sch:value' is not valid with respect to its type, 'QName'.</spring-ws:ValidationError>
    <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-complex-type.2.1: Element 'sch:value' must have no character or element information item [children], because the type's content type is empty.</spring-ws:ValidationError>
</detail>

It appears like a bug in the AxiomSoapMessageFactory / Axiom implementation to me (namespace context is lost), as both requests validate fine when using the SaajSoapMessageFactory. Note that the validation only fails on the xsi:type= attribute. The same namespace is recognized correctly for elements.

I cannot use SaajSoapMessageFactory due to high memory consumption for large responses. I found similar problems described in the Spring forum and on SO, but no solution. Thanks for help!


Solution

  • The reason is that Spring-WS uses OMContainer#getXMLStreamReader(). Instead it should use OMContainer#getXMLStreamReader(boolean, OMXMLStreamReaderConfiguration) and set the preserveNamespaceContext property to true in the OMXMLStreamReaderConfiguration object.

    You should file a bug for Spring-WS, or even better, fix the issue and submit a pull request.