Skip Headers
Oracle® Fusion Middleware Programming Advanced Features of JAX-WS Web Services for Oracle WebLogic Server
11g Release 1 (10.3.4)

Part Number E13734-03
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Master Index
Master Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

16 Operating at the XML Message Level

The following sections describes how to develop Web service provider-based endpoints and dispatch clients to operate at the XML message level:

Overview of Web Service Provider-based Endpoints and Dispatch Clients

Although the use of JAXB-generated classes is simpler, faster, and likely to be less error prone, there are times when you may want to generate your own business logic to manipulate the XML message content directly. Message-level access can be accomplished on the server side using Web service Provider-based endpoints, and on the client side using Dispatch clients.

A Web service Provider-based endpoint, implemented using the javax.xml.ws.Provider<T> interface, offers a dynamic alternative to the Java service endpoint interface (SEI)-based endpoint. Unlike the SEI-based endpoint that abstracts the details of converting between Java objects and their XML representation, the Provider interface enables you to access the content directly at the XML message level—without the JAXB binding. The steps to develop a Web service Provider-based endpoint are described in Developing a Web Service Provider-based Endpoint.. For more information about the javax.xml.ws.Provider<T> interface, see http://download.oracle.com/javaee/5/api/javax/xml/ws/Provider.html.

A Web service Dispatch client, implemented using the javax.xml.ws.Dispatch<T> interface, enables clients to work with messages at the XML level. The steps to develop a Web service Dispatch client are described in Developing a Web Service Dispatch Client. For more information about the javax.xml.ws.Dispatch<T> interface, see http://download.oracle.com/javaee/5/api/javax/xml/ws/Provider.html.

Dispatch clients and Provider endpoints can be used in combination with other WebLogic Web services features as long as a WSDL is available, including:

Usage Modes and Message Formats for Operating at the XML Level

When operating on messages at the XML level using Provider-based endpoints or Dispatch clients, you use one of the usage modes defined in the following table. You define the usage mode using the javax.xml.ws.ServiceMode annotation, as described in Specifying the Usage Mode (@ServiceMode Annotation).

Table 16-1 Usage Modes for Operating at the XML Message Level

Usage Mode Description

Message

Operates directly with the entire message. For example, if a SOAP binding is used, then the entire SOAP envelope is accessed.

Payload

Operates on the payload of a message only. For example, if a SOAP binding is used, then the SOAP body is accessed.


Provider-based endpoints and Dispatch clients can receive and send messages using one of the message formats defined in Table 16-2. This table also defines the valid message format and usage mode combinations based on the configured binding type (SOAP or XML over HTTP).

Table 16-2 Message Formats Supported for Operating at the XML Message Level

Message Format Usage Mode Support for SOAP/HTTP Binding Usage Mode Support for XML/HTTP Binding

javax.xml.transform.Source

Message mode: SOAP envelope

Payload mode: SOAP body

Message mode: XML content as Source

Payload mode: XML content as Source

javax.activation.DataSource

Not valid in either mode because attachments in SOAP/HTTP binding are sent using SOAPMessage format.

Message mode: DataSource object

Not valid in payload mode because DataSource is used for sending attachments.

javax.xml.soap.SOAPMessage

Message mode: SOAPMessage object

Not valid in payload mode because the entire SOAP message is received, not just the payload.

Not valid in either mode because the client can send a non-SOAP message in XML/HTTP binding.


Developing a Web Service Provider-based Endpoint

A Web service Provider-based endpoint, implemented using the javax.xml.ws.Provider<T> interface, enables you to access content directly at the XML message level—without the JAXB binding.

The following procedure describes the typical steps for programming a JWS file that implements a Web service provider.

Table 16-3 Steps to Develop a Web Service Provider-based Endpoint

#
Step Description

1

Import the JWS annotations that will be used in your Web service Provider-based JWS file.

The standard JWS annotations for a Web service Provider-based JWS file include:

import javax.xml.ws.Provider;
import javax.xml.ws.WebServiceProvider;
import javax.xml.ws.ServiceMode;

Import additional annotations, as required. For a complete list of JWS annotations that are supported, see "Web Service Annotation Support" in WebLogic Web Services Reference for Oracle WebLogic Server.

2

Specify one of the message formats supported, defined in Table 16-2, when developing the Provider-based implementation class.

