javax.xml.ws.soap.SOAPFaultException:解组错误:从AXIS迁移到CXF后出现意外元素(uri:"",local:" fault")

时间:2014-10-08 08:18:19

标签: java xml web-services wsdl cxf

问题

我正在尝试将我的Web服务客户端 Apache AXIS-1 迁移到 Apache CXF 。 Web服务本身运行AXIS-1并且不受我的控制 我生成了所有CXF工件,客户端一直运行良好,直到服务引发任何故障。有缺陷的XML看起来像:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <soapenv:Fault>
      <faultcode>soapenv:Server</faultcode>
      <faultstring>Remote error processing component card request</faultstring>
      <detail>
        <fault>
          <faultcode>:-303</faultcode>
          <faultstring>Remote error processing component card request</faultstring>
          <faultactor>remote_service</faultactor>
          <detail>
            <common-detail>
              <code>-303</code>
              <message>Remote error processing component card request</message>
            </common-detail>
          </detail>
        </fault>
      </detail>
    </soapenv:Fault>
  </soapenv:Body>
</soapenv:Envelope>

这使得CXF生成的客户端出现异常:

javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"fault"). 
Expected elements are <{http://some.namespace.org}AnsBonusAutopayStatus>,<{http://some.namespace.org}AnsBonusAutopaySubscribe>,
...
<{http://some.namespace.org}fault>
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:603)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:244)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:239)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:116)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1009)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:446)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:427)
    at com.sun.xml.bind.v2.runtime.unmarshaller.InterningXmlVisitor.startElement(InterningXmlVisitor.java:71)
    at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:137)
    at com.sun.xml.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:240)
    at com.sun.xml.bind.unmarshaller.DOMScanner.scan(DOMScanner.java:123)
...

来自这个堆栈跟踪的AFAIU,unmarshaller希望 fault 元素具有某些名称空间声明,但它没有一个。

有人可以说明该客户有什么问题,以及如何避免错误?

经过测试的解决方案

有很多类似的问题,但并非所有解决方案都适用于我,因为我无法在服务器端更改任何内容(至少出于向后兼容性原因),并且也不了解更改WSDL。因此,仅在客户端限制(包括其(重新)生成)。 我已根据类似的问题尝试了几种可能的解决方案:

  • 使用默认命名空间声明添加 package-info.class - 没有任何更改;
  • 在构造异常对象期间强制在CXF例程中为生成的错误和/或 Fault_Exception 类设置空命名空间 - NullPointerException (请参阅编辑部分下文);
  • 使用 SAX XmlFilter - 无法找到将其嵌入CXF生成例程的方法。

其他信息

CXF为异常生成了类,其faultInfo(没有任何更改)如下所示:
错误类:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "faultcode",
    "faultstring",
    "faultactor",
    "detail"
})
@XmlRootElement(name = "fault")
public class Fault {

    @XmlElement(required = true)
    protected String faultcode;
...

Fault_Exception 类:

@WebFault(name = "fault", targetNamespace = "http://some.namespace.org")
public class Fault_Exception extends Exception {

    private Fault fault;

    public Fault_Exception() {
        super();
    }
...

一些WSDL摘录。 WSDL错误消息声明:

  <wsdl:message name="Fault">
    <wsdl:part name="fault" element="fault"/>
  </wsdl:message>

XSD错误元素:

<xs:element name="fault">
<xs:annotation>
  <xs:documentation>Comment describing your root element</xs:documentation>
</xs:annotation>
<xs:complexType>
  <xs:sequence>
    <xs:element name="faultcode">...</xs:element>
    <xs:element name="faultstring">...</xs:element>
    <xs:element name="faultactor">...</xs:element>
    <xs:element minOccurs="0" name="detail">...</xs:element>
  </xs:sequence>
</xs:complexType>
</xs:element>

WSDL操作说明示例:

<wsdl:operation name="BonusConversionState">
  <wsdl:input name="BonusConversionStateRequest" message="tns:BonusConversionStateRequest"/>
  <wsdl:output name="BonusConversionStateResponse" message="tns:BonusConversionStateResponse"/>
  <wsdl:fault name="Fault" message="tns:Fault"/>
</wsdl:operation>

WSDL根元素:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://some.namespace.org" 
                  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
                  xmlns:tns="http://some.namespace.org" 
                  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
                  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">

可提供更多其他信息 提前谢谢!

编辑:

&#34;调查期间&#34;我发现 NullPointerException (我在&#34; Tested Solutions&#34中提到过)并不是我错误操作的结果。这是CXF的一个错误:

这两张票都以解决方案&#34;已修复&#34;关闭,但在评论用户报告中,他们仍然可以捕获此错误。似乎开发人员没有涵盖CXF处理自定义异常的所有情况,并且由于某些原因它有时会导致

  

org.apache.cxf.interceptor.ClientFaultConverter processFaultDetail
  信息:创建异常时发生异常:null
  显示java.lang.NullPointerException

有没有人遇到过这个问题?

1 个答案:

答案 0 :(得分:0)

这似乎是服务不符合其自身合同的情况。虽然您可能无法控制服务,但值得与服务提供商讨论。

客户抱怨的错误元素是第一个细节的直接孩子。元件。

根据异常消息,&#39; detail&#39;的第一个子元素应该是(假设目标命名空间&#39; http://some.namespace.org&#39;)AnsBonusAutopayStatus或AnsBonusAutopaySubscribe而不是{}错误元素。

如果你能够在操作和wsdl类型的故障声明周围提供更多的wsdl,可以提供额外的静态分析。