WebService Exception Process

Web services programming tips and tricks: Exception Handling with JAX-RPC

Throw the right exception from the service endpoint

developerWorks
Document options
Document options requiring JavaScript are not displayed
Set printer orientation to landscape mode Print this page
Email this page E-mail this page
Sample code

 

Rate this page
Help us improve this content

 

Level: Introductory

Ping Wang (pacific@us.ibm.com), Software Engineer, IBM
Russell Butek (butek@us.ibm.com), Software Engineer, IBM

06 Feb 2004

Explicitly declaring faults in WSDL operations, like explicitly declaring exceptions in Java methods, is good programming practice. This tip first examines the exception behavior in the absence of
wsdl:fault. It then focuses on how a
wsdl:fault is mapped to a checked Java exception and how a JAX-RPC runtime handles this checked exception.

Hide developerWorks content related to my search: java SOAP faultHide developerWorks content related to my search: java SOAP fault
Show descriptions |
Hide descriptions
Show descriptions |
Hide descriptions

 

1 – 10 of 723 search results |

View all search results

 

1) FAWS for SOAP-based Web services
Use a portable system called FAWS (FAult tolerance for Web services) to provide a client-transparent fault tolerance for Simple Object Access Protocol- (SOAP) based Web services. As Web services continue to increase in demand for application solutions and with the number of players entering the Web service arena rising, the ability of Web services to guarantee full availability of the service in the presence of failures becomes critical.

 

2) Apache SOAP type mapping, Part 1: Exploring Apache’s serialization APIs
SOAP defines a simple wire protocol for transferring application-level data. This protocol can easily carry arbitrary Java types as serialized XML, thanks to its rich and extensible type system. In this article, the first of a two-part series on the type system support found in the Apache SOAP toolkit, Gavin Bong will introduce you to the theoretical underpinnings of SOAP’s type system. You’ll also learn more about SOAP’s programmatic support for serialization and deserialization and conclude with an exploration into the toolkit’s internals. A better understanding of how these processes work will help you build your own distributed systems.

 

3) The Python Web services developer: SOAP over SMTP
When most people think of SOAP, they think of sending XML requests, and getting XML responses over the HTTP protocol. This does not always have to be the case. In fact, the SOAP protocol defines HTTP as one possible transport for SOAP messages. In this article Mike Olson and Uche Ogbuji explore sending and receiving SOAP requests over the Simple Mail Transfer Protocol (SMTP).

 

4) SOAP nodes in IBM WebSphere Message Broker V6.1, Part 1: SOAP node basics
SOAP nodes send and receive SOAP-based Web services messages, allowing a message flow to interact with Web service endpoints. The messages might be plain SOAP, SOAP with Attachments (SwA), or Message Transmission Optimization Mechanism (MTOM). The nodes are configured using Web Services Description Language (WSDL) and support WS-Security and WS-Addressing. This four-part series describes the SOAP nodes, the logical tree for the new SOAP domain, and details of configuration and runtime behavior. In this first article, you learn about the basic use of the nodes. You should have a general familiarity with SOAP-based Web services and WSDL to follow along with this article series.

 

5) The Python Web services developer: Python SOAP libraries, Part 3
In this installment of The Python Web services developer, Mike Olson gets back to writing some Python code. This column will revisit the example code from the fifth and sixth columns in this series, in which Thew authors talked about SOAP.py and ZSI, two available SOAP implementations in Python. Mike will continue the examination of these libraries and see how they interact with each other.

 

6) The Python Web services developer: Python SOAP libraries
In this first of a two-part series, Web services columnists Mike Olson and Uche Ogbuji discuss the various SOAP implementations available for Python, giving detailed code examples.

 

7) Repurposing CGI applications with SOAP
This article demonstrates how to wrap an existing CGI application into a SOAP service. Additionally, the article guides a quick tour of HTML page scraping that leads to a discussion of HTML::TreeBuilder.

 

