Contents


Loosely typed versus strongly typed web services

Comments

Web services are used more and more for Enterprise Application Integration (EAI), where service consumers and service providers communicate using an Enterprise Service Bus (ESB). Integration of enterprise applications has been done for quite some time now and has typically been achieved by creating application adapters, which translate messages into internal, proprietary formats and protocols.

On the surface, it seems that using web services to integrate applications is the same, or at least a similar, concept to previous integration schemes. But web services gives us more standardization, better tools, and better interoperability between platforms and programming languages than in the past.

The challenge remains to describe the relevant service interfaces of a system. Typically, developers use one of two approaches to address this challenge. On the one hand, Web Services Description Language (WSDL) definitions can leverage XML Schema descriptions of messages, allowing exact descriptions of exchanged messages. On the other hand, many services are built with a somewhat generic interface: One string goes in and one string comes out, or plain binary objects are exchanged. The proper interpretation of messages is left to the consumer and provider. While this is supposed to be more flexible when changes occur -- because the details of a message are handled in the service implementation -- it is also more error prone and requires more manual programming.

In this article, I'll compare both styles and give examples for where each style should be applied.

Loosely typed web services

First of all, let's define the term loosely typed within the context of this article. Loosely typed means that the interface definition of the service (in WSDL) does not contain a schema that strongly defines any kind of message format that that the service uses. In other words, an application cannot completely defer to a message instance from the service interface definition alone.

One example of a loosely typed description is web service that encodes the actual content of a message as a single string. The service interface describes one input parameter, of type xsd:string, and one output parameter. The WSDL <types> section could look like Listing 1 below.

Listing 1. WSDL <types>
<?xml version="1.0" encoding="UTF-8"?>

<wsdl:definitionstargetNamespace="http://mycomp.com"xmlns:impl=

   "http://mycomp.com"xmlns:intf="http://mycomp.com"xmlns:wsdl=

   "http://schemas.xmlsoap.org/wsdl/"xmlns:wsdlsoap=

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

   "http://ws-i.org/profiles/basic/1.1/xsd"xmlns:xsd=

   "http://www.w3.org/2001/XMLSchema">

  <wsdl:types>

   <schematargetNamespace="http://mycomp.com"xmlns=

     "http://www.w3.org/2001/XMLSchema"xmlns:impl=

     "http://mycomp.com"xmlns:intf=

     "http://mycomp.com"xmlns:wsdl=

     "http://schemas.xmlsoap.org/wsdl/"xmlns:xsd=

     "http://www.w3.org/2001/XMLSchema">

     <element name="executeResponse">

      <complexType>

       <sequence>

        <element name="executeReturn" nillable="true" type="xsd:string"/>

       </sequence>

      </complexType>

     </element>

     <element name="execute">

      <complexType>

       <sequence>

        <element name="message" nillable="true" type="xsd:string"/>

       </sequence>

      </complexType>

     </element>

    </schema>

  </wsdl:types>

 

</wsdl:definitions>

Note that this is a "wrapped document/literal" web service, hence the wrapping element called "execute". (Not all of the WSDL is shown here, but trust that the remainder of it shows a document/literal binding.) The single input and output parameter definition are highlighted in bold.

Given this definition, you don't know exactly what the content of the request and response messages will look like. It might be a character-delimited string, fixed-length string, or even XML. In any case, the service consumer and service provider need to agree on a common format that they both understand, and they both need to develop code that builds and interprets that format properly. There is not much a tool can do to help here, since the exact definition of the message content is not included in the WSDL definition.

On the positive side, if the message structure changes, you do not have to update the WSDL definition. You just have to ensure that all the participants are aware of such a change and can handle the updated format. Typically, however, the disadvantages of this approach will outweigh the advantages, especially when XML is sent as the content.

Sending XML in a string

Let's look a little closer at the case where XML data is sent within this string. This might be the case where an existing application contains information in an XML form, and the goal is to send this data unchanged across the web service interface. (The data is represented as a string parameter, since XML can be represented as a string.) For example, assume an XML document, using the following format, is to be sent as a response to a request by a client, as shown Listing 2 below.

