JAX-WS enables a client to consume RESTful web services programmatically. The main API is the
javax.xml.ws.Dispatch
interface described in code sample below:
// T is the message type. public interface Dispatch<T> { // synchronous request-response T invoke(T msg) throws WebServiceException; // async request-response Response<T> invokeAsync(T msg) throws WebServiceException; Future<?> invokeAsync(T msg, AsyncHandler<T> h) throws WebServiceException; // one-way void invokeOneWay(T msg) throws WebServiceException; }
Unlike the Provider
on the server side, developers do not actually implement this API. Instead, they
obtain an instance from the Service
object as shown here:
// Endpoint Address String endpointAddress = "http://java.boot.by/rest"; // Qname for Service QName serviceName = new Qname("http://java.boot.by/rest", "PO"); Service service = Service.create(serviceName); service.addPort(portName, HTTPBinding.HTTP_BINDING, endpointAddress); Dispatch<Source> dispatch = service.createDispatch(new QName("", ""), Source.class, Service.Mode.PAYLOAD); Map<String, Object> requestContext = dispatch.getRequestContext(); requestContext.put(MessageContext.HTTP_REQUEST_METHOD, "GET"); Source result = d.invoke(null); if (result != null) { ... }
Once you specify the address of the service, you pass it into the Service.addPort
method along with the
HTTPBinding
constant instead of the SOAP binding you use with SOAP messages. Then use the request
context you get from the Dispatch
to indicate that you are using the HTTP GET method. The runtime will
use the properties in this map to help it create the proper request and send it off.
The Dispatch
returns a Source
, which can be transformed into a number of Source
-related
objects suitable for different purposes.
The typed Dispatch<T>
interface and the invoke
method can accept and return four
major datatypes:
Dispatch<javax.xml.transform.Source>
Source
objects are low level objects that hold XML documents. Each Source
implementation provides methods that access the stored XML documents and manipulate its contents. The
following objects implement the Source
interface:
DOMSource
SAXSource
StreamSource
Dispatch<javax.xml.soap.SOAPMessage>
Dispatch
objects can use javax.xml.soap.SOAPMessage
objects when the
following conditions are true:
the Dispatch
object is using the SOAP binding.
the Dispatch
object is using message mode.
Dispatch<javax.activation.DataSource>
Dispatch
objects can use objects that implement the
javax.activation.DataSource
interface when the following conditions are true:
the Dispatch
object is using the HTTP binding.
the Dispatch
object is using message mode.
DataSource
objects provide a mechanism for working with MIME typed data from a variety of
sources including URLs, files, and byte arrays.
Dispatch<Object>
While Dispatch
objects are intended to be low level API that allows you to work with raw messages, they
also allow you to work with JAXB objects. To work with JAXB objects a Dispatch
object must be passed a
JAXBContext
that knows how to marshal and unmarshal the JAXB objects in use. The
JAXBContext
is passed when the Dispatch
object is created.
You can pass any JAXB object understood by the JAXBContext
object as the parameter to the
invoke(...)
method. You can also cast the returned message into any JAXB object understood by the
JAXBContext
object.
Code fragment below demonstrates how to make a POST request to http://java.boot.by/rest/acceptPO
with the XML as the body of the POST request read from a poXML
String
:
private void acceptPO() { Service service = Service.create(serviceName); service.addPort(portName, HTTPBinding.HTTP_BINDING, endpointAddress + "/acceptPO"); Dispatch<Source> dispatcher = service.createDispatch(qname, Source.class, Service.Mode.PAYLOAD); Map<String, Object> requestContext = dispatcher.getRequestContext(); requestContext.put(MessageContext.HTTP_REQUEST_METHOD, "POST"); Source result = dispatcher.invoke(new StreamSource(new StringReader(poXML))); printSource(result); }
Code fragment below demonstrates how to make a similar POST request, but it sends and returns JAXB-generated objects rather than handling strings directly:
private void acceptPOJAXB() throws JAXBException { JAXBContext jc = ... Service service = Service.create(serviceName); service.addPort(portName, HTTPBinding.HTTP_BINDING, endpointAddress + "/acceptPO"); Dispatch<Object> dispatcher = service.createDispatch(qname, jc, Service.Mode.PAYLOAD); Map<String, Object> requestContext = dispatcher.getRequestContext(); requestContext.put(MessageContext.HTTP_REQUEST_METHOD, "POST"); JAXBElement<PurchaseOrder> order = new ObjectFactory().createPurchaseOrderDocument(createPO()); JAXBElement<PurchaseOrderStatus> response = (JAXBElement<PurchaseOrderStatus>)dispatcher.invoke(order); PurchaseOrderStatus result= response.getValue(); System.out.println("Order id is : " + result.getOrderid()); System.out.println("Timestamp is : " + result.getTimestamp()); }
Code fragment below demonstrates how to make a similar PUT request using the Dispatch
interface:
private void updatePO() { Service service = Service.create(serviceName); service.addPort(portName, HTTPBinding.HTTP_BINDING, endpointAddress + "/updatePO"); Dispatch<Source> dispatcher = service.createDispatch(qname, Source.class, Service.Mode.PAYLOAD); Map<String, Object> requestContext = dispatcher.getRequestContext(); requestContext.put(MessageContext.HTTP_REQUEST_METHOD, "PUT"); Source result = dispatcher.invoke(new StreamSource(new StringReader(poXML))); printSource(result); }
![]() |
![]() ![]() |