Given a set of requirements, create code to handle system and service exceptions and faults received by a Web services client.

[Note]

WSDL-to-Java mapping

Let's look at the WSDL-to-Java mapping of faults to exceptions, starting with the WSDL. Run your favorite JAX-WS WSDL-to-Java code generator on this WSDL. It gives you the generated interface and fault classes.


<wsdl:definitions targetNamespace="urn:fault.sample"
    xmlns:tns="urn:fault.sample" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
    
  <wsdl:types>
    <xsd:schema targetNamespace="urn:fault.sample"
        xmlns:tns="urn:fault.sample" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <xsd:element name="op" type="tns:Op"/>
      <xsd:complexType name="Op">
        <xsd:sequence>
          <xsd:element name="in" type="xsd:string"/>
        </xsd:sequence>
      </xsd:complexType>
      <xsd:element name="opResponse" type="tns:OpResponse"/>
      <xsd:complexType name="OpResponse">
        <xsd:sequence>
          <xsd:element name="out" type="xsd:string"/>
        </xsd:sequence>
      </xsd:complexType>
      <xsd:element name="faultElement" type="tns:Fault"/>
      <xsd:complexType name="Fault">
        <xsd:sequence>
          <xsd:element name="code" type="xsd:string"/>
        </xsd:sequence>
      </xsd:complexType>
    </xsd:schema>
  </wsdl:types>
  
  <wsdl:message name="opRequest">
    <wsdl:part name="parameters" element="tns:op"/>
  </wsdl:message>
  
  <wsdl:message name="opResponse">
    <wsdl:part name="parameters" element="tns:opResponse"/>
  </wsdl:message>
  
  <wsdl:message name="faultMsg">
    <wsdl:part name="parameters" element="tns:faultElement"/>
  </wsdl:message>
  
  <wsdl:portType name="PT">
    <wsdl:operation name="op">
      <wsdl:input message="tns:opRequest"/>
      <wsdl:output message="tns:opResponse"/>
      <wsdl:fault name="fault" message="tns:faultMsg"/>
    </wsdl:operation>
  </wsdl:portType>
  
  <wsdl:binding name="Binding" type="tns:PT">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="op">
      <soap:operation soapAction=""/>
      <wsdl:input>
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal"/>
      </wsdl:output>
      <wsdl:fault name="fault">
        <soap:fault use="literal" name="fault"/>
      </wsdl:fault>
    </wsdl:operation>
  </wsdl:binding>
  
  <wsdl:service name="Service">
    <wsdl:port name="Port" binding="tns:Binding">
      <soap:address location="http://www.example.org/"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

					

Generated Java interface:

package sample.fault;

public interface PT {
    public String op(String in) throws FaultMsg;
}
					

The Java exception name is derived from the WSDL fault message's name; in this case FaultMsg:

package sample.fault;

public class FaultMsg extends Exception {
    private Fault faultInfo;
    public FaultMsg(String message, Fault faultInfo) {...}
    public FaultMsg(String message, Fault faultInfo, Throwable cause) {...}
    public Fault getFaultInfo() {...}
}
					

All mapped JAX-WS exceptions contain a private faultInfo instance variable. The type of this faultInfo is derived from the schema, which the fault's wrapper element refers to; in this case it's Fault:

package sample.fault;

public class Fault {
    protected String code;
    public String getCode() {...}
    public void setCode(String value) {...}
}
					

Why does a JAX-WS mapping of faults create a fault class and a fault info class? The reason is that JAX-WS delegates the generation of schema mappings to Java Architecture for XML Binding (JAXB). JAX-WS knows how to do Web services stuff, but it doesn't know how to do schema stuff. JAXB knows schema. A fault or exception is a Web services artifact. The data in a fault is a schema artifact. So the JAX-WS generator generates the exception, and the JAXB generator generates the Java bean containing the exception's data.

Java-to-WSDL mapping

JAX-WS seems to prefer that you build exceptions like the ones it generates, with the exception itself separate from the Java bean data for the exception. If you follow this pattern, you get the reverse of the mapping described in the previous section.

But separating the exception data from the exception is not typical of how a Java programmer writes exceptions. So JAX-WS also provides a mapping for the more natural exception. A simple example of this natural pattern is shown below.

SEI:

package sample2.fault;

public interface PT {
  public String op(String in) throws Fault;
}
					