Listing 2. Sending XML in a string
Note:  This is an example only.

<customer>

  <name>Joe Smith</name>

  <address>

    <street>4308 Sunshine Blvd</street>

    <city>Rochester</city>

    <state>MN</state>

    <zip>55901</zip>

   </address>

</customer>

Listing 3 illustrates what the Simple Object Access Protocol (SOAP) response message looks like when using the service interface definition in Listing 2.

Listing 3. Listing 3. SOAP response message
   <soapenv:Envelope xmlns:soapenv

   ="http://schemas.xmlsoap.org/soap/envelope/"xmlns:soapenc=

   "http://schemas.xmlsoap.org/soap/encoding/"xmlns:xsd=

   "http://www.w3.org/2001/XMLSchema"xmlns:xsi=

   "http://www.w3.org/2001/XMLSchema-instance">

<soapenv:Header/>

<soapenv:Body>

<p416:executeResponse xmlns:p416="http://mycomp.com">

<executeReturn><customer>   <name>Joe Smith</name>   

<address>   <street>4308 Sunshine Blvd</street>     

<city>Rochester</city>   <state>MN</state>

<zip>55901</zip>   </address></customer></executeReturn>

</p416:executeResponse>

</soapenv:Body>

</soapenv:Envelope>

This doesn't really look like XML, does it? The reason is that to the SOAP engine, it is a string. If XML is passed into this string, it is encoded so that it does not interfere with the SOAP engine's XML processing. However, the encoded string is decoded again before it is handed back to the client. This process is transparent to the actual service client and provider implementation -- definitely a positive. On the other hand, it increases the size of the message, makes debugging the SOAP messaging harder, and increases processing time for each message. Later in the article, I'll show an example that avoids some of these problems while delivering the same functionality. The point here is that using a string parameter to send XML across a web service interface is generally considered bad design and should be avoided.

For an example of sending XML in a string, see the EAR file, GenericString.ear, that accompanies this article.

Using <xsd:any>

Another way of indicating that no strict definition of a message format exists in a WSDL file is the use of the <xsd:any/> element. Its occurrence in a schema simply indicates that any kind of XML can appear in its place at runtime. In that respect, it behaves much like the case where single string parameters are defined. The difference is that here, real XML goes into the message, as opposed to an encoded string. At the same time, the handling of the message still must be hand coded, because the WSDL does not include any hint as to what this message will look like.

Consequently, the Java™ APIs for XML-Based Remote Procedure Call (JAX-RPC) specification describes that <xsd:any/> is mapped to javax.xml.soap.SOAPElement. This interface is part of the standard SOAP with Attachments API for Java (SAAJ API) and defines Java interfaces for individual elements of a SOAP message. It can be parsed in the same way that one would parse a regular Document Object Model (DOM) document. I'll show an example of this further below.

Here is the WSDL definition that I have used before; however, I replace the generic string by <xsd:any/>, as shown in Listing 4 below.

Listing 4. <xsd:any/>
<wsdl:definitions targetNamespace="http://mycomp.com"xmlns:impl=

   "http://mycomp.com"xmlns:intf="http://mycomp.com"xmlns:wsdl=

   "http://schemas.xmlsoap.org/wsdl/"xmlns:wsdlsoap=

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

   "http://ws-i.org/profiles/basic/1.1/xsd"xmlns:xsd=

   "http://www.w3.org/2001/XMLSchema">

    <wsdl:types>

      <schema targetNamespace="http://mycomp.com" xmlns=

    "http://www.w3.org/2001/XMLSchema" xmlns:impl=

    "http://mycomp.com"xmlns:intf="http://mycomp.com" xmlns:wsdl=

    "http://schemas.xmlsoap.org/wsdl/" xmlns:xsd=

    "http://www.w3.org/2001/XMLSchema">

      <element name="executeResponse">

        <complexType>

          <sequence>

            <xsd:any/>

          </sequence>

       </complexType>

      </element>

      <element name="execute">

        <complexType>

          <sequence>

            <xsd:any/>

          </sequence>

       </complexType>

      </element>

    </schema>

 <wsdl:types>