8) Using WSDL in SOAP applications
Web Services Description Language (WSDL) is a new specification to describe networked XML-based services. It provides a simple way for service providers to describe the basic format of requests to their systems regardless of the underlying protocol (such as Simple Object Access Protocol or XML) or encoding (such as Multipurpose Internet Messaging Extensions). WSDL is a key part of the effort of the Universal Description, Discovery and Integration (UDDI) initiative to provide directories and descriptions of such on-line services for electronic business. This article provides a brief background and technical introduction to WSDL. Knowledge of XML and XML Namespaces is required and some familiarity with XML Schemas and SOAP is useful.

 

9) Faults and exceptions in JAX-WS
This article details the Java API for XML Web Services (JAX-WS) mapping of Web Services Description Language (WSDL) faults to Java exceptions, Java exceptions to WSDL faults, and some other exceptions defined by the JAX-WS specification.

 

10) Build error-proof Web services
A well-designed system should always have a powerful mechanism for handling error conditions. Web service messages, commonly implemented as Simple Object Access Protocol (SOAP) messages over the Hypertext Transfer Protocol (HTTP), use SOAP’s fault mechanism to encode server-side error conditions to the Web service client. This article will introduce the SOAP fault mechanism and explain how version 2.2 of the Apache SOAP toolkit encodes server-side exceptions into a SOAP fault.

 

 

 

Hide developerWorks source code related to my search: java SOAP faultHide developerWorks source code related to my search: java SOAP fault
Show details |
Hide details
Show details |
Hide details

 

1 – 10 of 117 source code results |

Show all search results (hosted by Krugle)

 

1) MySOAPMessageHandler.java
* @see com.ibm.pvcws.
soap.handler.Handler#handle
Fault(com.ibm.pvcws.internal.jaxrpc.security.MessageContext)*/

public boolean handle
Fault(MessageContext arg0) throws
SOAPException {

System.out.println(“My
SOAPMessageHandler handle
Fault Argument :”+arg0);

Message messageObj = arg0.getMessage();

 

2) FactorizationServiceSoapBindingStub.java

this(null);

}

public FactorizationService
SoapBindingStub(
java.net.URL endpointURL, javax.xml.rpc.Service service) throws org.apache.axis.Axis
Fault {

this(service);

super.cachedEndpoint = endpointURL;

 

3) StockQuoterSoapBindingStub.java

package com.devworks.example;

