+

Search Tips   |   Advanced Search

Create a JAX-RPC web service application that uses Web Services Addressing

Web Services Addressing (WS-Addressing) aids interoperability between web services by defining a standard way to address web services and provide addressing information in messages. This task describes the steps required to create a JAX-RPC web service that is accessed by using a WS-Addressing endpoint reference. The task also describes the extra steps required to use stateful resources as part of the web service.

The steps described in this task apply to servers and clients that run on WebSphere Application Server.

Complete this task if you are creating a web service that uses the WS-Addressing specification.

  1. Provide a web service interface, by creating or generating a WSDL document for the web service, that returns an endpoint reference to the target service. The interface must return an endpoint reference, which it can do by using a factory operation or a separate factory service. The target service can front a resource instance, for example a shopping cart.

  2. Implement the web service created in the previous step. For the WS-Addressing portion of the implementation...

    1. Create an endpoint reference that references the web service, by following the instructions in Create endpoint references using the IBM proprietary Web Services Addressing API.

    2. Optional: If the interface involves a web service that fronts a resource instance, create or look up the resource instance.

    3. Optional: For a resource instance, obtain the identifier of the resource and associate it with the endpoint reference as a reference parameter, using the EndpointReference.setReferenceParameter(QName resource_id_name, String value) method. The resource identifier is application-dependent and might be generated during the creation of the resource instance. : Do not put sensitive information in the resource identifier, because the identifier is propagated in the SOAP message. The endpoint reference now targets the resource.

    4. Return the endpoint reference.

  3. If the web service uses resource instances, extend the implementation to match incoming messages to the appropriate resource instances. Because you associated the resource identifier with the endpoint reference created earlier, any incoming messages targeted at that endpoint reference contain the resource identifier information as a reference parameter in the SOAP header of the message. Because the resource identifier is passed in the SOAP header, we do not have to expose it on the web service interface. When WebSphere Application Server receives the message, it puts this information into the message context on the thread. Extend the implementation to undertake the following actions:

    1. Obtain the resource instance identifier from the message context, using the EndpointReferenceManager.getReferenceParameterFromMessageContext(QName resource_id_name) method.

    2. Forward the message to the appropriate resource instance.

  4. To configure a client to communicate with the service, use the endpoint reference that is produced by the service in the first step to send messages to the endpoint.

    1. Obtain a Stub object (by looking up the service in the JNDI), or create an empty Call object.

    2. Associate the endpoint reference with the proxy object. Use the setProperty(String property_name, Object value) method of the Stub or Call object. Use the WS-Addressing constant WSADDRESSING_DESTINATION_EPR as the property name, and the endpoint reference as the value.

      This procedure automatically configures the Stub or Call object, to represent the web service (or resource instance if your interface uses a web service that fronts a resource instance) of the endpoint reference. For Call objects, this process includes the configuration of the interface and endpoint metadata (portType and port elements) associated with the endpoint reference.

      If the metadata of the endpoint reference conflicts with the information already associated with the outbound message, for example if the Stub object is configured to represent a different interface, a javax.xml.rpc.JAXRPCException exception is thrown on attempts to invoke the endpoint.

    Invocations on the Stub or Call object are now targeted at the web service or resource instance defined by the endpoint reference. When an invocation occurs, the product adds appropriate message addressing properties, such as a reference parameter contained within the endpoint reference that identifies a target resource, to the message header.


Results

The web service and client are configured to use endpoint references through the WS-Addressing support.


Providing a web service interface that returns an endpoint reference to the target service

The following examples correspond to steps 1 to 4 in the procedure. The examples show how an IT organization might use web services to manage a network of printers. The organization might represent each printer as a resource that is addressed through an endpoint reference. The following examples show how to code such a service using the IBM proprietary Web Services Addressing (WS-Addressing) APIs (APIs) provided by WebSphere Application Server, and JAX-WS.

The IT organization implements a PrinterFactory service that offers a CreatePrinter portType element. This portType element accepts a CreatePrinterRequest message to create a resource that represents a logical printer, and responds with an endpoint reference that is a reference to the resource.

The WSDL definition for such a PrinterFactory service might include the following code:

<wsdl:definitions targetNamespace="http://example.org/printer" ...
                  xmlns:pr=" http://example.org/printer">
  <wsdl:types>
    ...
    <xsd:schema...>
      <xsd:element name="CreatePrinterRequest"/>
      <xsd:element name="CreatePrinterResponse" 
                   type="wsa:EndpointReferenceType"/>
    </xsd:schema>
  </wsdl:types>
  <wsdl:message name="CreatePrinterRequest">
    <wsdl:part name="CreatePrinterRequest" 
               element="pr:CreatePrinterRequest" />
  </wsdl:message>
  <wsdl:message name="CreatePrinterResponse">
    <wsdl:part name="CreatePrinterResponse" 
               element="pr:CreatePrinterResponse" />
  </wsdl:message>
  <wsdl:portType name="CreatePrinter">
    <wsdl:operation name="createPrinter">
      <wsdl:input name="CreatePrinterRequest" 
                  message="pr:CreatePrinterRequest" />
      <wsdl:output name="CreatePrinterResponse"
                  message="pr:CreatePrinterResponse" />
    </wsdl:operation>
  </wsdl:portType>
