Web Services Resource Framework base faults
The Web Services Resource Framework (WSRF) provides a recommended basic fault message element type from which you can derive all service-specific faults. The advantage of a common basic type is that all faults can, by default, contain common information. This behavior is useful in complex systems where faults might be systematically logged, or forwarded through several layers of software before being analyzed.
- A mandatory timestamp.
- An element that can be used to indicate the originator of the fault.
- Other elements that can describe and classify the fault.
- ResourceUnkownFault
- This fault is used to indicate that the WS-Resource is not known by the service that receives the message.
- ResourceUnavailableFault
- This fault is used to indicate that the web service is active, but temporarily unable to provide access to the resource.
<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>
The BaseFault class
For JAX-RPC applications, WebSphere® Application Server provides Java™ code mappings for all the base fault element types that are defined by the WSRF specifications, forming an exception hierarchy where each Java exception extends the com.ibm.websphere.wsrf.BaseFault class. Each fault class follows a similar pattern.
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)
{
...
}
...
}
The IOSerializableSOAPElement class
Because the BaseFault class extends the java.lang.Exception class, the BaseFault class must implement the java.io.Serializable interface. To meet this requirement, all properties of a BaseFault instance must be serializable. Because the javax.xml.soap.SOAPElement class is not serializable, WebSphere Application Server provides an IOSerializableSOAPElement class, which you can use to wrap a javax.xml.soap.SOAPElement instance to provide a serializable form of that instance.
// Get an instance of the IOSerializableSOAPElementFactory class
IOSerializableSOAPElementFactory factory = IOSerializableSOAPElementFactory.newInstance();
// Create an IOSerializableSOAPElement from a javax.xml.soap.SOAPElement
IOSerializableSOAPElement serializableSOAPElement = factory.createElement(soapElement);
// You can retrieve the wrapped SOAPElement from the IOSerializableSOAPElement
SOAPElement soapElement = serializableSOAPElement.getSOAPElement();
Any application-specific BaseFault instances must also adhere to this serializable requirement.
Application-specific faults
<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
{
// Determine the identity of the target printer instance.
PrinterState state = PrinterState.getState ();
if (state.OFFLINE)
{
try
{
// Get an instance of the SOAPFactory
SOAPFactory soapFactory = SOAPFactory.newInstance();
// Create the fault cause SOAPElement
SOAPElement faultCause = soapFactory.createElement("FaultCause");
faultCase.addTextNode("OFFLINE");
// Get an instance of the IOSerializableSOAPElementFactory
IOSerializableSOAPElementFactory factory = IOSerializableSOAPElementFactory.newInstance();
// Create an IOSerializableSOAPElement from the faultCause SOAPElement
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");
}
Custom binders
When you define a new application-level base fault, for example the PrinterFault fault with the PrinterFaultType type shown previously, you must provide a custom binder to define how the web services run time serializes the Java class into an appropriate XML message, and conversely how to deserialize an XML message into an instance of the Java class.
<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>
The BaseFaultBinderHelper class
WebSphere Application Server provides a BaseFaultBinderHelper class, which provides support for serializing and deserializing the data that is specific to a root BaseFault class, which all specialized BaseFault classes must extend. If a custom binder uses the BaseFaultBinderHelper class, the custom binder then needs to provide only the additional logic for serializing and deserializing the extended BaseFault data.
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
{
// Get an instance of the BaseFaultBinderHelper
private BaseFaultBinderHelper baseFaultBinderHelper = BaseFaultBinderHelperFactory.getBaseFaultBinderHelper();
public SOAPElement serialize(Object data, SOAPElement rootNode, CustomBindingContext context) throws SOAPException
{
// Serialize the BaseFault specific data
baseFaultBinderHelper.serialize(rootNode, (BaseFault)data);
// Serialize any PrinterFault specific data
...
// Return the serialized PrinterFault
return rootNode;
}
public Object deserialize(SOAPElement rootNode, CustomBindingContext context) throws SOAPException
{
// Create an instance of a PrinterFault
PrinterFault printerFault = new PrinterFault();
// Deserialize the BaseFault specific data - any additional data that
// forms the PrinterFault extension will be returned as a SOAPElement[].
SOAPElement[] printerFaultElements = baseFaultBinderHelper.deserialize(printerFault, rootNode);
// Deserialize the PrinterFault specific data contained within the printerFaultElements SOAPElement[]
...
// Return the deserialized PrinterFault
return printerFault;
}
...
}