public class StockQuoter
SoapBindingStub extends com.ibm.ws.webservices.engine.client.Stub implements com.devworks.example.StockQuoter {

public StockQuoter
SoapBindingStub(
java.net.URL endpointURL, javax.xml.rpc.Service service) throws com.ibm.ws.webservices.engine.WebServices
Fault {

if (service == null) {

 

4) EchoServiceSoapBindingStub.java
public class EchoService
SoapBindingStub extends com.ibm.ws.webservices.engine.client.Stub implements com.ibm.issw.EchoService {public EchoService
SoapBindingStub(
java.net.URL endpointURL, javax.xml.rpc.Service service) throws com.ibm.ws.webservices.engine.WebServices
Fault {

if (service == null) {

super.service = new com.ibm.ws.webservices.engine.client.Service();

 

5) EchoServiceSoapBindingStub.java
public class EchoService
SoapBindingStub extends com.ibm.ws.webservices.engine.client.Stub implements com.cna.services.EchoService {public EchoService
SoapBindingStub(
java.net.URL endpointURL, javax.xml.rpc.Service service) throws com.ibm.ws.webservices.engine.WebServices
Fault {

if (service == null) {

super.service = new com.ibm.ws.webservices.engine.client.Service();

 

6) Web2SoapBindingStub.java
public class Web2
SoapBindingStub extends com.ibm.ws.webservices.engine.client.Stub implements com.mycompany.webservices.web2.Web2 {public Web2
SoapBindingStub(
java.net.URL endpointURL, javax.xml.rpc.Service service) throws com.ibm.ws.webservices.engine.WebServices
Fault {

if (service == null) {

super.service = new com.ibm.ws.webservices.engine.client.Service();

 

7) Web3SoapBindingStub.java
public class Web3
SoapBindingStub extends com.ibm.ws.webservices.engine.client.Stub implements com.mycompany.webservices.web3.Web3 {public Web3
SoapBindingStub(
java.net.URL endpointURL, javax.xml.rpc.Service service) throws com.ibm.ws.webservices.engine.WebServices
Fault {

if (service == null) {

super.service = new com.ibm.ws.webservices.engine.client.Service();

 

8) Web1SoapBindingStub.java
public class Web1
SoapBindingStub extends com.ibm.ws.webservices.engine.client.Stub implements com.mycompany.webservices.web1.Web1 {public Web1
SoapBindingStub(
java.net.URL endpointURL, javax.xml.rpc.Service service) throws com.ibm.ws.webservices.engine.WebServices
Fault {

if (service == null) {

super.service = new com.ibm.ws.webservices.engine.client.Service();

 

9) ClaimServiceSoapBindingStub.java

package com.ibm.webservices.claim;

public class ClaimService
SoapBindingStub extends com.ibm.ws.webservices.engine.client.Stub implements com.ibm.webservices.claim.ClaimService {

public ClaimService
SoapBindingStub(
java.net.URL endpointURL, javax.xml.rpc.Service service) throws com.ibm.ws.webservices.engine.WebServices
Fault {

if (service == null) {

 

10) PolicyServiceSoapBindingStub.java

package com.ibm.webservices.policy;

public class PolicyService
SoapBindingStub extends com.ibm.ws.webservices.engine.client.Stub implements com.ibm.webservices.policy.PolicyService {

public PolicyService
SoapBindingStub(
java.net.URL endpointURL, javax.xml.rpc.Service service) throws com.ibm.ws.webservices.engine.WebServices
Fault {

if (service == null) {

 

 

 

 

In the SOAP Web services world, a fault flows from the server to the client in the form of SOAP fault. A SOAP fault consists of the faultcode, faultstring, and optional fault actor and detail. The JAX-RPC specification defines various rules about how to map from a Java exception to a SOAP fault (server side) and from the SOAP fault back to the Java exception (client side).

There are four types of exceptions that can be thrown from the server.

  • java.rmi.RemoteException
  • java.lang.RuntimeException
  • javax.xml.rpc.soap.SOAPFaultException (a special, subclass of RuntimeException)
  • a checked, user-defined exception (mapped from the WSDL’s wsdl:fault construct)

The client side will receive one of the following types of exceptions. Note that the client can not catch any RuntimeException other than SOAPFaultException.

  • java.rmi.RemoteException
  • javax.xml.rpc.soap.SOAPFaultException
  • a checked, user-defined exception

This article first discusses the expected behaviour on the client when the server throws various exceptions, and then emphasizes the use of checked exceptions.

RemoteException

JAX-RPC requires that all remote methods in a service endpoint interface (SEI) throw the standard java.rmi.RemoteException. This allows exceptions which arise from communications or runtime difficulties to propagate back to the caller. However, there is no portable means to send specific subclasses of RemoteException.

The application itself could also throw a RemoteException. However, since there is no portable means of sending specific RemoteExceptions, the client cannot catch specific RemoteExceptions. For a given SOAP fault returned from the server, different client-side JAX-RPC runtimes may have different interpretations and generate different RemoteExceptions. Because of this interoperability problem, the application should avoid throwing RemoteExceptions.

 

Back to top

 

RuntimeException

When a problem occurs in a server-side JAX-RPC runtime which results in a RuntimeException being thrown (for example, NullPointerException), that exception will propagate back to the client, but it will do so as a SOAP fault. The client runtime will map SOAP fault to either RemoteException or SOAPFaultException (described below). Therefore, a service endpoint should not throw a RuntimeException expecting the client to always catch that RuntimeException because the client may receive a RemoteException instead.

 

Back to top

 

SOAPFaultException

There is one special RuntimeException: javax.xml.rpc.soap.SOAPFaultException. SOAPFaultException is more descriptive than a RuntimeException and dictates the exact SOAP fault message which flows to the client. In other words, whoever throws this fault, whether the runtime or the application, controls the SOAP fault response. Therefore, how to map the SOAP fault to an appropriate exception really depends on the content of SOAPFaultException, it may be mapped to SOAPFaultException, RemoteException or even a checked user exception. SOAPFaultException is often used by JAX-RPC handlers. A JAX-RPC application itself normally should avoid throwing the SOAPFaultException.

 

Back to top

 

Checked user exception

A good programming practice often involves explicitly defining checked user exceptions as part of the interface contract. In the JAX-RPC world, programmers need to first define wsdl:faults as part of a wsdl:operation. A wsdl:operation allows multiple wsdl:fault elements, just like a Java method allows multiple exceptions. Each wsdl:fault is mapped to a user exception as part of the SEI. In most cases, Java exceptions do not have complicated data structures; similarly for wsdl:fault, the schema definition referenced by the wsdl:fault is often straightforward. Nevertheless, it’s still very important for programmers to think over which kind of exceptions are expected to be thrown, and then define appropriate wsdl:faults.

Mapping rules

Unlike wsdl:input and wsdl:output, the message referenced by wsdl:fault is only allowed a single message part which could refer to a simple type or a complex type. If the part element has a type attribute, then you can tell directly whether the type is simple (for example, xsd:int, xsd:string, etc.) or complex. If the part element has an element attribute, then you have to step to the element to see whether the type is simple or complex.

Mapping rules for simple types

For a simple type, the Java exception name is mapped from the name attribute of the wsdl:message element. The wsdl:part name is mapped to a getter method and a parameter in the constructor of the Java exception. For example, the fault information in the WSDL in Listing 1 maps to the Java language exception in Listing 2.
Listing 1. WSDL definition with a simple fault

<definitions ...>

  <message name="empty"/>
  <message name="InsufficientFundsFault">
    <part name="balance" type="xsd:int"/>
  </message>

  <portType name="Bank">
    <operation name="throwException">
      <input message="tns:empty"/>
      <output message="tns:empty"/>
      <fault name="fault" message="tns:InsufficientFundFault"/>
    </operation>
  </portType>
  ...
</definitions>

Listing 2. Java exception from the fault in Listing 1

public class InsufficientFundFault extends java.lang.Exception {
    private int balance;
    public int getBalance() {
        return this.balance;
    }

    public InsufficientFundFault() {
    }

    public InsufficientFundFault(int balance) {
        this.balance = balance;
    }
}

 

Mapping rules for complex types

For complexTypes, the Java exception name is mapped from the name of the complexType (or the name of the element if the fault message’s part refers to an element). Each element inside the complexType is mapped to a parameter in the constructor of the Java exception and a getter method. Note that, unlike beans, there is no setter method. The only way to set such a field is through the exception constructor. For example, the fault information in the WSDL in Listing 3 maps to the Java language exception in Listing 4.
Listing 3. WSDL definition for a complex fault

<definitions ...>

  <types>
    <schema xmlns="http://www.w3.org/2001/XMLSchema">
      <element name="InsufficientFundFault">
        <complexType>
          <sequence>
            <element name="balance" type="xsd:int"/>
            <element name="requestedFund" type="xsd:int"/>
          </sequence>
        </complexType>
      </element>
    </schema>
  </types>
			 
  <message name="empty"/>
  <message name="withdrawRequest">
    <part name="amount" type="xsd:int"/>
  </message>
  <message name="InsufficientFundFaultMessage">
    <part name="fault" element="tns:InsufficientFundFault"/>
  </message>

  <portType name="Bank">
    <operation name="withdraw">
      <input message="tns:withdrawRequest"/>
      <output message="tns:empty"/>
      <fault name="fault" message="tns:InsufficientFundFaultMessage"/>
    </operation>
  </portType>

  ...
</definitions>

Listing 4: Java exception from the fault in Listing 3

    public class InsufficientFundFault 
    	extends java.lang.Exception 
    	implements java.io.Serializable {
    private int balance;
    private int requestedFund;

    public InsufficientFundFault(
           int balance,
           int requestedFund) {
        this.balance = balance;
        this.requestedFund = requestedFund;
    }

    public int getBalance() {
        return balance;
    }

    public int getRequestedFund() {
        return requestedFund;
    }
}

 

Mapping rules for fault inheritance

Suppose you want to define a subclass of InsufficientFundFault, called AccountInsufficientFundFault, to carry the account number of the requesting client (see Listing 5). Your application can throw this subclass exception and your client would receive this exception. Very straightforward.
Listing 5: WSDL faults with inheritance

  <wsdl ...>
    <types>
    <schema targetNamespace="http://example" ...>
      ...

      <complexType name="InsufficientFundFaultType">
        <sequence>
          <element name="balance" type="xsd:int"/>
          <element name="requestedFund" type="xsd:int"/>
        </sequence>
      </complexType>

      <complexType name="AccountInsufficientFundFaultType">
        <complexContent>
           <extension base="tns:InsufficientFundFaultType">
             <sequence>
               <element name="account" type="xsd:string"/>
             </sequence>
           </extension>
        </complexContent>
      </complexType> 
			     		    
      <element name="InsufficientFundFault" 
               type="tns:InsufficientFundFaultType"/>
      ...
    </schema>
    </types>
			 
    <message name="AccountInsufficientFundFaultMessage">
      <part element="tns:AccountInsufficientFundFault" name="fault"/>
    </message>
			
    <operation name="withdraw">
      <input message="tns:withdrawRequest" name="withdrawRequest"/>
      <output message="tns:withdrawResponse" name="withdrawResponse"/>
      <fault message="tns:InsufficientFundFaultMessage" 
                name="InsufficientFundFault"/>
    </operation>
    ...
  </wsdl>

 

By doing this, the method “withdraw” of the generated SEI stays the same (see Listing 6). One item to note, however, is that any subclass of InsufficientFundFault must appear in the WSDL file for the client to receive that exception. You cannot create a new subclass of InsufficientFundFault in the server-side Java component without doing the same in the WSDL file. WSDL is a declarative language. Every possible fault that a service can throw must be explicitly defined in the XML, otherwise the client will not know about it and will not be able to receive it.
Listing 6: Java SEI mapped from the above WSDL definition

  public interface Bank extends java.rmi.Remote {
    public boolean withdraw(java.lang.String account, int amount) 
        throws java.rmi.RemoteException, 
               example.InsufficientFundFaultType;
  }

 

SOAP fault content

The JAX-RPC runtime catches a user exception and serializes it to XML data based on the schema definition referenced by the message part of the wsdl:fault. Such XML data is used to fill in the content of the detail element of the SOAP fault. Listing 7 is the SOAP message for the complex InsufficientFundFault example. The SOAP message for a simpleType fault is similar except that the detail section is different.
Listing 7: SOAP Fault example

  <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
      <soapenv:Fault>
        <faultcode >...</faultcode>
        <faultstring>...</faultstring>
        <detail>
          <InsufficientFundFault xmlns="http://example">
            <balance>1000</balance>
            <requestedFund>2000</requestedFund>
          </InsufficientFundFault>
        </detail>
      </soapenv:Fault>
    </soapenv:Body>
  </soapenv:Envelope>

 

The key thing here is that the detail section carries the content which must match the schema definition referenced by wsdl:fault. In this way, the client runtime will know which user exception it should be mapped to. Also note that the SOAP fault does not carry the exception stack trace as you normally expect for the Java exception; therefore, a Web services client should not expect to see the stack trace originating from the server side.

 

Back to top

 

Summary

It is good programming practice to introduce user-defined faults. Using RemoteExceptions or RuntimeExceptions is not only too general, there is also no guarantee that every vendor will handle these in the same manner.

Once you decide to introduce user-defined faults, you must decide what kinds of faults to use — faults of simple types, faults of complexTypes, or an inheritance tree of faults — and you must understand how those faults map to Java programming artifacts.

 

Back to top

 

Download

Description Name Size Download method
Source code for this article ws-tip-jacrpc.zip 40KB HTTP
Information about download methods

 

Resources

 

About the authors

Ping Wang is one of the developers of the IBM WebSphere Web services engine. Previously, he was a developer for WebSphere System Management and focused on how to manage distributed processes using JMX (Java Management eXtension). You can contact Ping at pacific at us.ibm.com

 

Russell Butek is one of the developers of the IBM WebSphere Web services engine. He is also an IBM representative on the JAX-RPC Java Specification Request (JSR) expert group. He was involved in the implementation of Apache’s AXIS SOAP engine, driving AXIS 1.0 to comply with JAX-RPC 1.0. Previously, he was a developer of the IBM CORBA ORB and an IBM representative on a number of OMG task forces: the portable interceptor task force (of which he was chair), the core task force, and the interoperability task force. You can contact Russell at butek at us.ibm.com.
Advertisements