Menu

Understanding Overloading in WSDL

January 8, 2003

Randy J. Ray

Randy J Ray is coauthor of Programming Web Services with Perl

Author's note: Overloaded methods (or "multi-methods") are a core feature of many languages, such as Java or C++. Languages such as Perl that have flexible typing mechanisms are also capable of presenting multiple calling interfaces for a given method. The Web Services Definition Language, or WSDL, allows for describing these types of multiple-interface calls so as to properly support services written using these various languages.

Why Overloading?

Overloaded methods may or may not be what you need for the project you are working on. Additionally, there are those who argue that if a function is taking a different set of argument-types, then it should be noted by giving it a different name. But neither of these are the argument for learning how to express overloaded interfaces in WSDL. The reason is simple: languages, commercially in use today, support this feature. In order to correctly describe their interfaces using a description written in WSDL, it must be possible to describe an operation that has different calling syntaxes.

It is important to note here that overloaded operations are supported in WSDL 1.1 (see the links in the "Resources" section below),but have been removed from the draft specification for WSDL 1.2. The committee developing the new draft has decided that overloading should not be present. The reasons and opinions for this decision are outside the scope of this article, but there are reference notes regarding it in the current working draft for WSDL 1.2 (see the links at the end of the article).

How WSDL Describes a Method

In reality, WSDL doesn't really describe methods per se. WSDL is not really aware of the mechanisms behind the scenes of your Web service; its only role is to describe to a potential client the nature of the interface so that the client can connect and make use of your services. A WSDL description for a service breaks the features down into port and binding definitions, which are combined to define service blocks. Ports are described using the portType element of WSDL, and bindings use the binding element. A port defines the interface itself in abstract terms, and a binding describes the concrete nature of a port in terms of actual transport and encoding instructions.

