【发布时间】:2016-01-24 12:07:18
【问题描述】:
我们有一个 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)
来自外部服务的响应如下所示(我有匿名类型名称,但保留了其他所有内容)
<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>
问题出在 faultCode 和 faultReason 中的 xsd:int 和 xsd:string 上。绑定时似乎没有从顶级信封继承前缀/命名空间声明。这个问题看起来类似于this question,除了这个问题是关于 SOAP 错误处理的,在我的例子中,代码在 JAX-WS 和 JAXB 内部,所以我不知道我们如何修复它或解决它。
除非旧代码依赖于某些本不应该起作用的行为,否则我不禁得出结论,JAX-WS 和 JAXB 在其 Java 8 实现中存在某些问题。
更新(2016 年 1 月 4 日):我还尝试使用 CXF 3.1.4 客户端而不是 Metro RI。同样的问题。这似乎与here提到的问题相同
更新(2016 年 1 月 6 日):我已将此问题缩小到对 JAXB RI 2.2.6 进行的更改。因此,通过强制升级到 JAXB RI 2.2.6,可以在 Java 7 上复制该问题。似乎它可能与 JAXB-890 中所做的更改有关。
我已经测试了至少以两种不同的方式解决这个问题:
- 使用 Java 8 并将 JAXB 强制降级回 2.2.5(JAX-WS 版本似乎无关紧要)。似乎不是一个好的长期解决方案。
- 我发现
-Dcom.sun.xml.bind.improvedXsiTypeHandling=false(或等效的.internal属性,如果使用捆绑的JDK JAXB RI)似乎可以解决这个问题。但我不知道这个设置的真正作用。或者对我系统中的其他 JAXB 使用有何影响。
关于如何在此处继续的任何想法?
【问题讨论】:
-
你能把
xmlns:xsd=声明从Envelope移动到Fault元素吗? -
不幸的是,并非没有某种预解组 Xml hack,因为我调用的服务不是我的。我不相信他们的回答有什么问题,尽管我同意这可能会解决这里的问题。
标签: web-services jaxb java-8 cxf jax-ws