Exception: package sample2.fault; public class Fault extends Exception { public Fault(String code) {...} public String getCode() {...} public void setCode(String value) {...} }

WSDL generated from above Java:


<definitions targetNamespace="http://fault.sample2/"
    xmlns:tns="http://fault.sample2/" xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
    
  <types>
    <xsd:schema>
      <xsd:import
          namespace="http://fault.sample2/"
          schemaLocation="PTImplService_schema1.xsd"/>
    </xsd:schema>
  </types>
  
  <message name="op">
    <part element="tns:op" name="parameters"/>
  </message>
  
  <message name="opResponse">
    <part element="tns:opResponse" name="parameters"/>
  </message>
  
  <message name="Fault">
    <part element="tns:Fault" name="fault"/>
  </message>
  
  <portType name="PTImpl">
    <operation name="op">
      <input message="tns:op"/>
      <output message="tns:opResponse"/>
      <fault message="tns:Fault" name="Fault"/>
    </operation>
  </portType>
  
  <binding name="PTImplPortBinding" type="tns:PTImpl">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="op">
      <soap:operation soapAction=""/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
      <fault name="Fault">
        <soap:fault name="Fault" use="literal"/>
      </fault>
    </operation>
  </binding>
  
  <service name="PTImplService">
    <port binding="tns:PTImplPortBinding" name="PTImplPort">
      <soap:address location="https://localhost:9444/SampleFault/PTImplService"/>
    </port>
  </service>
</definitions>
					
					

Schema generated from above Java:


<xs:schema targetNamespace="http://fault.sample2/"
        xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://fault.sample2/">

  <xs:element name="Fault" type="tns:Fault"/>

  <xs:element name="op" type="tns:op"/>

  <xs:element name="opResponse" type="tns:opResponse"/>

  <xs:complexType name="op">
    <xs:sequence>
      <xs:element minOccurs="0" name="arg0" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="opResponse">
    <xs:sequence>
      <xs:element minOccurs="0" name="return" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="Fault">
    <xs:sequence>
      <xs:element minOccurs="0" name="code" type="xs:string"/>
      <xs:element minOccurs="0" name="message" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>
					
					

Unmodeled faults

What happens when an unmodeled fault occurs? For example, what happens when the service above throws an exception other than sample2.fault.Fault (for instance, NullPointerException)? What happens on the client? The answer to that depends on the messaging protocol. For instance, when communicating via SOAP/HTTP, the server-side SOAP engine creates a SOAP message containing a SOAP fault with information relevant to the problem in the faultcode and faultstring fields:


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <soapenv:Fault>
      <faultcode>soapenv:Server</faultcode>
      <faultstring>java.lang.NullPointerException</faultstring>
      <detail/>
    </soapenv:Fault>
  </soapenv:Body>
</soapenv:Envelope>

					

Because a SOAP fault is returned to the client, JAX-WS has defined an exception named SOAPFaultException. When the service throws an unmodeled fault, the client receives a SOAPFaultException.

javax.xml.ws.soap.SOAPFaultException is a protocol-specific exception. It extends javax.xml.ws.ProtocolException. JAX-WS defines another extension of ProtocolException: javax.xml.ws.http.HTTPException for the XML/HTTP communication channel. Those are the only standardized bindings defined for WSDL. For other bindings, assume the binding provider defines other extensions of ProtocolException, one for each new binding.

JAX-WS defines a number of Java classes, such as Service, BindingProvider, and Dispatch. If calls to those classes fail, they throw WebServiceException, the general-purpose exception for the JAX-WS APIs.

java.lang.Object
  extended by java.lang.Throwable
      extended by java.lang.Exception
          extended by java.lang.RuntimeException
              extended by javax.xml.ws.WebServiceException
                  extended by javax.xml.ws.ProtocolException
                      extended by javax.xml.ws.soap.SOAPFaultException
                      extended by javax.xml.ws.http.HTTPException
					

Professional hosting     Belorussian informational portal         Free SCWCD 1.4 Study Guide     Free SCDJWS 1.4 Study Guide     SCDJWS 1.4 Quiz     Free IBM Certified Associate Developer Study Guide     IBM Test 000-287. Enterprise Application Development with IBM WebSphere Studio, V5.0 Study Guide     SCDJWS 5.0 Quiz