"前缀xsd未绑定到命名空间"在迁移到Java 8后使用JAXB解组SOAPFault

Cha*_*had 6 web-services cxf jax-ws jaxb java-8

我们有一个JAX-WS/JAXB绑定到外部Web服务,该服务在Java 7(1.7.0u80)上运行良好,包含了参考实现.在迁移到Java 8(1.8.0u66)期间,Web服务调用通常可以正常工作,但是它不能再将SOAP错误及其详细信息元素解析为具有自定义详细信息的Java异常,而是提供未绑定到命名空间错误的前缀.

失败的是

Caused by: javax.xml.ws.WebServiceException: java.lang.IllegalArgumentException: prefix xsd is not bound to a namespace
at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:138)
at com.sun.xml.internal.ws.client.sei.StubHandler.readResponse(StubHandler.java:238)
at com.sun.xml.internal.ws.db.DatabindingImpl.deserializeResponse(DatabindingImpl.java:189)
at com.sun.xml.internal.ws.db.DatabindingImpl.deserializeResponse(DatabindingImpl.java:276)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:104)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:77)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:147)
at com.sun.proxy.$Proxy61.proprietaryServiceCall(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.springframework.remoting.jaxws.JaxWsPortClientInterceptor.doInvoke(JaxWsPortClientInterceptor.java:580)
at org.springframework.remoting.jaxws.JaxWsPortClientInterceptor.doInvoke(JaxWsPortClientInterceptor.java:554)
... 56 more
Caused by: java.lang.IllegalArgumentException: prefix xsd is not bound to a namespace
at com.sun.xml.internal.bind.DatatypeConverterImpl._parseQName(DatatypeConverterImpl.java:355)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.LeafPropertyXsiLoader.selectLoader(LeafPropertyXsiLoader.java:75)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.LeafPropertyXsiLoader.startElement(LeafPropertyXsiLoader.java:58)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:559)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:538)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.InterningXmlVisitor.startElement(InterningXmlVisitor.java:60)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:153)
at com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:229)
at com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:266)
at com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:235)
at com.sun.xml.internal.bind.unmarshaller.DOMScanner.scan(DOMScanner.java:112)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:354)
at com.sun.xml.internal.bind.v2.runtime.BridgeImpl.unmarshal(BridgeImpl.java:124)
at com.sun.xml.internal.bind.api.Bridge.unmarshal(Bridge.java:309)
at com.sun.xml.internal.ws.db.glassfish.BridgeWrapper.unmarshal(BridgeWrapper.java:217)
at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.getJAXBObject(SOAPFaultBuilder.java:304)
at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:135)
Run Code Online (Sandbox Code Playgroud)

外部服务的响应如下所示(我有匿名类型名称,但保留其他所有内容)

<env:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <env:Header/>
        <env:Body>
        <env:Fault>
            <faultcode>env:Server</faultcode>
            <faultstring>ERROR MESSAGE</faultstring>
            <detail>
                <n1:ProprietaryException xmlns:n1="java:com.company.service" xsi:type="n1:ProprietaryException">
                    <errorCode xsi:type="xsd:int">400</errorCode>
                    <errorReason xsi:type="xsd:string">Specific error</errorReason>
                </n1:ProprietaryException>
            </detail>
        </env:Fault>
    </env:Body>
</env:Envelope>
Run Code Online (Sandbox Code Playgroud)

问题在于faultCode和faultReason中的xsd:intxsd:string.在绑定时,似乎没有从顶级包络继承前缀/名称空间声明.问题看起来类似于这个问题,除了那个问题与SOAP故障处理不同,在我的例子中,代码深入JAX-WS和JAXB,因此我不知道如何修复它或解决它.

除非旧代码依赖于一些从未应该起作用的行为,否则我不得不总结JAX-WS和JAXB在Java 8实现中已经被打破的东西.

更新(2016年1月4日):我也尝试使用CXF 3.1.4客户端而不是Metro RI.同样的问题.这似乎与这里提到的问题相同

更新(2016年1月6日):我已将此问题缩小到JAXB RI 2.2.6中引入的更改.因此,可以通过强制升级到JAXB RI 2.2.6在Java 7上复制该问题.它似乎可能与JAXB-890中的更改有关.

我已经测试过至少以两种不同的方式解决这个问题:

  1. 使用Java 8将JAXB force降级回2.2.5(JAX-WS版本似乎并不重要).似乎不是一个好的长期解决方案.
  2. 我发现-Dcom.sun.xml.bind.improvedXsiTypeHandling=false(或者.internal使用捆绑的JDK JAXB RI时的等效属性)似乎解决了这个问题.但我不知道这个设置到底是做什么的; 或者对我系统中其余JAXB用法的影响.

关于如何在这里进行的任何想法?

Cha*_*had 1

一种似乎有效的解决方法(但不应该是必需的,并且会对我的应用程序的其他部分中的 JAXB 使用产生其他后果,这使得它变得不可取)是用EclipseLink MOXy替换 JAXB 提供程序(已测试 1.6.2)。

鉴于此有效,这似乎确实是 Java 8(至少 1.8.0u66 之前)附带的 JAXB RI (Metro) 版本中的问题。