See Specifying the Message Format.

3

Add the standard required @WebServiceProvider JWS annotation at the class level to specify that the Java class exposes a Web service provider.

See Specifying that the JWS File Implements a Web Service Provider (@WebServiceProvider Annotation).

4

Add the standard @ServiceMode JWS annotation at the class level to specify whether the Web service provider is accessing information at the message or message payload level. (Optional)

See Specifying the Usage Mode (@ServiceMode Annotation).

The service mode defaults to Service.Mode.Payload.

5

Define the invoke() method.

The invoke() method is called and provides the message or message payload as input to the method using the specified message format. See Defining the invoke() Method.


Note:

To start from WSDL and flag a port as a Web service provider, see Starting from WSDL.

Example of a JWS File That Implements a Web Service Provider-based Endpoint

The following sample JWS file shows how to implement a simple Web service provider. The sample is described in detail in the sections that follow.

To review the JWS file within the context of a complete sample, see "Creating JAX-WS Web Services for Java EE" in the Web Services Samples distributed with Oracle WebLogic Server.

Note:

RESTful Web Services can be built using XML/HTTP binding based Provider endpoints. For an example of programming a Provider-based endpoint within the context of a RESTful Web service, see Programming Web Services Using XML Over HTTP.

Example 16-1 Example of a JWS File that Implements a Web Service Provider

package examples.webservices.jaxws;
 
import org.w3c.dom.Node;
 
import javax.xml.transform.Source;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.Provider;
import javax.xml.ws.ServiceMode;
import javax.xml.ws.WebServiceProvider;
import javax.xml.ws.Service;
import java.io.ByteArrayInputStream;
 
 
/**
 * A simple Provider-based Web service implementation.
 *
 * @author Copyright (c) 2010, Oracle and/or its affiliates. 
 * All Rights Reserved.
 */
// The @ServiceMode annotation specifies whether the Provider instance 
// receives entire messages or message payloads.
@ServiceMode(value = Service.Mode.PAYLOAD)

// Standard JWS annotation that configures the Provider-based Web service.
@WebServiceProvider(portName = "SimpleClientPort",
    serviceName = "SimpleClientService",
    targetNamespace = "http://jaxws.webservices.examples/",
    wsdlLocation = "SimpleClientService.wsdl")
public class SimpleClientProviderImpl implements Provider<Source> {
 
  //Invokes an operation according to the contents of the request message.
  public Source invoke(Source source) {
    try {
      DOMResult dom = new DOMResult();
      Transformer trans = TransformerFactory.newInstance().newTransformer();
      trans.transform(source, dom);
      Node node = dom.getNode();
      // Get the operation name node.
      Node root = node.getFirstChild();
      // Get the parameter node.
      Node first = root.getFirstChild();
      String input = first.getFirstChild().getNodeValue();
      // Get the operation name.
      String op = root.getLocalName();
      if ("invokeNoTransaction".equals(op)) {
        return sendSource(input);
      } else {
        return sendSource2(input);
      }
    }
    catch (Exception e) {
      throw new RuntimeException("Error in provider endpoint", e);
    }
  }
 
  private Source sendSource(String input) {
    String body =
        "<ns:invokeNoTransactionResponse
             xmlns:ns=\"http://jaxws.webservices.examples/\"><return>"
            + "constructed:" + input
            + "</return></ns:invokeNoTransactionResponse>";
    Source source = new StreamSource(new ByteArrayInputStream(body.getBytes()));
    return source;
  }
 
  private Source sendSource2(String input) {
    String body =
        "<ns:invokeTransactionResponse 
            xmlns:ns=\"http://jaxws.webservices.examples/\"><return>"
            + "constructed:" + input
            + "</return></ns:invokeTransactionResponse>";
    Source source = new StreamSource(new ByteArrayInputStream(body.getBytes()));
    return source;
  }
 
}

Specifying the Message Format

Specify one of the message formats supported, defined in Table 16-2, when developing the Provider-based implementation class.

For example, in the Provider implementation example shown in Example of a JWS File That Implements a Web Service Provider-based Endpoint, the SimpleClientProviderImpl class implements the Provider<Source> interface, indicating that both the input and output types are java.xml.transform.Source objects.

public class SimpleClientProviderImpl implements Provider<Source> {
. . .
}

