Describe and compare JAX-WS development approaches.

[Note]

Empty

Class

A Java class (not an interface) annotated with a javax.jws.WebService annotation can be used to define a Web service.

In order to allow for a separation between Web service interface and implementation, if the WebService annotation on the class under consideration has a endpointInterface element, then the interface referred by this element is for all purposes the SEI associated with the class.

Otherwise, the class implicitly defines a service endpoint interface (SEI) which comprises all of the public methods that satisfy one of the following conditions:

  1. They are annotated with the javax.jws.WebMethod annotation with the exclude element set to false or missing (since false is the default for this annotation element).

  2. They are NOT annotated with the javax.jws.WebMethod annotation but their declaring class has a javax.jws.WebService annotation.

For mapping purposes, this implicit SEI and its methods are considered to be annotated with the same Web service-related annotations that the original class and its methods have.

In pratice, in order to exclude a public method of a class annotated with WebService and not directly specifying a endpointInterface from the implicitly defined SEI, it is necessary to annotate the method with a WebMethod annotation with the exclude element set to true.

For mapping purposes, this class must be a top level class or a static inner class. As defined by JSR 181, a class annotated with javax.jws.WebService MUST HAVE a default public constructor.

Interface

A Java service endpoint interface (SEI) is mapped to a wsdl:portType element. The wsdl:portType element acts as a container for other WSDL elements that together form the WSDL description of the methods in the corresponding Java SEI. An SEI is a Java interface that meets all of the following criteria:

  1. It MUST carry a javax.jws.WebService annotation

  2. Any of its methods MAY carry a javax.jws.WebMethod annotation

  3. javax.jws.WebMethod if used, MUST NOT have the exclude element set to true.

  4. All method parameters and return types are compatible with the JAXB 2.0 Java to XML Schema mapping definition

Method

Each public method in a Java SEI is mapped to a wsdl:operation element in the corresponding wsdl:portType plus one or more wsdl:message elements.

Comparing JAX-WS and JAX-RPC SEI mapping

WSDL for a simple HelloWorld Web service:


<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:tns="urn:helloWorld/sample/ibm/com" ...>

  <wsdl:types>
    <xsd:schema ...>
    
      <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://server.org/" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>
					
					

JAX-RPC HelloWorld SEI:

package com.ibm.samples;

public interface HelloWorld extends java.rmi.Remote {
    ...
}
					

JAX-WS HelloWorld SEI:

package com.ibm.samples.helloworld;

import javax.jws.WebService;

@WebService(name = "HelloWorld", targetNamespace = "urn:samples.ibm.com/HelloWorld")
public interface HelloWorld {
    ...
}
					

There are three differences here:

Although JAX-WS provides support for Web services that have an SEI, this is not mandatory for all services. With JAX-WS, a JavaBean can be deployed on its own as a Web service implementation, as opposed to JAX-RPC where the bean must include an SEI. JAX-WS services deployed without an SEI are considered to have an implicit SEI.

Comparing JAX-WS and JAX-RPC operation mapping

Considering other JAX-WS and JAX-RPC differences

A major difference in operation mapping for JAX-WS over JAX-RPC is the introduction of asynchronous operations. Any WSDL operation with a two-way message flow, or one where the client expects to receive a response, can be mapped to an asynchronous Java representation. There are two different mechanisms, asynchronous with a callback and asynchronous polling, that require two different mappings.

JAX-WS asynchronous callback:


@WebMethod(action = "urn:samples.ibm.com/HelloWorld/hello")
@RequestWrapper(localName = "hello", 
    targetNamespace = "urn:samples.ibm.com/HelloWorld", 
    className = "com.ibm.samples.helloworld.Hello")
@ResponseWrapper(localName = "helloResponse", 
    targetNamespace = "urn:samples.ibm.com/HelloWorld", 
    className = "com.ibm.samples.helloworld.HelloResponse")
