Java web services

Understanding and modeling WSDL 1.1

Learn how WSDL 1.1 defines web services, and how WSDL documents can be modeled in the Java language for verification and transformation


Content series:

This content is part # of # in the series: Java web services

Stay tuned for additional content in this series.

This content is part of the series:Java web services

Stay tuned for additional content in this series.

Web services for enterprise applications depend heavily on the use of service definitions. Service definitions specify a basic contract between the service provider and any potential consumers, detailing the types of functions provided by the service and the messages exchanged as part of each function. Service providers and consumers are free to implement their ends of the exchange in any way they want, as long as the actual messages they send match the service definition. The use of service definitions specifying XML message exchanges is what sets web services apart from earlier technologies for distributed programming.

Various techniques have been proposed for defining web services, but the most widely used approach is WSDL 1.1. WSDL 1.1 has some drawbacks, including an excessively complex structure that makes it somewhat unreadable for the uninitiated. It also suffers from the lack of an authoritative formal definition, resulting in successive "add on" clarifications that have patched some of the holes in the original specification document. In response, web services stacks tend to process WSDL 1.1 documents as flexibly as possible. This flexibility can perversely add to the confusion in understanding WSDL 1.1, because developers can see a wide range of WSDL structures with no guidance as to which approach is best.

In this article, you'll learn to understand WSDL 1.1 documents, and you'll see the first portions of a Java model for verifying WSDL documents and transforming them to a standard form.

Understanding WSDL 1.1

WSDL 1.1, published early in 2001, has technically been superseded by the W3C WSDL 2.0 recommendation published in 2007. WSDL 2.0 offers a cleaner structure than WSDL 1.1, along with more flexibility. But WSDL 2.0 suffers from a chicken-and-egg problem — WSDL 2.0 is not widely used because it's not widely supported, and because it's not widely used there's little pressure on the implementers of web services stacks to support it. WSDL 1.1, though flawed, is good enough for most purposes.

The original WSDL 1.1 specification was imprecise about how many features were to be used. Because the focus of WSDL was on working with SOAP service definitions, it also included support for some SOAP features (such as rpc encoding) that were later found to be undesirable. The Web Services Interoperability Organization (WS-I) addressed these issues in the Basic Profile (BP), which defined best practices for web services using SOAP and WSDL. BP 1.0 was approved in 2004 and updated as BP 1.1 in 2006. In this article, I'll cover WSDL 1.1 based on the WS-I BP guidelines, ignoring effectively deprecated features such as rpc encoding for SOAP.

XML Schema definitions are supposed to define the structure of XML documents. WSDL 1.1 included a schema description in the original specification, but that schema didn't match the text descriptions in several respects. This was corrected in a modified version of the schema somewhat later, but the WSDL 1.1 document was not updated to reflect this change. Then the WS-I BP group decided to make even more changes to the WSDL schema, so it created what appears to be the best-practices version of this slippery schema. Documents written to one version of the schema are generally not compatible with other versions (despite using the same namespace), but fortunately most web services tools basically ignore the schema and accept anything that looks reasonable. (See Related topics for links to the many schemas of WSDL.)

Even the WS-I BP version of the WSDL 1.1 schema doesn't help much in ensuring that WSDL 1.1 documents conform to the specification. The schema does not reflect all of the constraints in the WS-I BP, particularly with respect to the order of components. Beyond this, XML Schema is incapable of handling many types of easily stated constraints on documents (such as alternative attributes, or required extension elements from separate schemas). So checking that a WSDL 1.1 document conforms to the WSDL 1.1 specification (as amended by WS-I BP) involves a lot more than just turning on XML schema validation. I'll get back to this topic later in this article. First I'll review the structure of WSDL 1.1 service descriptions.

Components of the description

WSDL 1.1 documents use a fixed root element, conveniently named <wsdl:definitions>. Within this root element, one "passive" child element (just referencing separate WSDL 1.1 documents) and five "active" child elements (those actually contributing to the service description) are defined in the WSDL 1.1 namespace:

  • <wsdl:import> references a separate WSDL 1.1 document, with descriptions to be incorporated into this document.
  • <wsdl:types> defines XML types or elements used for message exchanges.
  • <wsdl:message> defines an actual message, in terms of XML types or elements.
  • <wsdl:portType> defines an abstract set of operations implemented by a service.
  • <wsdl:binding> defines the actual implementation of a <wsdl:portType>, using particular protocols and formats.
  • <wsdl:service> defines a service as a whole, generally including one or more <wsdl:port> elements with access information for <wsdl:binding> elements.