Specifying that the JWS File Implements a Web Service Provider (@WebServiceProvider Annotation)

Use the standard javax.xml.ws.WebServiceProvider annotation to specify, at the class level, that the JWS file implements a Web service provider, as shown in the following code excerpt:

@WebServiceProvider(portName = "SimpleClientPort",
    serviceName = "SimpleClientService",
    targetNamespace = "http://jaxws.webservices.examples/",
    wsdlLocation = "SimpleClientService.wsdl")

In the example, the service name is SimpleClientService, which will map to the wsdl:service element in the generated WSDL file. The port name is SimpleClientPort, which will map to the wsdl:port element in the generated WSDL. The target namespace used in the generated WSDL is http://jaxws.webservices.examples/ and the WSDL location is local to the Web service provider, at SimpleClientService.wsdl.

For more information about the @WebServiceProvider annotation, see https://jax-ws.dev.java.net/nonav/2.1.5/docs/annotations.html.

Specifying the Usage Mode (@ServiceMode Annotation)

The javax.xml.ws.ServiceMode annotation is used to specify whether the Web service Provider-based endpoint receives entire messages (Service.Mode.MESSAGE) or message payloads (Service.Mode.PAYLOAD) only.

For example:

@ServiceMode(value = Service.Mode.PAYLOAD)

If not specified, the @ServiceMode annotation defaults to Service.Mode.PAYLOAD.

For a list of valid message format and usage mode combinations, see Table 16-2.

For more information about the @ServiceMode annotation, see https://jax-ws.dev.java.net/nonav/2.1.4/docs/annotations.html.

Defining the invoke() Method

The Provider<T> interface defines a single method that you must define in your implementation class:

T invoke(T request)

When a Web service request is received, the invoke() method is called and provides the message or message payload as input to the method using the specified message format.

For example, in the Provider implementation example shown in Example of a JWS File That Implements a Web Service Provider-based Endpoint, the class defines an invoke method to take as input the Source parameter and return a Source response.

public Source invoke(Source source) {
    try {
      DOMResult dom = new DOMResult();
      Transformer trans = TransformerFactory.newInstance().newTransformer();
      trans.transform(source, dom);
      Node node = dom.getNode();
      // Get the operation name node.
      Node root = node.getFirstChild();
      // Get the parameter node.
      Node first = root.getFirstChild();
      String input = first.getFirstChild().getNodeValue();
      // Get the operation name.
      String op = root.getLocalName();
      if ("invokeNoTransaction".equals(op)) {
        return sendSource(input);
      } else {
        return sendSource2(input);
      }
    }
    catch (Exception e) {
      throw new RuntimeException("Error in provider endpoint", e);
    }
  }

Starting from WSDL

If the Provider-based endpoint is being generated from a WSDL file, the <provider> WSDL extension can be used to mark a port as a provider. For example:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<bindings wsdlLocation="SimpleClientService.wsdl" 
  xmlns="http://java.sun.com/xml/ns/jaxws">
<bindings node="wsdl:definitions" > 
    <package name="provider.server"/>    
   <provider>true</provider>
</bindings>

Developing a Web Service Dispatch Client

A Web service Dispatch client, implemented using the javax.xml.ws.Dispatch<T> interface, enables clients to work with messages at the XML level.

The following procedure describes the typical steps for programming a Web service Dispatch client.

Table 16-4 Steps to Develop a Web Service Provider-based Endpoint

#
Step Description

1

Import the JWS annotations that will be used in your Web service Provider-based JWS file.

The standard JWS annotations for a Web service Provider-based JWS file include:

import javax.xml.ws.Service;
import javax.xml.ws.Dispatch;
import javax.xml.ws.ServiceMode;

Import additional annotations, as required. For a complete list of JWS annotations that are supported, see "Web Service Annotation Support" in WebLogic Web Services Reference for Oracle WebLogic Server.

2

Create a Dispatch instance.

See Creating a Dispatch Instance.

3

Invoke a Web service operation.

You can invoke a Web service operation synchronously (one-way or two-way) or asynchronously (polling or asynchronous handler). See Invoking a Web Service Operation.


Example of a Web Service Dispatch Client

The following sample shows how to implement a basic Web service Dispatch client. The sample is described in detail in the sections that follow.

Example 16-2 Example of a Web Service Dispatch Client