public Future<?> helloAsync(
    @WebParam(name = "name", targetNamespace = "")
    String name,
    @WebParam(name = "asyncHandler", targetNamespace = "")
    AsyncHandler<String> asyncHandler
);

					 

JAX-WS asynchronous polling:


@WebMethod(action = "urn:samples.ibm.com/HelloWorld/hello")
@RequestWrapper(localName = "hello", 
    targetNamespace = "urn:samples.ibm.com/HelloWorld", 
    className = "com.ibm.samples.helloworld.Hello")
@ResponseWrapper(localName = "helloResponse", 
    targetNamespace = "urn:samples.ibm.com/HelloWorld", 
    className = "com.ibm.samples.helloworld.HelloResponse")
public Response<String> helloAsync(
    @WebParam(name = "name", targetNamespace = "")
    String name
);

					

There is no asynchronous mapping for WSDL operations in JAX-RPC, so you do not have anything to make a comparison to here. One important note, however, is that the asynchronous mappings only apply to the client side. No such asynchronous mappings exist for service endpoints, only for clients.

Comparing IN/OUT parameters for JAX-WS and JAX-RPC

Both JAX-RPC and JAX-WS support parameters known as IN/OUT parameters. In this scenario, both JAX-RPC and JAX-WS map that parameter to a holder parameter, but the impact this has is different for each mapping.

A WSDL with an IN/OUT parameter:


<xsd:element name="hello">
  <xsd:complexType>
    <xsd:sequence>
      <xsd:element name="name" nillable="true" type="xsd:string" />
      <xsd:element name="inout" 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:element name="inout" nillable="true" type="xsd:string" />
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>

					

JAX-RPC SEI with IN/OUT parameters:

public interface HelloWorld extends java.rmi.Remote {
    public java.lang.String hello(
        java.lang.String name, 
        javax.xml.rpc.holders.StringHolder inout
    ) throws java.rmi.RemoteException;
}
					

JAX-WS SEI with IN/OUT parameters:


@WebService(name = "HelloWorld", targetNamespace = "urn:helloWorld/sample/ibm/com")
public interface HelloWorld {

    @WebMethod(action = "urn:helloWorld/sample/ibm/com/hello")
    @RequestWrapper(localName = "hello", 
        targetNamespace = "urn:helloWorld/sample/ibm/com", 
        className = "helloworld.sample.ibm.com.Hello")
    @ResponseWrapper(localName = "helloResponse", 
        targetNamespace = "urn:helloWorld/sample/ibm/com", 
        className = "helloworld.sample.ibm.com.HelloResponse")
    public void hello(
        @WebParam(name = "name", targetNamespace = "")
        String name,
        @WebParam(name = "inout", targetNamespace = "", mode = Mode.INOUT)
        Holder<String> inout,
        @WebParam(name = "response", targetNamespace = "", mode = Mode.OUT)
        Holder<String> response
    );
}

					 

For JAX-RPC, there are a set of classes defined by the specification as holder classes for known types. These include types like java.lang.String and other primitive types. For user defined types, JAX-RPC requires that custom holder classes be generated that can handle the user-defined types. JAX-WS, on the other hand, makes use of the Generics feature in Java 5 to provide a single class that can work for all types, including user-defined types.

Another interesting thing to note here is the difference in return types. Rather than keeping the return type as JAX-RPC does, JAX-WS makes the method void and makes use of the holder for what was the return value. By rule in JAX-WS, when there is more than one parameter that can be considered an OUT parameter for an operation, the return type must be void, and all OUT parameters are mapped to holder types.

Professional hosting     Belorussian informational portal         Free SCWCD 1.4 Study Guide     Free SCDJWS 1.4 Study Guide     SCDJWS 1.4 Quiz     Free IBM Certified Associate Developer Study Guide     IBM Test 000-287. Enterprise Application Development with IBM WebSphere Studio, V5.0 Study Guide     SCDJWS 5.0 Quiz