There's also a <wsdl:document> element that can be used for documentation purposes, as the first child of the <wsdl:definitions> element and also as the first child of any of the above elements.

A complete service description normally requires at least one of each of these elements except for <wsdl:import>, but they needn't all be present in the same document. You can use <wsdl:import> to assemble a complete WSDL description from multiple documents, giving you the flexibility to split descriptions to suit your organization. For instance, the first three description elements (<wsdl:types>, <wsdl:message>, and <wsdl:portType>) together provide a complete service interface description (perhaps defined by an architecture team), so it might make sense to keep them separate from the implementation-oriented <wsdl:binding> and <wsdl:service> elements. All the major web services stacks support splitting descriptions into multiple WSDL documents.

Listing 1 and Listing 2 show a sample of a WSDL service description split into two WSDL documents, with the interface-description components in a BookServerInterface.wsdl file and the implementation components in BookServerImpl.wsdl. Listing 1 shows BookServerInterface.wsdl:

Listing 1. BookServerInterface.wsdl
<wsdl:definitions ... xmlns:tns=""
  <wsdl:document>Book service interface definition.</wsdl:document>
    <xs:schema ...
      <xs:import namespace=""
  <wsdl:message name="getBookMessage">
    <wsdl:part name="part" element="tns:getBook"/>
  <wsdl:message name="getBookResponseMessage">
    <wsdl:part name="part" element="tns:getBookResponse"/>
  <wsdl:message name="addBookMessage">
    <wsdl:part name="part" element="tns:addBook"/>
  <wsdl:message name="addBookResponseMessage">
    <wsdl:part name="part" element="tns:addBookResponse"/>
  <wsdl:message name="addDuplicateFault">
    <wsdl:part name="fault" element="tns:addDuplicate"/>
  <wsdl:portType name="BookServerPortType">
      Book service implementation. This creates an initial library of books when the
      class is loaded, then supports method calls to access the library information
      (including adding new books).
    <wsdl:operation name="getBook">
        Get the book with a particular ISBN.
      <wsdl:input message="tns:getBookMessage"/>
      <wsdl:output message="tns:getBookResponseMessage"/>
    <wsdl:operation name="addBook">
      <wsdl:documentation>Add a new book.</wsdl:documentation>
      <wsdl:input message="tns:addBookMessage"/>
      <wsdl:output message="tns:addBookResponseMessage"/>
      <wsdl:fault message="tns:addDuplicateFault" name="addDuplicateFault"/>

Listing 2 shows BookServerImpl.wsdl. The <wsdl:import> element near its start imports the interface description from BookServerInterface.wsdl.

Listing 2. BookServerImpl.wsdl
<wsdl:definitions ... xmlns:ins=""
    Definition of actual book service implementation.
  <wsdl:import namespace=""
  <wsdl:binding name="BookServerBinding" type="ins:BookServerPortType">
    <soap:binding transport="" style="document"/>
    <wsdl:operation name="getBook">
      <soap:operation soapAction="urn:getBook"/>
    <wsdl:operation name="addBook">
      <soap:operation soapAction="urn:addBook"/>
      <wsdl:fault name="addDuplicateFault">
        <soap:fault name="addDuplicateFault"/>
  <wsdl:service name="BookServer">
    <wsdl:port name="BookServerPort" binding="tns:BookServerBinding">
      <soap:address location="http://localhost:8080/cxf/BookServer"/>

Besides the element (and attribute) definitions in the WSDL 1.1 namespace, WSDL 1.1 also defines extension elements. These extension elements are intended to slot into particular locations in WSDL 1.1 service descriptions in order to provide additional information required for a particular type of service. The only WSDL 1.1 extension elements still in widespread use are those for SOAP 1.1 bindings (seen in Listing 2, within the <wsdl:binding> and <wsdl:service> elements), which were defined by the original WSDL 1.1 specification, and for SOAP 1.2 bindings, defined by a separate specification in 2006.

Component details

The <wsdl:types> element wraps all the XML definitions used for messages, in the form of one or more <xs:schema> elements. (WSDL allows alternatives to XML Schema for these definitions, but most stacks only support XML Schema.) The <xs:schema> elements can use <xs:import> and/or <xs:include> to incorporate other schemas external to the WSDL, if desired (as well as to reference separate schemas contained within the same WSDL).

Because a single <wsdl:types> element can contain any number of schema definitions, there's never a reason to use more than one <wsdl:types> element in a WSDL document. In Listing 1, the <wsdl:types> element is near the top of BookServerInterface.wsdl.

