XSD 在 Spring WS 中使用 AxiomSoapMessageFactory 时,验证失败并显示 UndeclaredPrefix
XSD validation fails with UndeclaredPrefix when using AxiomSoapMessageFactory in Spring WS
我正在使用 spring-ws 2.2.3 构建合同优先的 SOAP Web 服务。我的 XML 架构使用扩展,导致 XML 请求中的 xsi:type=
属性。由于某些响应可能非常大 (30MB),因此我使用 AxiomSoapMessageFactory 而不是默认的 SaajSoapMessageFactory,如 Spring WS docs 中所建议的那样。我使用 PayloadValidatingInterceptor 验证传入请求:
PayloadValidatingInterceptor interceptor = new PayloadValidatingInterceptor();
interceptor.setSchema(new ClassPathResource("format-service.xsd"));
interceptor.setValidateRequest(true);
interceptor.setValidateResponse(false);
我的问题是我收到虚假的验证错误,这取决于在 XML 中声明命名空间的位置:如果它在有效负载中声明,那么一切正常:
<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>
但是一旦我将 sch
名称空间声明移动到信封中:
<soapenv:Envelope xmlns:sch="http://example.com/springws/extension/schema" ...>
验证失败,我收到 SOAP 错误:
<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>
这对我来说似乎是 AxiomSoapMessageFactory / Axiom 实现中的错误(命名空间上下文丢失),因为在使用 SaajSoapMessageFactory 时两个请求都可以正常验证。请注意,验证仅在 xsi:type=
属性上失败。元素可以正确识别相同的命名空间。
我无法使用 SaajSoapMessageFactory,因为大型响应会占用大量内存。我在Spring forum and on SO中发现了类似的问题,但没有解决方案。感谢您的帮助!
原因是Spring-WS在OMXMLStreamReaderConfiguration
对象中使用了OMContainer#getXMLStreamReader()
. Instead it should use OMContainer#getXMLStreamReader(boolean, OMXMLStreamReaderConfiguration)
and set the preserveNamespaceContext
属性到true
您应该为 Spring-WS 提交错误,或者更好的是,修复问题并提交拉取请求。
我正在使用 spring-ws 2.2.3 构建合同优先的 SOAP Web 服务。我的 XML 架构使用扩展,导致 XML 请求中的 xsi:type=
属性。由于某些响应可能非常大 (30MB),因此我使用 AxiomSoapMessageFactory 而不是默认的 SaajSoapMessageFactory,如 Spring WS docs 中所建议的那样。我使用 PayloadValidatingInterceptor 验证传入请求:
PayloadValidatingInterceptor interceptor = new PayloadValidatingInterceptor();
interceptor.setSchema(new ClassPathResource("format-service.xsd"));
interceptor.setValidateRequest(true);
interceptor.setValidateResponse(false);
我的问题是我收到虚假的验证错误,这取决于在 XML 中声明命名空间的位置:如果它在有效负载中声明,那么一切正常:
<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>
但是一旦我将 sch
名称空间声明移动到信封中:
<soapenv:Envelope xmlns:sch="http://example.com/springws/extension/schema" ...>
验证失败,我收到 SOAP 错误:
<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>
这对我来说似乎是 AxiomSoapMessageFactory / Axiom 实现中的错误(命名空间上下文丢失),因为在使用 SaajSoapMessageFactory 时两个请求都可以正常验证。请注意,验证仅在 xsi:type=
属性上失败。元素可以正确识别相同的命名空间。
我无法使用 SaajSoapMessageFactory,因为大型响应会占用大量内存。我在Spring forum and on SO中发现了类似的问题,但没有解决方案。感谢您的帮助!
原因是Spring-WS在OMXMLStreamReaderConfiguration
对象中使用了OMContainer#getXMLStreamReader()
. Instead it should use OMContainer#getXMLStreamReader(boolean, OMXMLStreamReaderConfiguration)
and set the preserveNamespaceContext
属性到true
您应该为 Spring-WS 提交错误,或者更好的是,修复问题并提交拉取请求。