2012-04-17 7 views
9

Ich arbeite an einigen Web-Services-basierte Anwendung und ich habe eine Frage über Apache CXF-Unmarshalling. In unserem Projekt verwenden wir CXF 2.4.1 Version.Override CXF Fehlerbehandlung

Wenn einig SOAP-Anforderung nicht korrekt ist (zB einig Feld Text anstelle von numerischen) CXF wirft Standard SOAPFaultException und SOAP-Antwort wird mit Standardfeldern wie aufgebaut:

<soap:Fault> 
    <faultcode>soap:Client</faultcode> 
    <faultstring>Unmarshalling Error: some field missing</faultstring> 
</soap:Fault> 

Projektanforderungen sagt, dass bei jedem Störungssystem müssen in einem anderen Format, wie reagieren:

<soap:body> 
    <ResponseState> 
     <ErrorCode>2732</ErrorCode> 
     <ErrorMessage>Unmarshalling Error: some field missing</ErrorMessage> 
     <ErrorDetails> some details </ErrorDetails> 
     <some other fields> 
     ... 
    </ResponseState> 
</soap:body> 

die Frage ist also: wie kann ich irgendwie diese Fehlerbehandlung außer Kraft setzen und in meinem Format reagieren, nicht Standard?

Vielen Dank im Voraus.

P.S. Ich habe versucht, einige ValidationEventHandler-Principals zu untersuchen, aber in CXF 2.0 und höher funktioniert es anders.

Antwort

6

OK, also nach viel Forschung habe ich einige Möglichkeiten der CXF-Fehlerbehandlung gefunden.

*. ValidationEventHandler gibt Ihnen die Möglichkeit, Ihre eigene Ausnahme anstelle der Standardausnahme auszulösen. ABER Sie können das Antwortverhalten nicht ändern, und Sie können das SOAP-Antwortformat nicht ändern.

*. Eine weitere Möglichkeit, die Fehlerbehandlung zu ändern, besteht darin, einen eigenen Interzeptor zu erstellen. Der CXF-Workflow basiert auf einer Kette von Interzeptoren. Es gibt 4 Arten von Interzeptoren: inInterceptor, outInterceptor, inFaultInterceptor und outFaultInterceptor.

Mithilfe einiger intelligenter Hacks können Sie den Arbeitsablauf ändern, indem Sie Ihren eigenen Interzeptor erstellen (indem Sie ihn der Kette hinzufügen) und den Standardabfanger aus der Kette entfernen (wenn Sie seinen Klassennamen kennen). Sie können also alles tun, was Sie brauchen.

ABER soweit all diese Interzeptoren Marshall-Antwort manuell (xmlWriter.writeStartElement() usw.) kann es eine große Herausforderung sein, Ihre eigenen Interzeptoren für jede Flow-Phase zu schreiben. Es könnte wirklich ein riesiger Haufen Arbeit sein.

Leider habe ich keine gute Referenz über CXF-Interzeptoren gefunden.

Eine andere Sache - wenn Sie regelmäßige Antwort anstelle von SOAPFaultException zurückgeben müssen Sie möglicherweise zusätzliche Informationen wie: tatsächlichen Service, der diese Antwort zurückgeben, Service-Parameter in Anfrage übergeben usw. Ich habe diese Informationen nicht in zugänglichen Parametern in Interzeptoren gefunden . Und dadurch betrügen Sie den Client-Code, der OK statt einer echten Ausnahme zurückgibt.

*. Entwerfen Sie Ihre WSDL mit allen Parametern als Text möglicherweise sehr nicht sehr gut Lösung:

a. Verbraucher Ihrer Dienste können wirklich verwirrt sein, wenn keine Datentypen und Validierungsregeln in WSDL.

b. Sie müssen das Rad für die Validierung neu erfinden. Ich meine, dass Sie Ihren eigenen Prüfer schreiben müssen, der mit einigen komplizierten Regeln sehr schwierig sein könnte. Zur gleichen Zeit hat XSD alle diese Validierungen implementiert und gut getestet.

Und schließlich über meine Situation: Wir diskutierten es mit Anforderungsmanager und beschlossen, CXF werfen eigene Standardausnahmen, wenn XML-Schema-Anforderungen in Anforderung verletzt. Es ist eine gute Lösung, denn jetzt nutzen wir alle Möglichkeiten der XSD-Validierung und verschwenden keine Zeit mit komplizierten und nutzlosen Arbeiten.

Vielen Dank an @ericacm für die Antwort.

+0

Vielen Dank für die Zusammenfassung der Forschung, die Sie zu diesem Thema gemacht haben. Ich stehe jetzt vor einer ähnlichen Herausforderung. – Withheld

1

Sie können mit Sicherheit eine bessere Fehlerreaktion als die Standardeinstellung generieren, indem Sie ValidationEventHandler verwenden und einen Fehler auslösen, der der JAX-WS Fault-Spezifikation entspricht. Aber es wird Ihnen nur so viel Anpassung erlauben - es wird einige Elemente geben, über die Sie keine Kontrolle haben. Zum Beispiel, hier ist die Validation Antwort von einem meiner apps:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soap:Body> 
     <soap:Fault> 
     <faultcode>soap:Client</faultcode> 
     <faultstring>Errors in request</faultstring> 
     <detail> 
      <ns2:ValidationFault xmlns:ns2="http://notification.ws.foo.com/"> 
       <errors> 
        <error> 
        <inputElement>topicId</inputElement> 
        <errorMessage>java.lang.NumberFormatException: For input string: "" [line:6]</errorMessage> 
        </error> 
       </errors> 
      </ns2:ValidationFault> 
     </detail> 
     </soap:Fault> 
    </soap:Body> 
</soap:Envelope> 

Sie nichts über die <soap:Fault>, <faultcode> and <faultstring> Elemente tun können. Aber alles von <ValidationFault> bis </ValidationFault> ist Brauch.

Wenn Sie eine detailliertere Kontrolle über die Antwort benötigen, sollten Sie den Feldtyp von numerisch in string ändern und dann die Validierung in Ihrem Code durchführen, damit der Unmarshaller den Fehler nicht abfangen kann.

Ja, ich stimme zu, zwingt es zu einem String würde saugen aber wenn die Antwort genau das sein muss, was Sie oben angegeben haben, wird es nicht möglich sein, tiefer in CXF als der JAX-WS Layer (zum Beispiel mit einem Abfangjäger).

+0

Danke für eine Antwort. Und ich habe ein paar Kommentare dazu. Ja, ValidationEventHandler gibt Ihnen die Möglichkeit, Ihre eigene Ausnahme anstelle der Standardausnahme zu verwenden. Aber es kann Ihnen nicht helfen, wenn Sie die Antwortnachricht vollständig neu schreiben möchten. Aber wenn wir nur alle String-Elemente erhalten, dann werden all unsere generierten Objekte all diese Strings enthalten und dann müssen wir das Rad neu erfinden, um alle zu konvertieren und zu validieren. Auf der anderen Seite: Wie wird der Verbraucher unserer Web Services verstehen, was Anforderungen für Felder sind? Durch Kommentare in der WSDL-Datei? Also, IMO, Saiten ist nicht wirklich eine gute Entscheidung. –

+0

Aktualisierte Antwort. – sourcedelica