Other than <wsdl:import> and <wsdl:types>, all the other top-level components of a WSDL document are individually named by the use of a required name attribute. If you use a targetNamespace attribute on the document root <wsdl:definitions> element (which you generally should do, as a best practice), the names for these components are defined in that target namespace. This means that when you define the name, you give only the simple or "local" part of the name, but references to that component must qualify the name with a namespace prefix or default namespace. Figure 1 shows the most important linkages between WSDL components, with the solid lines representing qualified name references and the dotted lines representing names used for identification without namespace qualification:

Figure 1. Linkages between WSDL components
Linkages between WSDL components

Messages, represented by <wsdl:message> elements, are at the core of WSDL service descriptions. <wsdl:message> elements are the descriptions of XML data exchanged between a client and a service provider. Each <wsdl:message> contains zero or more (typically one) <wsdl:part> child elements. Each part element requires its own name attribute (unique within the <wsdl:message>) and either an element or a type attribute referencing the schema definition of the XML data. Several <wsdl:message> elements are shown in Listing 1, following the <wsdl:types> element in BookServerInterface.wsdl.

<wsdl:portType> elements define the abstract interface for a service, in terms of the messages sent to and from the service. <wsdl:portType> elements contain any number of <wsdl:operation> child elements. Each <wsdl:operation> child element needs its own name attribute (required by WS-I BP to be unique within the <wsdl:portType>), and contains one or more child elements describing the messages used by the operation. The child elements are of three types, representing different types of usage:

  • <wsdl:input> : Data sent from the client to the service provider as input to the operation
  • <wsdl:output> : Data returned to the client by the service provider as the result of the operation
  • <wsdl:fault> : Data returned to the client by the service provider when an error occurs in processing

WSDL 1.1 defines several patterns of interactions between the client and the service provider, as represented by different sequences of <wsdl:input> and <wsdl:output> child elements, but not all the patterns are well enough defined to be implemented. WS-I BP restricts the patterns to just two: request-response operations, with an <wsdl:input> followed by a <wsdl:output>, and one-way operations, with only a <wsdl:input>. In the case of request-response operations (the most common type, by far), the <wsdl:input> and <wsdl:output> elements can be followed by any number of <wsdl:fault> elements.

Each <wsdl:input>, <wsdl:output>, or <wsdl:fault> element references a message description through the required message attribute. This reference is namespace-qualified, so it generally needs to include a prefix. You can see examples of this in Listing 1, for instance with the <wsdl:input message="tns:getBookMessage"/> element used in the getBook operation description. (The tns prefix is defined on the root <wsdl:definitions> element with the same namespace URI as the targetNamespace attribute.)

You can think of the <wsdl:portType> as the logical equivalent of a Java interface in most respects, with the <wsdl:operation> elements equivalent to methods, the <wsdl:input> elements as method parameters, the <wsdl:output> elements as method returns, and the <wsdl:fault> elements as checked exceptions. Java code generation from WSDL uses these correspondences, as do most tools that generate WSDL from existing Java code.

<wsdl:binding> elements represent an instance of the abstract interface defined by a <wsdl:portType>, seen in Listing 2 at the start of BookServerImpl.wsdl. The type attribute gives the qualified name of the port type implemented by the binding.

The child elements of the <wsdl:binding> give the details of how the port type is implemented. The child elements from the WSDL namespace correspond to those of the <wsdl:portType> and must use the same name values — not namespace-qualified references, as with the <wsdl:portType> reference. Figure 1 shows this connection at the <wsdl:operation> level by dotted lines. The same connection by name applies to the <wsdl:input>/<wsdl:output>/<wsdl:fault> child elements of the <wsdl:operation> elements. Despite this reuse of the same element names, the content of these elements is very different when they're children of a <wsdl:binding> rather than a <wsdl:portType> element.

<wsdl:binding> is where the extensions defined by WSDL come into play. The <soap:binding> child element is used in defining a SOAP service (the only type of service allowed by the WS-I BP, though WSDL 1.1 also allows HTTP bindings). This <soap:binding> element uses the required transport attribute to define the type of transport used by the binding. (HTTP, as shown by the value in Listing 2, is the only choice allowed by the WS-I BP.) The optional style attribute lets you choose between rpc and document styles for the XML data representation (with the default of document most common, corresponding to messages using schema element definitions, rather than type definitions).