Focusing for the moment on ports, a port describes a set of operations, which we are considering methods for the sake of this article. The operations are described in terms of their input and output definitions (and fault definitions, but these don't affect overloading). Each operation is named, and the name is used to match an abstract operation within a portType with the concrete counterpart later on in a binding. For example, the following fragments illustrate the definition of an operation within the abstract and concrete settings:


<portType name="RandomNumberPort">

  <operation name="random">

    <documentation>Return a random number between 0 and

      num</documentation>

    <input message="integer_in" />

    <output message="integer_out" />

  </operation>

</portType>



<binding name="RandomNumberSOAP" type="RandomNumberPort"

         xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">

  <soap:binding style="rpc"

                transport="http://schemas.xmlsoap.org/soap/http"/>

  <operation name="random">

    <soap:operation soapAction="http://www.blackperl.com/SOAP/random"/>

    <input>

      <soap:body use="encoded"

                 namespace="http://www.blackperl.com/SOAP/random"

                 encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>

    </input>

    <output>

      <soap:body use="encoded"

                 namespace="http://www.blackperl.com/SOAP/random"

                 encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>

    </output>

  </operation>

</binding>

    

(This fragment assumes some basic familiarity with WSDL, and we'll gloss over details like defining input/output messages and such, until the full WSDL document is presented.)

In this fragment, we define a simple random function. It's an integer-based random number generator, taking an integer value as input and returning a number in the range of [0, n-1]. The input uses a message that was called "integer_in", and the output uses a similarly-named "integer_out". Pretty simple stuff so far.

Not all uses for random numbers are integer-based, though. It's not at all unusual for people to want a random number as a floating-point value in the range of [0, 1) (that notation meaning a range that includes 0, but only approaches 1 without ever returning 1). The challenge is to express this interface so that the client decides which type of random number they want, by virtue of the type of the input value.

Two Faces on the Same Coin

In Java or C++, declaring two versions of the random function is a simple task. In Perl, it isn't necessary to define the function twice, but instead to examine the single input value while within the function itself. But the client of a web service could be written in any language, so the description carries the responsibility for making these options clear.

The previous fragment defined the random operation as taking and returning an integer. The following fragment defines the same operation, using different messages that indicate floating-point values:


<portType name="RandomNumberPort">

  <operation name="random">

    <documentation>Return a floating-point random number between 0 and

      1</documentation>

    <input message="null_in" />

    <output message="float_out" />

  </operation>

</portType>

    

There are two things to note here: First, the input is declared as a message we can assume (from the name) means that there is no actual input parameter. Since this form always uses the [0, 1) range, there's no need for an input parameter. The second, and more significant, thing to notice is that as it stands, this will conflict with the earlier definition. An operation definition must be unique by name within the portType it appears in. The catch is that the name used to identify it is actually more than just the name attribute for the tag.

Naming of Operations, Inputs, and Outputs

This is the important part to understand about WSDL: the naming of an operation is actually a combination of the operation name, the input name and the output name. The part that is most often confusing is that inputs and outputs don't usually have names assigned to them. However, they can have these attributes. It's just that most people don't need to explicitly name these parts of the operation declaration.

Put another way, inputs and outputs are always named. They actually have default names that are implied, based on the name of the operation itself. The rules for this are detailed in section 2.4.5 of the WSDL 1.1 specification, but for this example just understand that the input element's name attribute defaults to "randomRequest", and the output element's default is "randomResponse". As long as a set of operation declarations all have unique combinations of names from the operation, input and output tags, the portType block is valid.

This is the key to expressing overloaded operations in WSDL. For each of the different calling-styles for the method in question, an operation needs to be defined that is identified uniquely with regard to other operations of the same name. To better illustrate this, consider this take on the portType section:


<portType name="RandomNumberPort">

  <operation name="random">

    <documentation>Return a random number between 0 and

      num</documentation>

    <input name="int" message="integer_in" />

    <output name="int" message="integer_out" />

  </operation>

  <operation name="random">

    <documentation>Return a floating-point random number between 0 and

      1</documentation>

    <input name="float" message="null_in" />

    <output name="float" message="float_out" />

  </operation>

</portType>

    

Here, the triple of ("random", "int", "int") is easily distinct from ("random", "float", "float"). These are used to match the abstract definitions here to the concrete definitions in a binding later on.

Yes, the same consideration has to be present within the binding used to declare the service. It's not enough to do this just at the abstract level. Fortunately, for this example, the actual meaty part of the binding is the same for both types of inputs:


<binding name="RandomNumberSOAP" type="RandomNumberPort"

         xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">

  <soap:binding style="rpc"

                transport="http://schemas.xmlsoap.org/soap/http"/>

  <operation name="random">

    <soap:operation soapAction="http://www.blackperl.com/SOAP/random"/>

    <input name="int">

      <soap:body use="encoded"

                 namespace="http://www.blackperl.com/SOAP/random"

                 encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>

    </input>

    <output name="int">

      <soap:body use="encoded"

                 namespace="http://www.blackperl.com/SOAP/random"

                 encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>

    </output>

  </operation>

  <operation name="random">

    <soap:operation soapAction="http://www.blackperl.com/SOAP/random"/>

    <input name="float">

      <soap:body use="encoded"

                 namespace="http://www.blackperl.com/SOAP/random"

                 encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>

    </input>

    <output name="float">

      <soap:body use="encoded"

                 namespace="http://www.blackperl.com/SOAP/random"

                 encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>

    </output>

  </operation>

</binding>

    

The only difference here is that the input and output tags now have explicit names assigned to them. Which means that one could potentially send all the "float" versions of the random operation with a completely different "soapAction" value or even namespace and encoding.

Final View

That's all there is to understanding overloading in WSDL. By not relying on default names, the description becomes more flexible. Unfortunately, the initial reference to overloading in the WSDL 1.1 specification was limited to a brief mention in a single paragraph under section 2.5. This is too bad, as it has left many users of WSDL confused and not sure where to turn for clarification. I hope this article has been some help in that regard.

While the WSDL is complete, it doesn't describe an actual service running on www.blackperl.com.

Resources

  • The WSDL 1.1 Specification

  • The WSDL 1.2 Drafts: For version 1.2, the World Wide Web Consortium (W3C) has broken the specification into two parts. These are being developed under the auspices of the Web Services Description Working Group.

  • Part 1 of the specification deals with the basic WSDL structure and syntax (and contains the notes regarding the decision to drop overloading support in 1.2). Part 2 deals with the syntax and disposition of the binding framework.


O'Reilly & Associates recently released (December 2002) Programming Web Services with Perl .