WSRF-Fehler
Das Web Services Resource Framework (WSRF) stellt einen empfohlenen Basiselementtyp für Fehlernachrichten bereit, aus dem alle servicespezifischen Fehler abgeleitet werden können. Der Vorteil eines einheitlichen Basistyps besteht darin, dass alle Fehler standardmäßig einheitliche Informationen enthalten können. Dies ist in komplexen Systemen nützlich, in denen Fehler systematisch protokolliert oder durch mehrere Softwareschichten hindurch weitergeleitet werden können, bevor sie analysiert werden.
- Eine obligatorische Zeitmarke.
- Ein Element, mit dem der Ersteller des Fehlers angegeben werden kann.
- Andere Elemente, die den Fehler beschreiben und klassifizieren können.
- ResourceUnkownFault
- Mit diesem Fehler wird angezeigt, dass die WS-Resource dem Service, der die Nachricht empfängt, nicht bekannt ist.
- ResourceUnavailableFault
- Mit diesem Fehler wird angezeigt, dass der Web-Service zwar aktiv ist, aber derzeit keinen Zugriff auf die Ressource bereitstellen kann.
<wsrf-bf:BaseFault>
<wsrf-bf:Timestamp>2005-05-31T12:00:00.000Z</wsrf-bf:Timestamp>
<wsrf-bf:Originator>
<wsa:Address>
http://www.example.org/Printer
</wsa:Address>
<wsa:ReferenceParameters>
<pr:pr-id>P1</pr:pr-id>
</wsa:ReferenceParameters>
</wsrf-bf:Originator>
<wsrf-bf:Description>Offline for service maintenance</wsrf-bf:Description>
<wsrf-bf:FaultCause>OFFLINE</wsrf-bf:FaultCause>
</wsrf-bf:BaseFault>
Die Klasse BaseFault
Für JAX-RPC-Anwendungen stellt WebSphere Application Server für alle durch die WSRF-Spezifikationen definierten Basisfehlerelementtypen Java™-Codezuordnungen bereit, wodurch eine Hierarchie von Ausnahmen entsteht, in der jede Java-Ausnahme die Klasse com.ibm.websphere.wsrf.BaseFault erweitert. Jede Fehlerklasse folgt einem ähnlichen Muster.
package com.ibm.websphere.wsrf;
public class BaseFault extends Exception
{
public BaseFault()
{
...
}
public BaseFault(EndpointReference originator,
ErrorCode errorCode,
FaultDescription[] descriptions,
IOSerializableSOAPElement faultCause,
IOSerializableSOAPElement[] extensibilityElements,
Attribute[] attributes)
{
...
}
...
}
Die Klasse IOSerializableSOAPElement
Da die Klasse BaseFault die Klasse java.lang.Exception erweitert, muss sie die Schnittstelle "java.io.Serializable" implementieren. Damit diese Voraussetzung erfüllt wird, müssen alle Eigenschaften einer BaseFault-Instanz selbst serialisierbar sein. Da die Klasse "javax.xml.soap.SOAPElement" nicht serialisierbar ist, stellt WebSphere Application Server die Klasse IOSerializableSOAPElement bereit, in die eine Instanz von javax.xml.soap.SOAPElement eingeschlossen werden kann, um eine serialisierbare Form dieser Instanz zu erhalten.
// Eine Instanz der Klasse IOSerializableSOAPElementFactory abrufen
IOSerializableSOAPElementFactory factory = IOSerializableSOAPElementFactory.newInstance();
// Ein IOSerializableSOAPElement aus einem javax.xml.soap.SOAPElement erstellen
IOSerializableSOAPElement serializableSOAPElement = factory.createElement(soapElement);
// Sie können das eingeschlossene SOAPElement aus dem IOSerializableSOAPElement abrufen
SOAPElement soapElement = serializableSOAPElement.getSOAPElement();
Alle anwendungsspezifischen BaseFault-Instanzen müssen ebenfalls serialisierbar sein.
Anwendungsspezifische Fehler
<xsd:complexType name="PrinterFaultType">
<xsd:complexContent>
<xsd:extension base="wsrf-bf:BaseFaultType"/>
</xsd:complexContent>
</xsd:complexType>
import com.ibm.websphere.wsrf.BaseFault;
import com.ibm.websphere.wsrf.*;
import javax.xml.soap.SOAPFactory;
...
public void print(PrintRequest req) throws PrinterFault, ResourceUnknownFault
{
// Die Identität der Zieldruckerinstanz ermitteln.
PrinterState state = PrinterState.getState ();
if (state.OFFLINE)
{
try
{
// Eine Instanz der SOAPFactory abrufen
SOAPFactory soapFactory = SOAPFactory.newInstance();
// Das SOAPElement faultCause erstellen
SOAPElement faultCause = soapFactory.createElement("FaultCause");
faultCase.addTextNode("OFFLINE");
// Eine Instanz der IOSerializableSOAPElementFactory abrufen
IOSerializableSOAPElementFactory factory = IOSerializableSOAPElementFactory.newInstance();
// Ein IOSerializableSOAPElement aus dem SOAPElement faultCause erstellen
IOSerializableSOAPElement serializableFaultCause = factory.createElement(faultCause);
FaultDescription[] faultDescription = new FaultDescription[1];
faultDescription[0] = new FaultDescription("Offline for service maintenance");
throw new PrinterFault(
state.getPrinterEndpointReference(),
null,
faultDescription,
serializableFaultCause,
null,
null); }
catch (SOAPException e)
{
...
}
}
...
import com.ibm.websphere.wsrf.BaseFault;
import com.ibm.websphere.wsrf.*;
...
try
{
printer1.print(job1);
}
catch (ResourceUnknownFault exc)
{
System.out.println("Operation threw the ResourceUnknownFault");
}
catch (PrinterFault exc)
{
System.out.println("Operation threw PrinterFault");
}
catch (BaseFault exc)
{
System.out.println("Exception is another BaseFault");
}
catch (Exception exc)
{
System.out.println("Exception is not a BaseFault");
}
Angepasste Binder
Wenn Sie einen neuen Basisfehler auf Anwendungsebene definieren, z. B. den oben gezeigten Druckerfehler (PrinterFault) des Typs PrinterFaultType, müssen Sie einen angepassten Binder bereitstellen, der definiert, wie die Web-Service-Laufzeit die Java-Klasse in eine geeignete XML-Nachricht serialisiert und wie umgekehrt eine XML-Nachricht in eine Instanz der Java-Klasse deserialisiert wird.
<customdatabinding:provider
xmlns:customdatabinding="http://www.ibm.com/webservices/customdatabinding/2004/06"
xmlns:pr="http://example.org/printer.xsd"
xmlns="http://www.ibm.com/webservices/customdatabinding/2004/06">
<mapping>
<xmlQName>pr:PrinterFaultType</xmlQName>
<javaName>PrinterFault</javaName>
<qnameScope>complexType</qnameScope>
<binder>PrinterFaultTypeBinder</binder>
</mapping>
</customdatabinding:provider>
Die Klasse BaseFaultBinderHelper
WebSphere EntApplication Server stellt die Klasse BaseFaultBinderHelper bereit, die Unterstützung für die Serialisierung und Entserialisierung der Daten einer BaseFault-Stammklasse liefert, die von allen spezialisierten BaseFault-Klassen erweitert werden muss. Wenn ein angepasster Binder die Klasse BaseFaultBinderHelper verwendet, dann muss dieser angepasste Binder nur die zusätzliche Logik zum Serialisieren und Deserialisieren der erweiterten BaseFault-Daten bereitstellen.
import com.ibm.wsspi.wsrf.BaseFaultBinderHelper;
import com.ibm.wsspi.wsrf.BaseFaultBinderHelperFactory;
import com.ibm.wsspi.webservices.binding.CustomBinder;
import com.ibm.wsspi.webservices.binding.CustomBindingContext;
...
public PrinterFaultTypeBinder implements CustomBinder
{
// Eine Instanz des BaseFaultBinderHelper abrufen
private BaseFaultBinderHelper baseFaultBinderHelper = BaseFaultBinderHelperFactory.getBaseFaultBinderHelper();
public SOAPElement serialize(Object data, SOAPElement rootNode, CustomBindingContext context) throws SOAPException
{
// Die spezifischen BaseFault-Daten serialisieren
baseFaultBinderHelper.serialize(rootNode, (BaseFault)data);
// Die spezifischen PrinterFault-Daten serialisieren
...
// Den serialisierten PrinterFault zurückgeben
return rootNode;
}
public Object deserialize(SOAPElement rootNode, CustomBindingContext context) throws SOAPException
{
// Eine Instanz eines PrinterFault erstellen
PrinterFault printerFault = new PrinterFault();
// Die spezifischen BaseFault-Daten entserialisieren - die zusätzlichen Daten, die
// die PrinterFault-Erweiterung bilden, werden als SOAPElement[] zurückgegeben.
SOAPElement[] printerFaultElements = baseFaultBinderHelper.deserialize(printerFault, rootNode);
// Spezifischen PrinterFault-Daten, die im SOAPElement[] printerFaultElements enthalten sind, entserialisieren
...
// Den deserialisierten PrinterFault zurückgeben
return printerFault;
}
...
}