Publish and find UDDI tModels with JAXR and WSDL

Work with WSDL, JAXR, and UDDI

Imagine you are a travel agent and frequently book cruise ship vacations. To offer your customers choice, you must maintain an up-to-date list of exotic destinations. In the past, you could have gathered this information by obtaining cruise ship company directories, inspecting each company's Website, or telephoning cruise operators to find out what cities their companies served.

Web services allow you to compile and maintain such lists automatically. That convenience comes with two requirements: First, cruise ship companies must agree to use a common Web service interface when publishing their destinations. Second, each company must implement that interface and register its implementation in Web service registries. With those requirements satisfied, you can consult Web service registries, discover all cruise destination service instances, invoke each service, and produce your cruise destinations master list.

The pattern of finding all implementations of a Web service interface and possibly invoking those service instances proves useful in other contexts as well. Portal Websites still rely on manual—or semi-manual—compilation of news articles, automobile inventories, available hotel rooms, or airline seats. Even when data exchanges electronically, that automation often comes at the expense of lengthy and pricey system integration. Among the biggest motivations for building Web services is the desire to automate those tedious information-gathering tasks. This article provides a working example of how UDDI (Universal Description, Discovery, and Integration) registries, the Java API for XML Registries (JAXR), and the Web Services Description Language (WSDL) work together to initiate that automation.

Reuse your WSDL

Currently, several industry groups are working to define Web service interface standards. Examples are the Open Travel Alliance for travel, the Star Consortium for automotive retail, and RosettaNet for supply chain management. Many of those groups employ a community-oriented process and make their specifications available to anyone for comments.

Real-world interface specifications aim to be comprehensive and are rather complex. Thus, to make this article easy to follow, I use a simple interface definition for the example cruise ship destination Web service. That interface features only a single method. When invoked, that method produces a list of destinations a cruise company serves. Here is that interface in Java:

   
public interface CruiseService {
    public String[] cruiseDestinations(); 
}

Because Web services aim to remain programming language-neutral, we must convert this interface definition to a format not tied to Java. WSDL defines a document structure suitable for describing Web service interfaces with XML data elements. My previous Web Services column demonstrated how development tools, such as open source Apache Axis, convert a Java interface to a WSDL document.

As apparent from Web service-related discussion lists, many developers debate the better practice: first define your Web service's interface with code—for instance, Java code—then convert that code to WSDL definitions, or create the WSDL documents first, then convert those documents to Java code. Finding the right method might have more to do with personal predilection than hard and fast rules. I prefer to define a service's interface in Java (or some other language) first, because I find that a programming language-based definition produces a clearer, simpler picture of a service's capabilities. WSDL-first advocates have a point too: converting Java interfaces to XML structures is not an exact science and can introduce subtleties leading to surprising results.

Regardless of how you create a WSDL document, it consists of six element types:

  1. definitions: the WSDL document's root element, also includes name space declarations and target names
  2. types: data type definitions
  3. message: message definitions
  4. portType: a set of operations provided by the services described by those operations
  5. binding: wire protocol and message formats offered by the service
  6. service: ports for using the service, each port possibly with several bindings

Here is the entire WSDL document Apache Axis created based on the CruiseService interface. To make it more readable, I divided it according to the six major WSDL elements:

  1. definitions (preceded by document header):

      <?xml version="1.0" encoding="UTF-8"?>
    <wsdl:definitions 
        targetNamespace="urn:cruise" 
        xmlns="http://schemas.xmlsoap.org/wsdl/" 
        xmlns:apachesoap="http://xml.apache.org/xml-soap" 
        xmlns:impl="urn:cruise-impl" 
        xmlns:intf="urn:cruise" 
        xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
        xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    
  2. types: This element first identifies the XML Schema namespace. The only type defined here is a string array for our method's return value. That value may also be null. The declaration of that string array's complex type precedes the type's definition:

      <wsdl:types>
        <schema targetNamespace="urn:cruise" 
            xmlns="http://www.w3.org/2001/XMLSchema">
            <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
          <complexType name="ArrayOf_soapenc_string">
            <complexContent>
                <restriction base="soapenc:Array">
                    <attribute ref="soapenc:arrayType" 
                         wsdl:arrayType="soapenc:string[]"/>
                </restriction>
            </complexContent>
          </complexType>
          <element name="ArrayOf_soapenc_string" nillable="true" 
             type="intf:ArrayOf_soapenc_string"/>
        </schema>
    </wsdl:types>
    
  3. message: There are two messages: a response and a request. The response refers to the type with the name ArrayOf_soapenc_string declared in the previous element. Since our method takes no parameters, the request message is empty:

      <wsdl:message name="cruiseDestinationsResponse">
        <wsdl:part name="return" type="intf:ArrayOf_soapenc_string"/>
    </wsdl:message>
    <wsdl:message name="cruiseDestinationsRequest">
    </wsdl:message>
    
  4. portType: The only port type defined here is named CruiseService and operates on the input and output messages defined earlier:

      <wsdl:portType name="CruiseService">
        <wsdl:operation name="cruiseDestinations">
            <wsdl:input message="intf:cruiseDestinationsRequest" 
                name="cruiseDestinationsRequest"/>
            <wsdl:output message="intf:cruiseDestinationsResponse" 
                name="cruiseDestinationsResponse"/>
        </wsdl:operation>
    </wsdl:portType>
    
  5. binding: This WSDL document declares only one service binding. That binding allows access to the service via SOAP (Simple Object Access Protocol). That service binding's SOAP operation corresponds to our interface's single method, cruiseDestinations(), and that method's input and output parameters:

      <wsdl:binding name="AxisServletSoapBinding" type="intf:CruiseService">
        <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="cruiseDestinations">
            <wsdlsoap:operation soapAction=""/>
            <wsdl:input name="cruiseDestinationsRequest">
                <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
                  namespace="urn:cruise" use="encoded"/>
            </wsdl:input>
            <wsdl:output name="cruiseDestinationsResponse">
                <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
                    namespace="urn:cruise" use="encoded"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    
  6. service: This section defines where the service's port bindings, defined in the previous element, are actually accessed. This example has only one such service access point, identifying a URL for the SOAP-based port:

      <wsdl:service name="CruiseService">
        <wsdl:port binding="intf:AxisServletSoapBinding" name="AxisServlet">
            <wsdlsoap:address location="http://192.168.1.10:8080/axis/servlet/AxisServlet"/>
        </wsdl:port>
    </wsdl:service>
    </wsdl:definitions>
    

