Web services hints and tips: JAX-RPC versus JAX-WS, Part 4

The dynamic invocation interfaces

This fourth part of the series about Java™ API for XML-based RPC (JAX-RPC) 1.1 and Java API for XML Web Services (JAX-WS) 2.0 compares the dynamic invocation models. This tip walks you through the similarities and describes the major differences, using an example for each model.

Share:

Russell Butek (butek@us.ibm.com), IT Specialist, IBM

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.


developerWorks Contributing author
        level

Nicholas Gallardo, Staff Software Engineer, IBM

Nick Gallardo works as a software engineer on the IBM WebSphere platform, focusing on various aspects of the web services, most recently the JAX-WS support. His previous work in IBM includes other assignments within the WebSphere and Tivoli platforms. Nick came to IBM in 2001 after working in development in two different technology startups in Austin, Texas.



21 June 2007

Also available in Chinese

Introduction

Develop skills on this topic

This content is part of a progressive knowledge path for advancing your skills. See Building and deploying JAX-WS web services

Both the JAX-RPC 1.1 and the JAX-WS 2.0 client dynamic model have a similar set of high-level steps to make an invocation:

  1. Define the service.
  2. Create the dynamic invocation object from this service.
  3. Build the message.
  4. Invoke the operation.

Even though both models follow these same steps, this tip describes how different the details between the two models are. You'll use the HelloWorld Web Services Description Language (WSDL) that you used in the previous tip. You can find it here in Listing 1.

Listing 1. HelloWorld service's WSDL
                <?xml version="1.0" encoding="UTF-8"?>
      <wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
      xmlns:tns="urn:helloWorld/sample/ibm/com"
      xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="HelloWorld"
      targetNamespace="urn:helloWorld/sample/ibm/com">
  <wsdl:types>
    <xsd:schema targetNamespace="urn:helloWorld/sample/ibm/com"
        xmlns:tns="urn:helloWorld/sample/ibm/com"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <xsd:element name="hello">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="name" nillable="true" type="xsd:string" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
      <xsd:element name="helloResponse">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="response" nillable="true" type="xsd:string" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
    </xsd:schema>
  </wsdl:types>
  <wsdl:message name="helloRequestMsg">
    <wsdl:part element="tns:hello" name="helloParameters" />
  </wsdl:message>
  <wsdl:message name="helloResponseMsg">
    <wsdl:part element="tns:helloResponse" name="helloResult" />
  </wsdl:message>
  <wsdl:portType name="HelloWorld">
    <wsdl:operation name="hello">
      <wsdl:input message="tns:helloRequestMsg" name="helloRequest" />
      <wsdl:output message="tns:helloResponseMsg" name="helloResponse" />
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="HelloWorldBinding" type="tns:HelloWorld">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="hello">
      <soap:operation soapAction="urn:helloWorld/sample/ibm/com/hello" />
      <wsdl:input name="helloRequest">
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output name="helloResponse">
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="HelloWorldService">
    <wsdl:port name="port" binding="tns:HelloWorldBinding">
      <soap:address location="http://tempuri.org/" />
    </wsdl:port>
  </wsdl:service>
  </wsdl:definitions>

JAX-RPC's dynamic Call interface

JAX-RPC's dynamic invocation interface (DII) is the Call object (javax.xml.rpc.Call). Listing 2 contains a complete client main class that calls Listing 1's HelloWorld service using the Call object. You can also see the high-level steps described in the introduction in Listing 2.

Listing 2. JAX-RPC's DII client
                package com.ibm.samples.dii;

import javax.xml.namespace.QName;
import javax.xml.rpc.Call;
import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;
import javax.xml.rpc.encoding.XMLType;

public class HelloWorldClient {

    public static void main(String[] args) {
        try {
            // Define the service.
            QName serviceName = new QName(
                    "urn:helloWorld/sample/ibm/com",
                    "HelloWorldService");
            ServiceFactory factory = ServiceFactory.newInstance();
            Service service = factory.createService(serviceName);

            // Create the dynamic invocation object from this service.
            Call call = service.createCall();
            call.setTargetEndpointAddress(
                    "http://localhost:9081/HelloWorldService/services/port");

            // Build the message.
            QName operationName = new QName(
                    "urn:helloWorld/sample/ibm/com",
                    "hello");
            call.setOperationName(operationName);
            call.addParameter(
                    "name",             // parameter name
                    XMLType.XSD_STRING, // parameter XML type QName
                    String.class,       // parameter Java type class
                    ParameterMode.IN);  // parameter mode
            call.setReturnType(XMLType.XSD_STRING);
            call.setProperty(
                    Call.OPERATION_STYLE_PROPERTY,
                    "wrapped");

            // Invoke the operation.
            Object[] actualArgs = {"Georgia"};
            String response = (String) call.invoke(actualArgs);
            System.out.println("response = " + response);
        }
        catch (Throwable t) {
            t.printStackTrace();
        }
    }
    }

Let's look at the details of those high-level steps:

  1. Define the service. Using the fully qualified name of the WSDL's service, you construct a javax.xml.rpc.Service object.
  2. Create the dynamic invocation object from this service. In JAX-RPC, the dynamic invocation object is javax.xml.rpc.Call.
  3. Build the message. In this step, you populate the Call object with information about the operation. There's one thing to point out here: We call call.setProperty(Call.OPERATION_STYLE_PROPERTY, "wrapped"); . wrapped is not a value defined by JAX-RPC for this property. JAX-RPC defines only rpc and document. However, rpc really means RPC/encoded, and document really means document/literal, non-wrapped. The document/literal wrapped pattern has become the industry standard since JAX-RPC was written, so its Call object doesn't deal well with it. You can do it, but it's not pretty. Extending this property to include the wrapped value is IBM's way of filling this gap of the specification, but it's a nonstandard extension.
  4. Invoke the operation. The input in this example is a simple string, so you populate the argument array with a string and pass it to the invoke function. The response is also a string, and in this example you simply display it.

