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
Usage Modes and Message Formats for Operating at the XML Level
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:
WS-Security
WS-ReliableMessaging
WS-MakeConnection
WS-AtomicTransaction
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 |
---|---|---|
|
Message mode: SOAP envelope Payload mode: SOAP body |
Message mode: XML content as Payload mode: XML content as |
|
Not valid in either mode because attachments in SOAP/HTTP binding are sent using |
Message mode: Not valid in payload mode because |
|
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. |
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" |
2 |
Specify one of the message formats supported, defined in Table 16-2 |
|
3 |
Add the standard required |
See Specifying that the JWS File Implements a Web Service Provider (@WebServiceProvider Annotation). |
4 |
Add the standard |
See Specifying the Usage Mode (@ServiceMode Annotation). The service mode defaults to |
5 |
Define the |
The |
Note:
To start from WSDL and flag a port as a Web service provider, see Starting from WSDLThe 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 HTTPExample 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; } }
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> { . . . }
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
.
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
.
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); } }
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>
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" |
2 |
Create a |
|
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 |
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; } }
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
.
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); ...