package jaxws.dispatch.client;
 
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.URL;
 
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
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.WebServiceException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
import javax.xml.ws.soap.SOAPBinding;
 
public class WebTest extends TestCase {
   private static String in_str = "wiseking";
   private static String request = 
      "<ns1:sayHello xmlns:ns1=\"http://example.org\"><arg0>"+in_str+"</arg0></ns1:sayHello>";
 
   private static final QName portQName = new QName("http://example.org", "SimplePort");
   private Service service = null;

   protected void setUp() throws Exception {
 
      String url_str = System.getProperty("wsdl");
      URL url = new URL(url_str);
      QName serviceName = new QName("http://example.org", "SimpleImplService");
      service = Service.create(serviceName);
      service.addPort(portQName, SOAPBinding.SOAP11HTTP_BINDING, url_str);
      System.out.println("Setup complete.");
 
   }
 
   public void testSayHelloSource() throws Exception {
      setUp();
      Dispatch<Source> sourceDispatch = 
         service.createDispatch(portQName, Source.class, Service.Mode.PAYLOAD);
      System.out.println("\nInvoking xml request: " + request);
      Source result = sourceDispatch.invoke(new StreamSource(new StringReader(request)));
      String xmlResult = sourceToXMLString(result);
      System.out.println("Received xml response: " + xmlResult);
      assertTrue(xmlResult.indexOf("HELLO:"+in_str)>=0);
   }
 
   private String sourceToXMLString(Source result) {
      String xmlResult = null;
      try {
         TransformerFactory factory = TransformerFactory.newInstance();
         Transformer transformer = factory.newTransformer();
         transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
         transformer.setOutputProperty(OutputKeys.METHOD, "xml");
         OutputStream out = new ByteArrayOutputStream();
         StreamResult streamResult = new StreamResult();
         streamResult.setOutputStream(out);
         transformer.transform(result, streamResult);
         xmlResult = streamResult.getOutputStream().toString();
      } catch (TransformerException e) {
         e.printStackTrace();
      }
      return xmlResult;
   }
 
}

Creating a Dispatch Instance

The javax.xml.ws.Service interface acts as a factory for the creation of Dispatch instances. So to create a Dispatch instance, you must first create a Service instance. Then, create the Dispatch instance using the Service.createDispatch() method.

For example:

...
      String url_str = System.getProperty("wsdl");
      QName serviceName = new QName("http://example.org", "SimpleImplService");
      service = Service.create(serviceName);
      service.addPort(portQName, SOAPBinding.SOAP11HTTP_BINDING, url_str);
      Dispatch<Source> sourceDispatch = 
         service.createDispatch(portQName, Source.class, Service.Mode.PAYLOAD);
...

In the example above, the createDispatch() method takes three parameters:

  • Qualified name (QName) of the target service endpoint.

  • Class of the type parameter T. In this example, the javax.xml.transform.Source format is used. For valid values, see Table 16-2.

  • Usage mode. In this example, the message payload is specified. For valid usage modes, see Table 16-1.

Alternatively, you can pass the JAXB context to operate on XML messages using custom annotated JAXB classes. For more information about the valid parameters that can be used to call the Service.createDispatch() method, see the javax.xml.ws.Service Javadoc at: https://jax-ws.dev.java.net/nonav/2.1.1/docs/api/javax/xml/ws/Service.html.

Invoking a Web Service Operation

Once the Dispatch instance is created, use it to invoke a Web service operation. You can invoke a Web service operation synchronously (one-way or two-way) or asynchronously (polling or asynchronous handler). For complete details about the synchronous and asynchronous invoke methods, see the javax.xml.ws.Dispatch Javadoc at: https://jax-ws.dev.java.net/nonav/2.1.1/docs/api/javax/xml/ws/Dispatch.html

For example, in the following code excerpt, the XML message is encapsulated as a javax.xml.transform.stream.StreamSource object and passed to the synchronous invoke() method. The response XML is returned in the result variable as a Source object, and transformed back to XML. The sourcetoXMLString() method used to transform the message back to XML is shown in Example 16-2.

...
private static String request = "<ns1:sayHello xmlns:ns1=\"http://example.org\"><arg0>"+in_str+"</arg0></ns1:sayHello>";
Source result = sourceDispatch.invoke(new StreamSource(new StringReader(request)));
String xmlResult = sourceToXMLString(result);
...