JAX-WS's dynamic Dispatch interface

JAX-WS's DII is the Dispatch object (javax.xml.ws.Dispatch). Listing 3 contains a complete client main class that calls Listing 1's HelloWorld service via this Dispatch object. You can see the high-level steps described in the introduction in Listing 3.

Listing 3. JAX-WS's DII client
                import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.soap.SOAPBinding;

public class HelloWorldClient {

    public static void main(String[] args) {
        try {      
            // Define the service.
            QName svcQname = new QName(
                    "urn:helloWorld/sample/ibm/com", 
                    "HelloWorldService");
            QName portQName = new QName(
                    "urn:helloWorld/sample/ibm/com", 
                    "port");
            Service svc = Service.create(svcQname);
            svc.addPort(
                    portQName, 
                    SOAPBinding.SOAP11HTTP_BINDING,
                    "http://localhost:9080/JAXBSampleWebService/HelloWorldService");

            // Create the dynamic invocation object from this service.
            Dispatch<Source> dispatch = svc.createDispatch(
                    portQName, 
                    Source.class, 
                    Service.Mode.PAYLOAD);

            // Build the message.
            String content = 
                    "<ns2:hello xmlns:ns2=\"urn:helloWorld/sample/ibm/com\">" +
                      "<name>Georgie</name>" +
                    "</ns2:hello>";
            ByteArrayInputStream bais = new ByteArrayInputStream(content.getBytes());
            Source input = new StreamSource(bais);

            // Invoke the operation.
            Source output = dispatch.invoke(input);

            // Process the response.
            StreamResult result = new StreamResult(new ByteArrayOutputStream());
            Transformer trans = TransformerFactory.newInstance().newTransformer();
            trans.transform(response, result);
            ByteArrayOutputStream baos = (ByteArrayOutputStream) result.getOutputStream();

            // Write out the response content.
            String responseContent = new String(baos.toByteArray());
            System.out.println(responseContent);
        }
        catch (Throwable t) {
            t.printStackTrace();
        }
    }
}

Let's look at the details of those high-level steps in this JAX-WS dynamic client:

  1. Define the service. Like in JAX-RPC's model, you define the service based on its fully qualified name, but you also define the port within that service.
  2. Create the dynamic invocation object from this service. In JAX-WS, the dynamic invocation object is javax.xml.ws.Dispatch. This class leverages the new Generics feature in Java 5 to support multiple parameter types.
  3. Build the message. Here you build the raw SOAP message body contents.
  4. Invoke the operation. You send the contents of the SOAP body to the service and receive the SOAP response back from the service.

The differences between the models

Looking at the high-level steps, it appears that the dynamic invocation model for JAX-RPC and JAX-WS are similar. But this is somewhat misleading. When you look at the details of each example, you can see that the models are, in fact, very different. Let's take a look at some of those differences a little more closely.

Operation style

It should be fairly clear that the primary difference between the models is that JAX-RPC follows a remote procedure call (RPC) model (hence the RPC in the specification name), while JAX-WS's dynamic client follows a messaging model. With JAX-RPC, the Call object must be configured to explicitly invoke a particular operation from the WSDL. In JAX-WS, the Dispatch object is unaware of what operation is being invoked and is just sending XML data.

Parameter style

With JAX-RPC, the parameter type(s) passed retain the XML Schema-to-Java mappings that are defined by the specification. With JAX-WS, there are two different ways to use the Dispatch object: either as an XML-based Dispatch (as shown in this tip) or as a JAXB-based Dispatch. The XML-based Dispatch accepts parameters that are based on these object types: javax.xml.transform.Source, javax.xml.soap.SOAPMessage, and javax.activation.DataSource. The JAXB-based Dispatch requires the user to configure a javax.xml.bind.JAXBContext that can be used to marshall and unmarshall instances of the parameters, which are JAXB Java beans.

Another major difference in the parameter style is in what the content passed in represents. For JAX-RPC, the parameter(s) always form the parameter data of the request. With JAX-WS, there are two different parameter modes: PAYLOAD and MESSAGE mode. PAYLOAD mode means the parameter represents just the contents of the SOAP body, where MESSAGE mode means the parameter represents the entire message, including the SOAP envelope.

Invocation patterns

As shown above, JAX-RPC and JAX-WS both provide a synchronous two-way invocation via the invoke() method. Both models also provide a method for invoking one-way Web service operations via the invokeOneWay method. A major difference between the two models is that JAX-WS also provides an asynchronous invocation model. There is an asynchronous callback model and an asynchronous polling model. JAX-RPC doesn't provide an option for asynchronous invocations.

Server-side dynamic programming model

Another major difference, which isn't covered in detail here, is that JAX-WS adds what JAX-RPC never had — a dynamic server-side programming model. Like the client-side model, it too can be configured for PAYLOAD or MESSAGE mode.


Summary

Both JAX-RPC and JAX-WS provide a dynamic client model. And both can be viewed as equivalent from a high-level point of view. But when you get down to the details, you can see that JAX-RPC's dynamic model is an RPC model, while JAX-WS's dynamic model is a messaging model. The JAX-WS APIs provide greater flexibility and are the next step in the evolution of Web services programming models. JAX-WS also adds support for asynchronous support and for a dynamic service, which JAX-RPC doesn't define.

Resources

Learn

Get products and technologies

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

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into SOA and web services on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and web services, Information Management
ArticleID=231293
ArticleTitle=Web services hints and tips: JAX-RPC versus JAX-WS, Part 4
publish-date=06212007