<wsdl:definitions/>

Using <xsd:any/> is preferable to a generic string because you do not have to encode the message. However, it only works with XML messages, and it still requires that code appear on both the service provider and consumer sides to parse and build the message. Listing 5 illustrates what the service provider code might look like if it sends the same Customer XML document back that I have used in Listing 4:

Listing 5. Service provider code
package com.mycomp;



import javax.xml.soap.SOAPElement;

import javax.xml.soap.SOAPException;

import javax.xml.soap.SOAPFactory;



import com.ibm.websphere.webservices.soap.IBMSOAPFactory;



public class GenericAnySoapBindingImpl implements com.mycomp.GenericAny{

		 

	public String customer = 

	     "<customer>"  +

	        "<name>Joe Smith</name>"  +

	        "<address>"  +

	           "<street>4308 Sunshine Blvd</street>"  +

	           "<city>Rochester</city>"  +

	           "<state>MN</state>"  +

	           "<zip>55901</zip>"  +

	       "</address>"  +

	     "</customer>";

		 

  public javax.xml.soap.SOAPElement execute(javax.xml.soap.SOAPElement any) 

  throws java.rmi.RemoteException {

    	SOAPElement result = null;

    	try {

          SOAPFactory factory = SOAPFactory.newInstance();

    	  result = 

    	  ((IBMSOAPFactory)factory).createElementFromXMLString(customer);

    	} catch (SOAPException x) {}

        return result;

  }



}

Listing 6 shows what the SOAP response message to the above request looks like.

Listing 6. SOAP response message
Note:  This is an example only.



<soapenv:Envelope xmlns:soapenv=

   "http://schemas.xmlsoap.org/soap/envelope/" 

   xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd=

   "http://www.w3.org/2001/XMLSchema" xmlns:xsi=

   "http://www.w3.org/2001/XMLSchema-instance">

<soapenv:Header/>

<soapenv:Body>

<p416:executeResponse xmlns:p416="http://mycomp.com">

  <customer>

    <name>Joe Smith</name>

    <address>

      <street>4308 Sunshine Blvd</street>

      <city>Rochester</city>

      <state>MN</state>

      <zip>55901</zip>

    </address>

  </customer>

</p416:executeResponse>

</soapenv:Body>

</soapenv:Envelope>

This is much more readable than the message that you saw in Listing 5, because it is not encoded. However, I had to manually build the response message. Also, I have no schema that would indicate to the client what the response will be.

The GenericAny.ear accompanying this article provides a complete example showing use of the <xsd:any/> element.

Loosely typed services and document/literal style

The use of loosely typed web services is often related to the style of service that is defined in the WSDL. You can define the invocation style of a service as "document" or "RPC", and the encoding can be "SOAP" or "literal". The most common combination of these two is called "document/literal." Most web services engines use "wrapped document/literal" as their default. For a great writeup explaining these different styles, see the developerWorks article "Which style of WDSL should I use?".

However, the style you use has nothing to do with whether you create a loosely typed or generic interface or not. The way wrapped document/literal style is defined, it ends up invoking a remote procedure. This remote procedure can have one or more generic parameters, or strongly typed once. Similarly, you can define a generic interface (like the one taking just one string above) and declare it to be "rpc/encoded" in the WSDL binding.

In other words, the design decisions on invocation style and strong typing of an interface have little, if anything, to do with each other.

Loosely typed web services evaluated

As described above, loosely typed web services allow sending data without declaring up front, in the interface definition, the structure of the data. There are cases where this is useful. For example, assume you have a set of coarse-grained services that take potentially large XML documents as input. These documents might have different structures, depending on the context in which they are used. And this structure might change often throughout the lifetime of the service. A web service can be implemented in a way that it can handle all these different types of messages, possibly parsing them and routing them to their eventual destination. Changes to message formats can be made so that they are backward compatible, that is, so that existing code does not have to be updated.

Another example is the use of intermediaries. They have a web service interface and receive messages. But many times, they provide some generic processing for a message before routing it to its final destination. For example, an intermediary that provides logging of messages does not need a strongly typed interface, because it simply logs the content of any message that it receives.