While the WSDL Recommendation defines bindings for SOAP, HTTP GET and POST, and MIME (Multipurpose Internet Mail Extensions), a WSDL document allows the specification of any binding mechanism. For instance, you may choose to define a service that provides access via the RMI/IIOP (Remote Method Invocation/Internet Inter-ORB Protocol) protocols, allowing RMI-style service invocation. In addition, you may choose to provide data type and message definitions not tied to XML Schema or even to XML and rely, for example, on Java byte code. Or a service might have numerous access point URLs listed. WSDL's extensible structure offers that flexibility.

But WSDL's power comes at the price of increased document complexity. Since many WSDL elements can take multiple values, a Web service's WSDL definition can become quite extensive. To avoid the need for monster WSDL documents, the WSDL Recommendation defines an import mechanism:

The WSDL import element information item allows the separation of the different elements of a service definition into independent documents, which can be imported as needed. This technique helps in writing clearer service definitions, by separating the definitions according to their level of abstraction, and maximizes reusability.

With WSDL's import mechanism, we can split our service WSDL document into multiple logical documents. Before seeing how that works, note that WSDL's import capability is not an include mechanism; it simply associates a namespace with a WSDL document. An editor's note in the latest WSDL Recommendation draft reveals how the distinction between import and include has confounded many developers:

We have run into many, many people who appear to be confused about how import is supposed to work. The notion that it only establishes a relationship between a namespace and a location is quite hard to grasp, it appears. Specifically, the fact that nothing is said about what one may find about the namespace at that location appears to be very confusing.

WSDL's import works similarly to how one XML Schema document might refer to a namespace external to that schema. You have already seen an example of that external namespace reference in our WSDL document's types element. There, we imported the SOAP encoding namespace so that we could define our return array type with a SOAP encoding mechanism:

 ... <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
...

WSDL's import allows us to split our CruiseService interface into a WSDL document that corresponds to the service's interface definition and another WSDL document corresponding to the service's implementation. Separating interface from implementation lets us reuse the service interface. If cruise companies agree to adhere to the reusable service interface, CruiseService, each company must only publish the implementation portion of their Web service description and declare that implementation's compliance with the CruiseService interface by importing the service interface's namespace. Figure 1 illustrates that process.

Figure 1. Separation of Web service interface and implementation in WSDL

Our service interface WSDL document will include the definitions, types, message, portType, and binding elements. The service element, referring to a specific implementation, will form another WSDL document's content. The latter document must also reference the first document's namespace via WSDL's import statement.

Apache Axis's WSDL-generation tool, Java2WSDL, offers command-line parameters for splitting a WSDL definition into a WSDL service interface and implementation-specific WSDL documents. Given the original Java interface, CruiseService, the following command creates the WSDL service interface:

  java org.apache.axis.wsdl.Java2WSDL -o cruise_interface.wsdl       -n urn:cruise -S CruiseService -w interface CruiseService

The -o parameter specifies the output file's name; -n designates the WSDL namespace; -S provides the Web service interface's name; and -w interface signifies our interest in a service interface WSDL.

To create an implementation-specific WSDL, change interface to implementation for the -w option, specify a different output filename, and provide the service implementation's location:

 java org.apache.axis.wsdl.Java2WSDL -o cruise_implementation.wsdl     -l http://192.168.1.10:8080/axis/servlet/AxisServlet       -n urn:cruise -S CruiseService -w implementation CruiseService

Register WSDL interfaces as UDDI tModels

The easier to find out about the Web service interface WSDL, the more likely companies will create compatible implementations. Web service registries, such as UDDI and ebXML, ease the discovery of well-known services and their implementations. Thus, the next step: publish the existence of that interface WSDL in Web service registries.

Figure 2. The UDDI registry information model. Click on thumbnail to view full-size image.
1 2 3 4 Page
Recommended
Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more