Inside each <wsdl:operation> child of the <wsdl:binding>, a <soap:operation> element can be used to specify a SOAPAction value for identifying requests invoking that operation (and potentially also to override the choice of rpc or document style determined by the <soap:binding> element, though the WS-I BP forbids this use). Each <wsdl:input>/<wsdl:output>/<wsdl:fault> child element contains another extension element, which in the case of Listing 2 is always <soap:body> (indicating that the message data is sent in the SOAP message body — it's also possible to send data and even faults in the SOAP headers, though I consider this a poor practice) for a <wsdl:input> or <wsdl:output>, or the equivalent <soap:fault> used with a <wsdl:fault>.

The final component of a WSDL service description is the <wsdl:service> element, which consists of a grouping of <wsdl:port> elements. Each <wsdl:port> element associates an access address with a <wsdl:binding>. The access address is provided by the nested <soap:address> extension element.

Working with WSDL

With all the variations of schemas and rules for WSDL 1.1 documents, it's no surprise that many documents don't match the best-practices form defined by WS-I BP. Support by all the web services stacks for many variances from the best-practices form has helped perpetuate the use of outdated or incorrect constructs, leading to the spread of bad practices across the industry. And I'm definitely not immune from this contagion — in reviewing the WSDL documents I've provided for sample code in this series, I was surprised to find that not one was completely correct.

So when I set out to write this article, I thought it would be good to include a tool people could use to verify WSDL documents against the best-practices rules. It seemed a small step from there to transforming WSDL documents into the best-practices form, as long as the original WSDL is free of errors. This turned out to be considerably more work than I'd originally planned, and the full details of the model will be developed over the next two articles in this series.

Many different models have been constructed for working with WSDL documents in the Java language, including the widely used Web Services Description Language for Java Toolkit (WSDL4J), which is the JSR 110 reference implementation (see Related topics). None of those models really seemed to fit with what I wanted to accomplish, because of the dual goals of first, reading WSDL documents in any halfway reasonable form and reporting both errors and variations from best practices, and second, writing error-free WSDL documents reformatted into best-practices form. WSDL4J, for instance, would not maintain the order of elements from the input so that I could report ordering issues, and also does not handle schema definitions so could not be used directly to check the references from <wsdl:part> elements. So I could choose between setting my goals more realistically or writing my own model. I naturally chose to write my own model.

WSDL model

I'd previously implemented a partial WSDL model for use with JiBX data binding, as part of the JiBX/WS project. That model was designed for output only, and it involves a relatively small number of classes that in some cases combine data from nested elements of the WSDL XML structure (the <wsdl:message> combined with a single <wsdl:part> child, the <wsdl:input>, <wsdl:output>, and <wsdl:fault> within a <wsdl:binding> combined with a <soap:body> or <soap:fault> element, and so on). This compact class structure made it easy to construct the subset of WSDL documents supported by the structure, but when I initially considered basing a verification and restructuring tool on that model, I realized that supporting input of possibly poorly structured WSDL would require a model closer to the XML representation.

Code generation from the WS-I BP schema for WSDL 1.1 was another option. When I looked at that, I realized that just using the generated classes directly would be a mess, because the schema includes redundant types as well as some awkward constructs used to represent the different message-exchange patterns (some of which were then forbidden by the WS-I BP text).

So I ended up just constructing the classes manually, though the end result was pretty much the same as if I'd started with the code generated from the schema and just pruned out the unnecessary duplication and complexity. JiBX data binding supports multiple bindings to the same classes, so I was able to set up the input binding to handle the full range of options allowed by any version of WSDL 1.1 while configuring the output binding to output WSDL only in a best-practices form.

Listing 3 shows part of the Definitions class, corresponding to the root <wsdl:definitions> element:

Listing 3. Definitions class (partial)
public class Definitions extends ElementBase
    /** Enumeration of child elements, in expected order. */
    static enum AddState {
        invalid, imports, types, message, portType, binding, service };
    /** List of allowed attribute names. */
    public static final StringArray s_allowedAttributes =
        new StringArray(new String[] { "name", "targetNamespace" });
    /** Validation context in use. */
    private ValidationContext<ElementBase,Definitions> m_validationContext;
    /** Current state (used for checking order in which child elements are added). */
    private AddState m_state;
    /** Name for this definitions. */
    private String m_name;
    /** Target namespace for WSDL. */
    private String m_targetNamespace;
    /** List of all import child elements. */
    private List<Import> m_imports = new ArrayList<Import>();
    /** List of all types child elements. */
    private List<Types> m_types = new ArrayList<Types>();
    /** List of all message child elements. */
    private List<Message> m_messages = new ArrayList<Message>();
    /** List of all portType child elements. */
    private List<PortType> m_portTypes = new ArrayList<PortType>();
    /** List of all binding child elements. */
    private List<Binding> m_bindings = new ArrayList<Binding>();
    /** List of all services child elements. */
    private List<Service> m_services = new ArrayList<Service>();
    /** Map from qualified name to message in this definition. */
    private Map<QName,Message> m_nameMessageMap =
        new HashMap<QName,Message>();
    /** Map from qualified name to port type in this definition. */
    private Map<QName,PortType> m_namePortTypeMap =
        new HashMap<QName,PortType>();

    /** Map from qualified name to message in this definition. */
    private Map<QName,Binding> m_nameBindingMap =
        new HashMap<QName,Binding>();
    /** Map from qualified name to service in this definition. */
    private Map<QName,Service> m_nameServiceMap =
        new HashMap<QName,Service>();
     * Check state transitions between different types of child elements. 
     * If the elements are not in the expected order,
     * this flags the first out-of-order element for reporting.
     * @param state new add state
     * @param comp element component
    private void checkAdd(AddState state, ElementBase comp) {
        if (m_state != state) {
            if (m_state == null || (m_state != AddState.invalid &&
                state.ordinal() > m_state.ordinal())) {
                // advanced on to another type of child element
                m_state = state;
            } else if (state.ordinal() < m_state.ordinal()) {
                // report child element out of order
                    ("Child element of wsdl:definitions out of order", comp);
                m_state = AddState.invalid;
     * Add an unmarshalled wsdl:message child element. This also indexes the message by
     * name for validation access.
     * @param child
    public void addMessage(Message child) {
        checkAdd(AddState.message, child);
        addName(child.getName(), child, m_nameMessageMap);

The organization of the child-element data in Listing 3 shows how the model supports both general-form input and best-practices output. Rather than using a single list of child elements of all types, it uses separate lists for each type. The input JiBX binding treats the child elements as an unordered set, calling a set-method specific to the type of element each time a child element is unmarshalled. The set-method adds the instance to a typed list rather than replacing any previous value, as you can see from the addMessage() set-method used for <wsdl:message> child elements. Each set-method also runs a state check to catch cases in which elements are not in the expected order.

Extension attributes and elements (basically any attributes or elements that don't use the WSDL 1.1 namespace) are allowed in any of the WSDL elements. The WS-Policy configurations embedded in the WSDL documents from previous articles in this series are one example of such extension elements, as are the actual policy references. The best practice with these extension elements is for them to precede any child elements from the WSDL 1.1 namespace, and that's the way they're handled in the output binding. The input binding processes extension elements and attributes using code from a base class of the WSDL element classes, not shown in Listing 3, and allows the elements to be in any order (generating a warning if they follow an element from the WSDL 1.1 namespace).

The model handles known extension elements by using separate bindings for each extension namespace, each with its own set of classes. I'll cover the handling of these extension elements in greater detail in the next Java web services installment, which will also provide more details of the source code.

Verifying the model

Some basic verification of WSDL data is performed as unmarshalled objects corresponding to elements are added into the WSDL document's tree structure, as shown in the addMessage() code at the end of Listing 3. This code uses the checkAdd() method to check the ordering of child elements, and the addName() method to make sure a valid name has been supplied (text matches the NCName schema type, and the value is unique within the element type) and to map the name to the object. But that's only checking the most basic information for the element in isolation; more verification code needs to be used to check other properties of each element and the interrelations between elements.

JiBX allows you to call user-extension hooks as part of the unmarshalling and marshalling process. The WSDL model uses one such extension hook, a post-set method, to run the verification logic. A post-set method is called after the unmarshalling of the associated object is completed, so it's often a good way to run object-verification checks. In the case of verifying WSDL, the easiest approach is to run all the object verification off a single post-set method, for the root <wsdl:definitions> element. This approach avoids any issues with forward references to components of the WSDL document when the components are not in the expected order.

More extensions

In this article, you've seen the basics of WSDL structure and usage, along with the introduction to a Java data model for WSDL intended to support both verifying WSDL documents and transforming them to a best-practices form.

The next article in the series takes this topic further, looking at the problems frequently encountered in writing WS-Policy and WS-SecurityPolicy assertions. It will also cover the WSDL model and verification processing in more depth, including extending the model to include WS-Policy/WS-SecurityPolicy assertions embedded in WSDL.

Downloadable resources

Related topics

Zone=Java development, SOA and web services
ArticleTitle=Java web services: Understanding and modeling WSDL 1.1