Finally, a message format might exist that can not be described in an XML schema, or the resulting schema cannot be handled by the web service engine of choice. The JAX-RPC and Java Architecture for XML Binding (JAXB) specifications do not define mappings for the full set of XML Schema elements into Java, for example. Industry standard schemas exist that cannot be mapped so that messages following those standards have to be handcoded anyway. Most JAX-RPC compliant tools treat those schema elements just like they treat <xsd:any/>, namely by mapping them to javax.xml.soap.SOAPElement.

On the other hand, you have seen in the examples above that sending such arbitrary messages in a SOAP envelope often requires additional processing by the SOAP engine. The wire format of a message might not be very readable once it gets encoded. Moreover, you must write code manually to deal with the payload of a message. Since there is no clear definition of the message in WSDL, the web services tooling cannot generate this code, which can make such a solution more error prone. Validating messages cannot take place. If a message format changes, it might be easier to update the service interface and regenerate binding code than ensuring all consumers and providers properly handle the new format.

Given the obvious weaknesses of the loosely typed approach, let's examine an alternative.

Strongly typed web services

Just as you did with loosely typed services, you need to define the term strongly typed. That term refers to a service that contains a complete definition of its input and output messages in XML Schema, a schema that is either included in the WSDL definition or referred to by that WSDL definition.

The only information that a service consumer and service provider must exchange is the WSDL definition, since it contains all the information that is required to build them. For example, remember the example above where we returned the Customer document as the result of a web service. A strongly typed WSDL definition could look like Listing 7 below.

Listing 7. Strongly typed WSDL definition
<?xml version="1.0" encoding="UTF-8"?>

<wsdl:definitions targetNamespace="http://mycomp.com" xmlns:impl=

   "http://mycomp.com" xmlns:intf="http://mycomp.com" xmlns:wsdl=

   "http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap=

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

   "http://ws-i.org/profiles/basic/1.1/xsd" xmlns:xsd=

   "http://www.w3.org/2001/XMLSchema">

   <wsdl:types>

     <schema targetNamespace="http://mycomp.com" xmlns=

    "http://www.w3.org/2001/XMLSchema" xmlns:impl=

    "http://mycomp.com" xmlns:intf="http://mycomp.com" xmlns:wsdl=

    "http://schemas.xmlsoap.org/wsdl/" xmlns:xsd=

    "http://www.w3.org/2001/XMLSchema">

      <element name="getCustomerResponse">

       <complexType>

        <sequence>

         <element name="getCustomerReturn" nillable="true" type="impl:Customer"/>

        </sequence>

       </complexType>

      </element>

      <element name="getCustomer">

       <complexType>

        <sequence>

         <element name="criteria" nillable="true" type="xsd:string"/>

       </sequence>

       </complexType>

      </element>

      <complexType name="Customer">

       <sequence>

        <element name="address" nillable="true" type="impl:Address"/>

        <element name="name" nillable="true" type="xsd:string"/>

       </sequence>

      </complexType>

      <complexType name="Address">

       <sequence>

        <element name="city" nillable="true" type="xsd:string"/>

        <element name="state" nillable="true" type="xsd:string"/>

        <element name="street" nillable="true" type="xsd:string"/>

        <element name="zip" nillable="true" type="xsd:string"/>

       </sequence>

      </complexType>

  </schema>

 </wsdl:types>

</wsdl:definitions>

Instead of simply defining a string or an <xsd:any/> parameter as the return type, you now use a completely defined complex type called Customer. This can be used to generate Java code that maps any message into a regular Java object with getters and setters. You don't need to write code to manually parse XML.

Listing 8 shows what the Java implementation of such a service would look like.

Listing 8. Defined complex type
package com.mycomp;



public class TypedCustomerRetrieval {

     public Customer getCustomer(String criteria) {

		Customer customer = new Customer();

		Address address = new Address();

		address.setCity("Rochester");

		address.setState("MN");

		address.setStreet("4308 Sunshine Blvd");

		address.setZip("55901");

		 

		customer.setName("Joe Smith");

		customer.setAddress(address);

		return customer;

     }



}

