Skip to main content

Web services hints and tips: Design reusable WSDL faults

Russell Butek (butek@us.ibm.com), IT Specialist, IBM, Software Group
Russell Butek is an IBM SOA and Web services consultant. He has been one of the developers of the IBM WebSphere Web services engine. He has also been a member 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.

Summary:  We all agree that defining Web Services Description Language (WSDL) faults is good (if you disagree, then you're probably not reading this article). There are a number of ways to define WSDL faults, but only a limited subset provides for reuse. This article presents you with a template for reusable WSDL faults, shows you how the template is reusable, and identifies some things you should avoid.

View more content in this series

Date:  25 Mar 2008
Level:  Intermediate PDF:  A4 and Letter (35KB)Get Adobe® Reader®
Activity:  2812 views

Reusable fault definition template

Before jumping into details of what makes a fault reusable, take a look at an example of a reusable fault. Listing 1 shows the XML schema, and Listing 2 shows the WSDL.


Listing 1. Template schema for a reusable fault
<xsd:schema 
 targetNamespace="urn:SchemaTemplates"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <xsd:complexType name="Fault"><xsd:sequence><xsd:element minOccurs="0" name="reason" type="xsd:string"/></xsd:sequence></xsd:complexType>
</xsd:schema>


Listing 2. Template WSDL for a reusable fault
<wsdl:definitions 
 targetNamespace="urn:WSDLTemplates"
 xmlns:tns="urn:WSDLTemplates"
 xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
  <wsdl:types>
   <xsd:schema 
     targetNamespace="urn:WSDLTemplates" 
     xmlns:tns="urn:WSDLTemplates"
     xmlns:t="urn:SchemaTemplates"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:import namespace="urn:SchemaTemplates" schemaLocation="Fault.xsd"/>
    <xsd:element name="op1" type="tns:op1"/>
    <xsd:complexType name="op1">
     <xsd:sequence>
      <xsd:element name="input" type="xsd:string"/>
     </xsd:sequence>
    </xsd:complexType>
    <xsd:element name="op1Response" type="tns:op1Response"/>
    <xsd:complexType name="op1Response">
     <xsd:sequence>
      <xsd:element name="output" type="xsd:string"/>
     </xsd:sequence>
    </xsd:complexType>
    <xsd:element name="fault" type="t:Fault"/>
   </xsd:schema>
  </wsdl:types>
  <wsdl:message name="op1RequestMsg">
   <wsdl:part name="op1Parameters" element="tns:op1"/>
  </wsdl:message>
  <wsdl:message name="op1ResponseMsg">
   <wsdl:part name="op1Result" element="tns:op1Response"/>
  </wsdl:message>
  <wsdl:message name="faultMsg"><wsdl:part name="fault" element="tns:fault"/>  </wsdl:message>
  <wsdl:portType name="Interface">
   <wsdl:operation name="op1">
    <wsdl:input name="op1Request" message="tns:op1RequestMsg"/>
    <wsdl:output name="op1Response" message="tns:op1ResponseMsg"/>
    <wsdl:fault name="fault" message="tns:faultMsg"/>
   </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="Binding" type="tns:Interface">
   <soap:binding 
    style="document" 
    transport="http://schemas.xmlsoap.org/soap/http"/>
   <wsdl:operation name="op1">
    <soap:operation soapAction=""/>
    <wsdl:input name="op1Request">
     <soap:body use="literal"/>
    </wsdl:input>
    <wsdl:output name="op1Response">
     <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>


Levels of reuse

If you define your WSDL following this pattern, you have reusable faults. But reusability comes at a number of levels. You don't necessarily have to adhere to the full reusability shown here. Let's look at those levels.

Intra-WSDL reuse

Intra-WSDL reuse is a local level of reuse: reuse within the WSDL file. To achieve intra-WSDL reuse, avoid unnecessary associations; in particular, avoid putting operation names into fault names. This may sound like an obvious practice, but some tools create such fault names. For example, the message name might be generated as op1_faultMsg. Tools and graphical editors make life easier by doing a lot of the grunt work for you, but sometimes what they generate may not be precisely what you want. If your fault contains the operation name, when you create a new operation—for example, op2—and you want to reuse op1's fault, it looks rather odd in op2 to refer to op1_faultMsg. You can create another WSDL message named op2_faultMsg, which refers to the same schema element that op1_faultMsg refers to, but that's extra overhead that you don't need. If you disassociate the fault message name from the operation name, you can reuse that message without it looking strange (see Listing 3).


Listing 3. Add op2 to the WSDL
.
.
.
 <wsdl:operation name="op2">
  <wsdl:input name="op2Request" message="tns:op2RequestMsg"/>
  <wsdl:output name="op2Response" message="tns:op2ResponseMsg"/>
  <wsdl:fault name="fault" message="tns:faultMsg"/>
 </wsdl:operation>
.
.
.

Inter-WSDL reuse

Inter-WSDL reuse is reuse between WSDLs where multiple WSDLs can use the same fault. There are two things to avoid here:

  • Obviously, don't define your fault in a WSDL's types section. Anything that you define directly within a WSDL types section is only visible to that WSDL. It's not reusable by other WSDLs.
  • The second is more obscure and requires you to think about mapping to programming languages. Take a look at your fault type. Because fault contains a single string field, you might prefer to go the simple route and put the string directly in the fault element rather than to go through t:Fault to get to the string. Some tools create this sort of fault (see Listing 4).

Listing 4. A fault that's too simple
  
.
.
.
<xsd:schema ...>
.
.
.
 <xsd:element name="fault" type="xsd:string"/>
</xsd:schema>
.
.
.
<wsdl:message name="faultMsg">
 <wsdl:part name="fault" element="tns:fault"/>
</wsdl:message>
.
.
.

While you can reuse schema elements and schema types, consider the programming language that the WSDL will map to. Language mappings, such as Java™ API for XML-based RPC (JAX-RPC), map schema types in a straightforward manner to language constructs. But it's not always obvious how elements are mapped. In the case of JAX-RPC, a fault maps to an exception class. If the fault is defined with a type, the name and package of the exception is mapped from the fault's type name and namespace. If the fault is defined simply as an element, then the name of the exception is mapped from the message name, and the package is mapped from the message's namespace (see Listing 5). As such, the fault is only reusable within the message's enclosing namespace, not universally reusable. You can define another fault message that reuses your existing fault element, but JAX-RPC maps it to yet another exception; it doesn't reuse the existing exception.


Listing 5. Java signature from Listing 4's WSDL
public String op1(String input) throws RemoteException, WSDLTemplates.FaultMsg;

Object reuse

The final level of reuse is a bit more abstract. Defining a fault as you have, it's not simply a fault, it's also a data type. This is particularly useful when fault data might be necessary outside of a SOAP fault, for instance, if you're dealing with batch operations. In a simple operation, you have a set of inputs and a set of outputs. A batch version of this operation would contain an array of the set of inputs and an array of the set of outputs. If your nonbatch version of the operation can also throw a fault, then you should have a way to plug the fault data into the output array. When you define the fault like in this article, that's easy. Listing 6 and Listing 7 show a batch example. It builds on the XML Schema Definition (XSD) and WSDL from Listing 1 and Listing 2, adding a batch version of op1 called batchOp1 and its additional data types.


Listing 6. XSD for batch operation with faults
<xsd:schema 
  targetNamespace="urn:SchemaTemplates"
  xmlns:tns="urn:SchemaTemplates"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <xsd:complexType name="Fault">
  <xsd:sequence>
   <xsd:element minOccurs="0" name="reason" type="xsd:string"/>
  </xsd:sequence>
 </xsd:complexType>
 <xsd:complexType name="Response" abstract="true"/><xsd:complexType name="NormalResponse"><xsd:complexContent><xsd:extension base="tns:Response"><xsd:sequence><xsd:element name="response" type="xsd:string"/></xsd:sequence></xsd:extension></xsd:complexContent></xsd:complexType><xsd:complexType name="FaultResponse"><xsd:complexContent><xsd:extension base="tns:Response"><xsd:sequence><xsd:element name="fault" type="tns:Fault"/></xsd:sequence></xsd:extension> </xsd:complexContent></xsd:complexType>
</xsd:schema>


Listing 7. WSDL for batch operation with faults
<wsdl:definitions 
   targetNamespace="urn:WSDLTemplates"
   xmlns:tns="urn:WSDLTemplates"
   xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
  <wsdl:types>
   <xsd:schema 
     targetNamespace="urn:WSDLTemplates" 
     xmlns:tns="urn:WSDLTemplates"
     xmlns:t="urn:SchemaTemplates"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:import namespace="urn:SchemaTemplates" schemaLocation="Fault.xsd"/>
    <xsd:element name="op1" type="tns:op1"/>
    <xsd:complexType name="op1">
     <xsd:sequence>
      <xsd:element name="input" type="xsd:string"/>
     </xsd:sequence>
    </xsd:complexType>
    <xsd:element name="op1Response" type="tns:op1Response"/>
    <xsd:complexType name="op1Response">
     <xsd:sequence>
      <xsd:element name="output" type="xsd:string"/>
     </xsd:sequence>
    </xsd:complexType>
    <xsd:element name="batchOp1" type="tns:batchOp1"/><xsd:complexType name="batchOp1"><xsd:sequence><xsd:element name="input" type="xsd:string" maxOccurs="unbounded"/></xsd:sequence></xsd:complexType><xsd:element name="batchOp1Response" type="tns:batchOp1Response"/><xsd:complexType name="batchOp1Response"><xsd:sequence><xsd:element name="output" type="t:Response" maxOccurs="unbounded"/></xsd:sequence></xsd:complexType>
    <xsd:element name="fault" type="t:Fault"/>
   </xsd:schema>
  </wsdl:types>
  <wsdl:message name="op1RequestMsg">
   <wsdl:part name="op1Parameters" element="tns:op1"/>
  </wsdl:message>
  <wsdl:message name="op1ResponseMsg">
   <wsdl:part name="op1Result" element="tns:op1Response"/>
  </wsdl:message>
  <wsdl:message name="faultMsg">
   <wsdl:part name="fault" element="tns:fault"/>
  </wsdl:message>
  <wsdl:message name="batchOp1RequestMsg"><wsdl:part name="batchOp1Parameters" element="tns:batchOp1"/></wsdl:message><wsdl:message name="batchOp1ResponseMsg"><wsdl:part name="batchOp1Result" element="tns:batchOp1Response"/></wsdl:message>
  <wsdl:portType name="Interface">
   <wsdl:operation name="op1">
    <wsdl:input name="op1Request" message="tns:op1RequestMsg"/>
    <wsdl:output name="op1Response" message="tns:op1ResponseMsg"/>
    <wsdl:fault name="fault" message="tns:faultMsg"/>
   </wsdl:operation>
   <wsdl:operation name="batchOp1"><wsdl:input name="batchOp1Request" message="tns:batchOp1RequestMsg"/><wsdl:output name="batchOp1Response" message="tns:batchOp1ResponseMsg"/></wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="Binding" type="tns:Interface">
   <soap:binding 
    style="document" 
    transport="http://schemas.xmlsoap.org/soap/http"/>
   <wsdl:operation name="op1">
    <soap:operation soapAction=""/>
     <wsdl:input name="op1Request">
      <soap:body use="literal"/>
     </wsdl:input>
     <wsdl:output name="op1Response">
      <soap:body use="literal"/>
     </wsdl:output>
     <wsdl:fault name="fault">
      <soap:fault use="literal" name="fault"/>
     </wsdl:fault>
    </wsdl:operation>
    <wsdl:operation name="batchOp1"><soap:operation soapAction=""/><wsdl:input name="batchOp1Request"><soap:body use="literal"/></wsdl:input><wsdl:output name="batchOp1Response"><soap:body use="literal"/></wsdl:output></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>

batchOp1 returns an array of Response. Response is an abstract type, so you have to fill the array with concrete extensions. The Response array elements may contain either NormalResponse objects or FaultResponse objects.

Real-world extension of this batch model

In a real-world example, you'd probably have multiple faults. To accommodate them, you can build a hierarchy of faults and then plug your base class of all faults into the FaultResponse type.

Summary

It's useful to make WSDL faults as extensible as possible. Hopefully you've learned how to do just that in this article.


Resources

Learn

Get products and technologies

  • Innovate your next development project with IBM trial software, available for download or on DVD.

Discuss

About the author

Russell Butek is an IBM SOA and Web services consultant. He has been one of the developers of the IBM WebSphere Web services engine. He has also been a member 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.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and Web services, Information Management
ArticleID=292229
ArticleTitle=Web services hints and tips: Design reusable WSDL faults
publish-date=03252008
author1-email=butek@us.ibm.com
author1-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers