【问题标题】:"prefix xsd is not bound to a namespace" un-marshalling SOAPFault with JAXB after migration to Java 8“前缀 xsd 未绑定到命名空间”在迁移到 Java 8 后使用 JAXB 解组 SOAPFault
【发布时间】: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:intxsd: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 中所做的更改有关。

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

  1. 使用 Java 8 并将 JAXB 强制降级回 2.2.5(JAX-WS 版本似乎无关紧要)。似乎不是一个好的长期解决方案。
  2. 我发现-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


【解决方案1】:

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

鉴于此工作正常,这似乎是 Java 8 随附的 JAXB RI (Metro) 版本(至少 1.8.0u66)中存在的问题。

【讨论】:

    【解决方案2】:

    最近遇到了类似的问题。切换到 MOXy 或使用一些晦涩的 JVM 参数不是一种选择,因此我寻找了实现上述某种“预解组黑客”的方法。

    事实证明,如果你像这样制作一个 SOAPHandler

    public class NamespaceBindingShim implements SOAPHandler<SOAPMessageContext> {
    
      @Override
      public boolean handleMessage(SOAPMessageContext context) {
        return true;
      }
    
      @Override
      public boolean handleFault(SOAPMessageContext context) {
        context.getMessage();    
        return true;
      }
    
      @Override
      public void close(MessageContext context) {
      }
    
      @Override
      public Set<QName> getHeaders() {
        return null;
      }
    }
    

    然后像这样将它添加到客户端的处理程序链中

    ServicePort port = service.getServicePort();
    BindingProvider bindingProvider = (BindingProvider) port;
    Binding binding = bindingProvider.getBinding();
    binding.setHandlerChain(Collections.singletonList(new NamespaceBindingShim()));
    

    然后一切都奇迹般地工作,专有的 SOAP 错误被转换为专有的异常。

    我还不知道为什么会这样以及它是否会破坏其他东西,因为很明显我没有在处理程序中进行任何 XML 操作(getter 只为信封 AFAICT 调用惰性 DOM 初始化)。

    编辑: 经过更多测试后,我发现这在某些测试中通过,但在其他测试中失败。回到绘图板...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-24
      • 2013-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多