The JAX-RPC tooling generates the Customer and Address classes that are used here. Just like in Listing 6 above, the data that goes across the wire is plain XML. In fact, it is exactly the same as in the <xsd:any/> example. As an additional bonus, because a complete schema exists for the message, it can be validated against that schema (even though most engines don't for performance reasons).

The complete TypedService.ear file accompanies this article. This and all other ear files for this article also include a test client.

Interface versus implementation

I mentioned earlier that some schema elements cannot be mapped into Java. Also, sometimes a service implementer might want to develop his or her own way of mapping an incoming SOAP message. In another exception, a document that is part of a web service might have many elements. The developer of the service might not want that to be mapped into a service interface that has, say, hundreds of individual parameters on it.

These situations do not require designing a web service to be loosely typed. Instead, they call for a discussion about interface versus implementation. A service can be strongly typed in its interface definition and generic in its implementation. The JAX-RPC specification requires a compliant engine to offer ways of bypassing the regular XML-to-Java type mapping and use alternative mechanisms instead. For example, WebSphere® Application Server (Application Server) allows you to map any request and/or response message into an instance of type javax.xml.soap.SOAPElement (similar to how <xsd:any/> is mapped, see Listing 4 above). For example, the WSDL extract listed above, containing complete type definitions, can be mapped into the following Java service endpoint interface, as shown in Listing 9 below.

Listing 9. Java service endpoint interface
Note:  This is an example only.



public interface TypedCustomerRetrieval extends java.rmi.Remote {

    public javax.xml.soap.SOAPElement getCustomer

    (javax.xml.soap.SOAPElement parameters) 

throws java.rmi.RemoteException;

}

There is no notion of Customer or Address in this interface. It is completely left to the developer to deal with the incoming and outgoing XML. (See the Resources section for references to articles that describe this in more detail).

Strongly typed web services evaluated

Strongly typed web services provide both consumers and providers of services with a complete definition of the data structure that is part of a service. Tools can easily generate code from such a formal contract that makes the use of SOAP and XML transparent to the client and server-side code. And as shown above, a strongly typed interface can be implemented in a loosely typed way in situations where generated code cannot or should not be used. By the way, this can be done differently between a service provider and a service consumer. The service implementer might prefer manually mapping and parsing a message. However, by providing a complete schema to the consumer, this consumer might choose to have a tool generate the appropriate mapping code. No further documentation is required between those two.

And in either case, the message that goes across the wire is typically smaller, because no encoding is required.

Summary

In this article, I have shown how web services can have different levels of typing. Loosely typed services use generic parameter definitions that do not include an explanation of the message content in form of a schema. They contain information in binary, string, or XML format (encoded), but it is up to the consumer and provider of the service to agree on this format and handle it accordingly. Loosely typed services are more flexible with respect to message format changes, message formats that vary depending on the service context, and the handling of advanced and complex data structures that cannot be handled by common tools. They also allow you to manually optimize message interpretation.

Strongly typed web services contain a complete schema definition in WSDL. This generally increases the level of automation, code generation, tool support, and use of standardized middleware. It also produces more stable code and relieves the developer from having to create infrastructure level code. And even a generically implemented service can provide a strongly typed interface definition.

In most real life scenarios that I have encountered, a strongly typed service interface is a better fit. It is best to avoid generic string type interfaces, as I pointed out earlier.

Above all and as usual, one size does not fit all. It is always up to the architect designing a solution to find the best way to describe interfaces, depending on the concrete requirements of that solution, the environment it runs in, and even the preferred style of the development team.


Downloadable resources


Related topics

  • "Which style of WSDL should I use? (developerWorks, May 2005)". A great writeup on invocation styles.
  • Get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®. You can download evaluation versions of the products at no charge, or select the Linux™ or Windows® version of developerWorks' Software Evaluation Kit.
  • Standards roadmap -- understand the impact and importance of standards and specifications for the development of SOA and web services.

Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and web services
ArticleID=93467
ArticleTitle=Loosely typed versus strongly typed web services
publish-date=09022005