Web Services Resource Framework base faults
The Web Services Resource Framework (WSRF) provides a recommended basic fault message element type from which we 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.
The common information includes the following items:
- 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.
The following two standard faults are defined for use with every WSRF operation:
- 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.
The following XML fragment shows an example of a base fault element:
<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>Important: The elements and classes that are discussed in the rest of this topic apply to JAX-RPC applications only. If the application uses JAX-WS, use the artifacts that are generated, for example by the wsimport tool, from the application WSDL document and XML schema that define and use the specific BaseFault type.
The BaseFault class
For JAX-RPC applications, WebSphere Application Server provides Java code mappings for all the base fault element types 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.
For example, the BaseFault class defines the following two constructors:
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 we can use to wrap a javax.xml.soap.SOAPElement instance to provide a serializable form of that instance.
Create an IOSerializableSOAPElement instance using the IOSerializableSOAPElementFactory class, as follows:
// 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); // 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
Applications can define their own extensions to the BaseFault element. Use XML type extensions to define a new XML type for the application fault that extends the BaseFaultType element. For example, the following XML fragment creates a new PrinterFaultType element:
<xsd:complexType name="PrinterFaultType"> <xsd:complexContent> <xsd:extension base="wsrf-bf:BaseFaultType"/> </xsd:complexContent> </xsd:complexType>The following example shows how a web service application, whose WSDL definition might define a print operation that declares two wsdl:fault messages, constructs a PrinterFault object:
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) { ... } } ...The following code shows how base fault hierarchies are handled as Java exception hierarchies:
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, 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.
The custom binder must implement the com.ibm.wsspi.webservices.binding.CustomBinder interface. Package the binder in a JAR file along with a declarative metadata file, CustomBindingProvider.xml, in the /META-INF/services directory of the JAR file. This metadata file defines the relationship between the custom binder, the Java BaseFault implementation and the BaseFault type. For example, you might define a custom binder called PrinterFaultTypeBinder, to map between the XML PrinterFaultType element and its Java implementation, PrinterFault, as follows:
<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.
The following code shows how we can implement a custom binder for the PrinterFaultType element to take advantage of the BaseFaultBinderHelper class support:
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; } ... }
Related tasks
Create stateful web services using the Web Services Resource Framework
wsimport command for JAX-WS applications
Related information:
OASIS WSRF primer