javax.xml.ws.Seife.SOAPFaultException: Unmarshalling Error: unexpected element (uri:"", örtlich:"Störung"), die nach der Migration von der ACHSE CXF
Das Problem
Ich versuche zu migrieren meine web-service client von Apache AXIS-1 zu Apache CXF. Der web service selbst läuft om-ACHSE-1 und ist aus meiner Kontrolle.
Ich erzeugt, die die CXF-Artefakte, und der client hat gut funktioniert bis ein Fehler wird ausgelöst, indem Sie den Dienst. Die fehlerhafte XML sieht wie folgt aus:
<?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>
Dies macht die CXF erzeugt client Herbst mit einer Ausnahme:
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 von dieser stacktrace, unmarshaller erwartet, dass die Fehler element, um bestimmte namespace-Deklaration, aber es kommt ohne.
Kann jeder jeden schlagen, was ist falsch mit, dass client und wie man den Fehler vermeiden?
Getesteten Lösungen
Gibt es viele ähnliche Fragen, aber nicht alle Lösungen sind anwendbar für mich, weil ich nichts ändern kann auf der server-Seite (zumindest aus Gründen der Abwärtskompatibilität), und ändern Sie die WSDL wird auch nicht geschätzt. Damit Veränderungen beschränkt sind, die in der client-Seite (einschließlich Ihrer (re -) generation).
Ich habe versucht mehrere mögliche Lösungen, basierend auf ähnliche Fragen:
- hinzufügen package-info.class mit default-namespace-Deklaration - es ändert sich nichts;
- force Einstellung leer-namespace für die generierten Fehler und/oder Fault_Exception Klassen - NullPointerException in die CXF-Routinen, die während der Konstruktion der Ausnahme-Objekt (siehe EDIT unten);
- mit SAX XmlFilter - konnte nicht einen Weg finden, zu binden Sie ihn in die CXF erzeugt Routinen.
Zusätzliche Info
CXF generierten Klassen für die Ausnahme und seine faultInfo (ohne meine änderungen) so Aussehen:
Fehler Klasse:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"faultcode",
"faultstring",
"faultactor",
"detail"
})
@XmlRootElement(name = "fault")
public class Fault {
@XmlElement(required = true)
protected String faultcode;
...
Fault_Exception Klasse:
@WebFault(name = "fault", targetNamespace = "http://some.namespace.org")
public class Fault_Exception extends Exception {
private Fault fault;
public Fault_Exception() {
super();
}
...
Einige WSDL-Ausschnitte.
WSDL-Fault Meldung Erklärung:
<wsdl:message name="Fault">
<wsdl:part name="fault" element="fault"/>
</wsdl:message>
XSD-Fehler element:
<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-operation Beschreibung Beispiel:
<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-root-element:
<?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/">
Mehr zusätzliche Informationen bereitgestellt werden können.
Vielen Dank im Voraus!
EDIT:
Während der "Untersuchung" habe ich herausgefunden, dass NullPointerException (die ich erwähnt habe in "bewährte Lösungen") ist nicht eine Folge meiner falschen Handlungen. Es ist ein Fehler von CXF:
Beide tickets geschlossen werden mit der Auflösung "Fester", aber in den Kommentaren Anwender berichten, die Sie noch fangen diesen Fehler. Es scheint, dass die Entwickler nicht auf alle die Fälle, in denen benutzerdefinierte Ausnahmen werden von CXF und für einige Gründe, es führt manchmal zu
org.apache.cxf.interceptor.ClientFaultConverter processFaultDetail
INFO: Ausnahme ist aufgetreten während der Erstellung Ausnahme: null
java.lang.NullPointerException
Hat jemand jemals konfrontiert dieses problem auch?
- Ich habe ein workaround für das Problem, aber es kann nicht empfohlen als eine gute Lösung.
- Die Idee mit dem workaround kurz. Nach Festlegung expliziter leeren namespace generierten
Fault
Klasse, die die eingehenden interceptor-Kette sein sollte, angereichert mitXSLTInInterceptor
. Der interceptor (über XSLT) sollten exportieren Sie alle sensiblen Daten (fault-code und Nachricht) aus innere element auf die oberstesoapenv:Fault
Ebene. Dies sollte helfen, zu vermeiden, die die CXF-bug Fragen. Nach, dass der client-code geändert werden sollte, erhalten Sie Fehler-info ausSOAPFaultException
(nicht generierte exception-Klasse). Vorsicht, die Lösung kann sich verschlechtern die Leistung (Erhöhung der client-Methoden CPU execution time).
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies scheint ein Fall für den service nicht einhält, mit seinen eigenen Vertrag, wo der Fehler betroffen ist. Während Sie vielleicht nicht haben Kontrolle über den Dienst, das ist es Wert, eine Diskussion mit dem service-provider.
Dem fault-element Ihr Kunde beschwert sich über die unmittelbare Kind der ersten "detail" - element.
Basiert auf der exception-Nachricht, die ersten child-element des 'detail' wird erwartet, dass (unter Annahme einer Ziel-namespace 'http://some.namespace.org') entweder AnsBonusAutopayStatus oder AnsBonusAutopaySubscribe und nicht die {} - fault-element.
Wenn Sie in der Lage, ein bisschen mehr von der wsdl um die Schuld-Erklärung über den Betrieb und die wsdl-Typen zusätzliche statische Analyse kann zur Verfügung gestellt werden.
detail
element, welches das root-element für benutzerdefinierte exception-Objekt. CXF kann nicht finden, eine geeignete Klasse für die Deserialisierung von benutzerdefinierten Ausnahme aufgrund der namespace-Deklaration Unterschiede auf. Das problem kann umgangen werden, indem explizit leeren namespace-Deklaration für generierte Fehler-Klasse, aber dieser Ansatz zeigt einen Fehler in CXF selbst (siehe Abschnitt BEARBEITEN der Frage). Auf der Suche nach anderen Möglichkeiten...