Codehaus XFire
DocumentationQuicklinksDevelopers
Sponsors |
Exceptions in ServicesAny non-runtime exception that is thrown by a service will eventually be caught by XFire and turned into a Fault. The fault is created by the static method XFireFault.createFault(Exception e). If a fault occurrs, all the handlers that been executed will have their handleFault() method executed in the order reverse of execution. When a fault occurs, the fault pipeline is invoked. This is created from the service's fault handlers, the transport's fault handlers, and the global fault handlers. To add a handler to the fault pipeline you would do something like so: Service myService = ...;
myService.addFaultHandler(new MyFaultHandler());
You should create your faiult handler by subclassing org.codehaus.xfire.handler.AbstractHandler. This will fill in various required functions. The only method you are required to provide is 'invoke' Inside your FaultHandler you may want to get ahold of the fault. This can be done like so: public void invoke(MessageContext context) throws Exception { XFireFault fault = (XFireFault) context.getExchange().getFaultMessage().getBody(); ... do something with the fault } Custom Exceptions to SOAP FaultsXFire provides a way to process your custom exceptions as SOAP Faults when not using JAX-WS 2.0 @WebFault. <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soap:Body> <soap:Fault> <faultcode>soap:Client</faultcode> <faultstring>A NPE occured</faultstring> <detail> <WeatherFault xmlns="http://www.webservicex.net"> <detailMessage>More explanation here...</detailMessage> <code>code1</code> </WeatherFault> </detail> </soap:Fault> </soap:Body> </soap:Envelope> To add your custom data in the <detail /> element, your exception needs to extend org.codehaus.xfire.fault.FaultInfoException. package org.codehaus.xfire.jaxb; import javax.xml.namespace.QName; import org.codehaus.xfire.fault.FaultInfoException; import net.webservicex.WeatherFaultDetail; public class WeatherException extends FaultInfoException { private WeatherFaultDetail faultDetail; public WeatherException(Throwable cause, String message, WeatherFaultDetail detail) { super(message, cause); this.faultDetail = detail; } public WeatherFaultDetail getFaultInfo() { return faultDetail; } public static QName getFaultName() { return new QName("http://www.webservicex.net", "WeatherFault"); } } The two important methods in this class are the getFaultInfo() method which will return the detail of the fault, and the getFaultName() method which will return the QName of the fault type. This means there must be a schema that defines the http://www.webservicex.net/WeatherFault type. Here is an example of such a schema : <s:schema elementFormDefault="qualified" targetNamespace="http://www.webservicex.net" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.webservicex.net"> <s:complexType name="WeatherFaultDetail"> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="detailMessage" type="s:string"/> <s:element minOccurs="0" maxOccurs="1" name="code" type="s:string"/> </s:sequence> </s:complexType> </s:schema> When a service interface has a method that throws a WeatherException, there will be a corresponding WSDL operation with a wsdl:fault which name will be WeatherFault, and which detail type will be WeatherFaultDetail : @WebMethod GetWeatherByZipCodeResponse GetWeatherByZipCode(@WebParam(name="GetWeatherByZipCode") GetWeatherByZipCode body) throws WeatherException; Here is a sample of the resulting WSDL : <wsdl:definitions targetNamespace="http://www.webservicex.net" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://www.webservicex.net" xmlns:....> <wsdl:types> ......... <s:schema elementFormDefault="qualified" targetNamespace="http://www.webservicex.net" xmlns:s="http://www.w3.org/2001/XMLSchema"> ......... <s:complexType name="WeatherFaultDetail"> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="detailMessage" type="s:string"/> <s:element minOccurs="0" maxOccurs="1" name="code" type="s:string"/> </s:sequence> </s:complexType> <xsd:element name="WeatherFault" type="tns:WeatherFaultDetail"/> ......... </s:schema> ......... </wsdl:types> ......... <wsdl:operation name="GetWeatherByZipCode"> <wsdlsoap:operation soapAction=""/> <wsdl:input name="GetWeatherByZipCodeRequest"> <wsdlsoap:body use="literal"/> </wsdl:input> <wsdl:output name="GetWeatherByZipCodeResponse"> <wsdlsoap:body use="literal"/> </wsdl:output> <wsdl:fault name="WeatherFault"> <wsdlsoap:fault name="WeatherFault" use="literal"/> </wsdl:fault> </wsdl:operation> Now clients know that a WeatherFault can be thrown when invoking GetWeatherByZipCode operation, and they know how to process custom data in the <detail /> element. |