Wir haben eine JAX-WS/JAXB-Bindung an einen externen Webservice, der auf Java 7 (1.7.0u80) funktioniert) mit den mitgelieferten Referenzimplementierungen. Während der Migration zu Java 8 (1.8.0u66) funktionieren die Web-Service-Aufrufe in der Regel OK, jedoch können SOAP-Fehler und ihre Detailelemente nicht mehr mit Java-Ausnahmen mit benutzerdefinierten Details entfernt werden, sondern ein Präfix, das nicht an einen Namespace-Fehler gebunden ist."Präfix xsd ist nicht an einen Namespace gebunden" SOAPFault mit JAXB nach Migration nach Java 8 migrieren
Das Scheitern ist
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)
Die Antwort des externen Service sieht aus wie unter dem (ich habe Typnamen anonymisiert, aber alles andere links)
<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>
Das Problem ist, mit dem xsd : int und xsd: string im faultCode und faultReason. Es scheint, dass die Präfix-/Namespace-Deklarationen nicht von der obersten Ebene der Hüllkurve beim Binden übernommen werden. Das Problem sieht ähnlich wie this question aus, aber im Gegensatz zu dieser Frage handelt es sich um SOAP Fault Handling, und in meinem Fall ist der Code tief in JAX-WS und JAXB, also habe ich keine Ahnung, wie wir es reparieren oder umgehen können.
Wenn sich der alte Code nicht auf ein Verhalten verlassen hat, das nie hätte funktionieren sollen, kann ich nicht anders, als zu schlussfolgern, dass in ihren Java-8-Implementierungen zwischen JAX-WS und JAXB etwas gebrochen wurde.
Update (4. Januar 2016): Ich habe das auch mit einem CXF 3.1.4 Client anstelle der Metro RI versucht. Gleiches Problem. Es scheint, das gleiche Problem zu sein, wie here erwähnte
Update (6. Januar 2016): Ich habe dieses Problem auf eine an die JAXB RI 2.2.6 eingeführte Änderung verengt haben. Somit kann das Problem auf Java 7 mit einem erzwungenen Upgrade auf JAXB RI 2.2.6 repliziert werden. Es scheint sich um Änderungen in JAXB-890 zu handeln.
Ich habe getestet in mindestens zwei verschiedenen Möglichkeiten, um dieses Arbeits:
- Verwenden Java 8 mit JAXB Kraft degradiert zurück zu 2.2.5 (JAX-WS-Version scheint nicht Rolle). Scheint keine gute langfristige Lösung.
- Ich fand, dass
-Dcom.sun.xml.bind.improvedXsiTypeHandling=false
(oder die gleichwertige.internal
Eigenschaft, wenn Sie das gebündelte JDK JAXB RI verwenden) scheint das Problem zu umgehen. Aber ich habe keine Ahnung, was diese Einstellung wirklich macht; oder was die Implikationen für den Rest der JAXB-Nutzung in meinem System wären.
Irgendwelche Ideen für, wie man hier vorgeht?
Können Sie die 'xmlns: xsd =' Deklaration von der 'Envelope' zum' Fault' Element verschieben? – Holger
Leider nicht ohne irgendeine Art von Vor-Unmarshall Xml-Hack, da der Dienst, den ich anrufe, nicht meiner ist. Ich glaube nicht, dass irgendetwas mit ihrer Antwort falsch ist, obwohl ich zustimme, dass dies das Problem wahrscheinlich lösen würde. – Chad