</wsdl:definitions>

The CreatePrinter operation in the previous example returns a wsa:EndpointReference object that represents the newly created Printer resource. The client can use this endpoint reference to send messages to the service instance that represents the printer.

The createPrinter method shown in the following example creates an endpoint reference to the Printer service. The operation then obtains the identifier for the individual printer resource instance, and associates it with the endpoint reference. Finally, the createPrinter method converts the EndpointReference object, which now represents the new printer, into a W3CEndpointReference object, and returns the converted endpoint reference.

import com.ibm.websphere.wsaddressing.EndpointReferenceManager;
import com.ibm.websphere.wsaddressing.EndpointReference;
import com.ibm.websphere.wsaddressing.jaxws.EndpointReferenceConverter;
import com.ibm.websphere.wsaddressing.jaxws.W3CEndpointReference;

import javax.xml.namespace.QName;

public class MyClass {

    // Create the printer
    ...

    // Define the printer resource ID as a static constant as it is required in later steps     
    public static final QName PRINTER_ID_PARAM_QNAME = new QName("example.printersample", "IBM_WSRF_PRINTERID", "ws-rf-pr" ); 
    public static final QName PRINTER_SERVICE_QNAME = new QName("example.printer.com", "printer", "..."); 
    public static final String PRINTER_ENDPOINT_NAME = new String("PrinterService");
    
    public W3CEndpointReference createPrinter(java.lang.Object createPrinterRequest)
    throws Exception {
     // Create an EndpointReference that targets the appropriate WebService URI and port name.
     EndpointReference epr =  EndpointReferenceManager.createEndpointReference(PRINTER_SERVICE_QNAME, 
                                                                               PRINTER_ENDPOINT_NAME);

     // Create or lookup the stateful resource and derive a resource
     // identifier string.
     String resource_identifier = "...";

     // Associate this resource identifier with the EndpointReference as 
     // a reference parameter.
     // The choice of name is arbitrary, but should be unique     
     // to the service.
     epr.setReferenceParameter(PRINTER_ID_PARAM_QNAME,resource_identifier);
     // The endpoint reference now targets the resource rather than the service.
     ...

     return EndpointReferenceConverter.createW3CEndpointReference(epr);
    }
}

Because of the web service implementation described previously, the printer resource instance now has a unique identifier embedded in its endpoint reference. This identifier becomes a reference parameter in the SOAP header of subsequent messages that are targeted at the web service, and can be used by the web service to match incoming messages to the appropriate printer.

When a web service receives a message containing WS-Addressing message-addressing properties, the WAS processes these properties before the message is dispatched to the application endpoint, and sets them into the message context on the thread. The Printer web service application accesses the reference parameters associated with the target endpoint from the WebServiceContext object, as illustrated in the following example:

import com.ibm.websphere.wsaddressing.EndpointReferenceManager; 
...
 // Initialize the reference parameter name  QName name = new QName(..);
 // Extract the String value.
 String resource_identifier = 
        EndpointReferenceManager.getReferenceParameterFromMessageContext(PRINTER_ID_PARAM_QNAME);

The web service implementation can forward messages based on the printer identity acquired from the getReferenceParameterFromMessageContext method to the appropriate printer instances.

The client creates a JAX-WS proxy for the printer, and converts the proxy into a BindingProvider object. The client then associates the EndpointReference object obtained previously with the request context of the BindingProvider object, as illustrated in the following example.

import javax.xml.ws.BindingProvider;
...

 javax.xml.ws.Service service= ...;
 Printer myPrinterProxy = service.getPort(portName, Printer.class);
 
 javax.xml.ws.BindingProvider bp = (javax.xml.ws.BindingProvider)myPrinterProxy;
  
 // Retrieve the request context for the BindingProvider object  Map myMap = myBindingProvider.getRequestContext();  

 // Associate the endpoint reference that represents the new printer to the request context 
 // so that the BindingProvider object now represents a specific printer instance.
 myMap.put(WSADDRESSING_DESTINATION_EPR, destinationEpr);

...
The BindingProvider object now represents the new printer resource instance, and can be used by the client to send messages to the printer through the Printer web service. When the client invokes the BindingProvider object, WebSphere Application Server adds appropriate message-addressing properties to the message header, which in this case is a reference parameter contained within the endpoint reference identifying target printer resource.

Alternatively, the client can use a JAX-RPC Stub or Call object, which the client configures to represent the new printer. The use of the Call object is illustrated in the following example.

import javax.xml.rpc.Call;
...
 :
 // Associate the endpoint reference that represents the new printer with the call.
 call.setProperty(
        "com.ibm.websphere.wsaddressing.WSAConstants.
                             WSADDRESSING_DESTINATION_EPR ", epr);

From the perspective of the client, the endpoint reference is opaque. The client cannot interpret the contents of any endpoint reference parameters and should not try to use them in any way. Clients cannot directly create instances of endpoint references because the reference parameters are private to the service provider; clients must obtain endpoint references from the service provider, for example through a provider factory service, and use them to direct web service operations to the endpoint that is represented by the endpoint reference, as shown.


What to do next


Subtopics


Related concepts

  • Web Services Addressing APIs


    Related tasks

  • Enable Web Services Addressing support for JAX-RPC applications