A JAX-WS client may be started from the
command line like any other Axis2-based client, including
through the use of the
Java API for XML-Based Web Services
(JAX-WS) provides support for invoking Web services using an
asynchronous client invocation. JAX-WS provides support for
both a callback and polling model when calling Web services
asynchronously. Both the callback model and the polling model
are available on the Dispatch client and the Dynamic Proxy
client.
An asynchronous invocation of a Web service sends a request
to the service endpoint and then immediately returns control
to the client program without waiting for the response to
return from the service. JAX-WS asynchronous Web service
clients consume Web services using either the callback
approach or the polling approach. Using a polling model, a
client can issue a request and receive a response object that
is polled to determine if the server has responded. When the
server responds, the actual response is retrieved. Using the
callback model, the client provides a callback handler to
accept and process the inbound response object. The
handleResponse() method of the handler is called
when the result is available. Both the polling and callback
models enable the client to focus on continuing to process
work without waiting for a response to return, while
providing for a more dynamic and efficient model to invoke
Web services.
Using the callback asynchronous invocation model
To
implement an asynchronous invocation that uses the callback
model, the client provides an
AsynchHandler
callback handler to accept and process the inbound response
object. The client callback handler implements the
javax.xml.ws.AsynchHandler interface, which
contains the application code that is executed when an
asynchronous response is received from the server. The
javax.xml.ws.AsynchHandler interface contains
the
handleResponse(java.xml.ws.Response) method
that is called after the run time has received and processed
the asynchronous response from the server. The response is
delivered to the callback handler in the form of a
javax.xml.ws.Response object. The response
object returns the response content when the
get() method is called. Additionally, if an
error was received, then an exception is returned to the
client during that call. The response method is then invoked
according to the threading model used by the executor method,
java.util.concurrent.Executor on the client's
java.xml.ws.Service instance that was used to
create the Dynamic Proxy or Dispatch client instance. The
executor is used to invoke any asynchronous callbacks
registered by the application. Use the
setExecutor and
getExecutor methods
to modify and retrieve the executor configured for your
service.
Using the polling asynchronous invocation model
Using
the polling model, a client can issue a request and receive a
response object that can subsequently be polled to determine
if the server has responded. When the server responds, the
actual response can then be retrieved. The response object
returns the response content when the
get()
method is called. The client receives an object of type
javax.xml.ws.Response from the
invokeAsync method. That
Response
object is used to monitor the status of the request to the
server, determine when the operation has completed, and to
retrieve the response results.
Using an asynchronous message exchange
By default,
asynchronous client invocations do not have asynchronous
behavior of the message exchange pattern on the wire. The
programming model is asynchronous; however, the exchange of
request or response messages with the server is not
asynchronous. To use an asynchronous message exchange, the
org.apache.axis2.jaxws.use.async.mep property must be set on
the client request context with a boolean value of true. When
this property is enabled, the messages exchanged between the
client and server are different from messages exchanged
synchronously. With an asynchronous exchange, the request and
response messages have WS-Addressing headers added that
provide additional routing information for the messages.
Another major difference between asynchronous and synchronous
message exchange is that the response is delivered to an
asynchronous listener that then delivers that response back
to the client. For asynchronous exchanges, there is no
timeout that is sent to notify the client to stop listening
for a response. To force the client to stop waiting for a
response, issue a
Response.cancel() method on
the object returned from a polling invocation or a
Future.cancel() method on the object returned
from a callback invocation. The cancel response does not
affect the server when processing a request.
The steps necessary to invoke a Web service asynchronously
are:
- Determine if you want to implement the callback method
or the polling method for the client to asynchronously
invoke the Web service.
- (Optional) Configure the client request context. Add
the
org.apache.axis2.jaxws.use.async.mep
property to the request context to enable asynchronous
messaging for the Web services client. Using this
property requires that the service endpoint supports
WS-Addressing which is supported by default for the
application server. The following example demonstrates
how to set this property:
Map<String, Object> rc = ((BindingProvider) port).getRequestContext();
rc.put("org.apache.axis2.jaxws.use.async.mep", Boolean.TRUE);
- To implement the asynchronous callback method, perform
the following steps.
- Find the asynchronous callback method on the SEI or
javax.xml.ws.Dispatch interface. For an
SEI, the method name ends in Async and has
one more parameter than the synchronous method of type
javax.xml.ws.AsyncHandler. The
invokeAsync(Object, AsyncHandler) method
is the one that is used on the Dispatch interface.
- (Optional) Add the service.setExecutor
methods to the client application. Adding the executor
methods gives the client control of the scheduling
methods for processing the response. You can also
choose to use the java.current.Executors
class factory to obtain packaged executors or implement
your own executor class. See the JAX-WS specification
for more information on using executor class methods
with your client.
- Implement the
javax.xml.ws.AsynchHandler interface. The
javax.xml.ws.AsynchHandler interface only
has the
handleResponse(javax.xml.ws.Response)
method. The method must contain the logic for
processing the response or possibly an exception. The
method is called after the client run time has received
and processed the asynchronous response from the
server.
- Invoke the asynchronous callback method with the
parameter data and the callback handler.
- The handleResponse(Response) method is
invoked on the callback object when the response is
available. The Response.get() method is
called within this method to deliver the response.
- To implement the polling method,
- Find the asynchronous polling method on the SEI or
javax.xml.ws.Dispatch interface. For an
SEI, the method name ends in Async and has
a return type of javax.xml.ws.Response.
The invokeAsync(Object) method is used on
the Dispatch interface.
- Invoke the asynchronous polling method with the
parameter data.
- The client receives the object type,
javax.xml.ws.Response, that is used to
monitor the status of the request to the server. The
isDone() method indicates whether the
invocation has completed. When the
isDone() method returns a value of true,
call the get() method to retrieve the
response object.
- Use the cancel() method for the callback
or polling method if the client needs to stop waiting for a
response from the service. If the cancel()
method is invoked by the client, the endpoint continues to
process the request. However, the wait and response
processing for the client is stopped.
When developing Dynamic Proxy clients, after you generate the
portable client artifacts from a WSDL file using the
wsimport command, the generated service endpoint
interface (SEI) does not have asynchronous methods included
in the interface. Use JAX-WS bindings to add the asynchronous
callback or polling methods on the interface for the Dynamic
Proxy client. To enable asynchronous mappings, you can add
the
jaxws:enableAsyncMapping binding declaration
to the WSDL file. For more information on adding binding
customizations to generate an asynchronous interface, see
chapter 8 of the JAX-WS specification.
Note: When you run the
wsimport tool and enable
asynchronous invocation through the use of the JAX-WS
enableAsyncMapping binding declaration, ensure
that the corresponding response message your WSDL file does
not contain parts. When a response message does not contain
parts, the request acts as a two-way request, but the actual
response that is sent back is empty. The
wsimport tool
does not correctly handle a void response. To avoid this
scenario, you can remove the output message from the
operation which makes your operation a one-way operation or
you can add a <wsdl:part> to your message. For more
information on the usage, syntax and parameters for the
wsimport tool, see the
wsimport command for
JAX-WS applications documentation.
The following example illustrates a Web service interface
with methods for asynchronous requests from the client.
@WebService
public interface CreditRatingService {
// Synchronous operation.
Score getCreditScore(Customer customer);
// Asynchronous operation with polling.
Response<Score> getCreditScoreAsync(Customer customer);
// Asynchronous operation with callback.
Future<?> getQuoteAsync(Customer customer,
AsyncHandler<Score> handler);
}
Using the callback method The callback method requires a
callback handler that is shown in the following example. When using
the callback procedure, after a request is made, the callback
handler is responsible for handling the response. The response
value is a response or possibly an exception. The
Future<?> method represents the result of an
asynchronous computation and is checked to see if the computation
is complete. When you want the application to find out if the
request is completed, invoke the
Future.isDone()
method. Note that the
Future.get() method does not
provide a meaningful response and is not similar to the
Response.get() method.
CreditRatingService svc = ...;
Future<?> invocation = svc.getCreditScoreAsync(customerTom,
new AsyncHandler<Score>() {
public void handleResponse (
Response<Score> response)
{
score = response.get();
// process the request...
}
}
);
Using the polling method The following example illustrates an
asynchronous polling client:
CreditRatingService svc = ...;
Response<Score> response = svc.getCreditScoreAsync(customerTom);
while (!response.isDone()) {
// Do something while we wait.
}
score = response.get();
As in the Java API for XML-based RPC
(JAX-RPC) programming model, the JAX-WS programming model
provides an application handler facility that enables you to
manipulate a message on either an inbound or an outbound
flow. You can add handlers into the JAX-WS runtime
environment to perform additional processing of request and
response messages. You can use handlers for a variety of
purposes such as capturing and logging information and adding
security or other information to a message. Because of the
support for additional protocols beyond SOAP, JAX-WS provides
two different classifications for handlers. One type of
handler is a logical handler that is protocol independent and
can obtain the message in the flow as an extensible markup
language (XML) message. The logical handlers operate on
message context properties and message payload. These
handlers must implement the
javax.xml.ws.handler.LogicalHandler interface. A
logical handler receives a
LogicalMessageContext
object from which the handler can get the message
information. Logical handlers can exist on both SOAP and
XML/HTTP-based configurations.
The second type of handler is a protocol handler. The
protocol handlers operate on message context properties and
protocol-specific messages. Protocol handlers are limited to
SOAP-based configurations and must implement the
javax.xml.ws.handler.soap.SOAPHandler interface.
Protocol handlers receive the message as a
javax.xml.soap.SOAPMessage to read the message
data.
The JAX-WS runtime makes no distinction between server-side
and client-side handler classes. The runtime does not
distinguish between inbound or outbound flow when a
handleMessage(MessageContext) method or
handleFault(MessageContext) method for a
specific handler is invoked. You must configure the handlers
for the server or client, and implement sufficient logic
within these methods to detect the inbound or outbound
direction of the current message.
To use handlers with Web services client applications, you
must add the
@HandlerChain annotation to the
service endpoint interface or the generated service class and
provide the handler chain configuration file. The
@HandlerChain annotation contains a file
attribute that points to a handler chain configuration file
that you create. For Web services client applications, you
can also configure the handler chain programmatically using
the Binding API. To modify the
handlerchain
class programmatically, use either the default implementation
or a custom implementation of the
HandlerResolver method.
To use handlers with your server application, you must set
the
@HandlerChain annotation on either the
service endpoint interface or the endpoint implementation
class, and provide the associated handler chain configuration
file. Handlers for the server are only configured by setting
the
@HandlerChain annotation on the service
endpoint implementation or the implementation class. The
handler classes must be included in the deployed
artifact.
For both server and client implementations of handlers using
the
@HandlerChain annotation, you must specify
the location of the handler configuration as either a
relative path from the annotated file or as an absolute URL.
For example:
@HandlerChain(file="../../common/handlers/myhandlers.xml")
or
@HandlerChain(file="http://foo.com/myhandlers.xml")
For more information on the schema of the handler
configuration file, see the JSR 181 specification.
For more information regarding JAX-WS handlers, see chapter 9
of the JAX-WS specification.
To create a JAX-WS handler:
- Determine if you want to implement JAX-WS handlers on
the service or the client.
- Use the default implementation of a handler
resolver. The runtime now uses the
@HandlerChain annotation and the default
implementation of HandlerResolver class to
build the handler chain. You can obtain the existing
handler chain from the Binding, add or
remove handlers, and then return the modified handler
chain to the Binding object.
- To use a custom implementation of a handler
resolver, set the custom HandlerResolver
class on the Service instance. The runtime
uses your custom implementation of the
HandlerResolver class to build the handler
chain, and the default runtime implementation is not
used. In this scenario, the @HandlerChain
annotation is not read when retrieving the handler
chain from the binding after the custom
HandlerResolver instance is registered on
the Service instance. You can obtain the
existing handler chain from the Binding,
add or remove handlers, and then return the modified
handler chain to the Binding object.
- Configure the client handlers by setting the
@HandlerChain annotation on the service
instance or service endpoint interface, or you can modify
the handler chain programmatically to control how the
handler chain is built in the runtime. If you choose to
modify the handler chain programmatically, then you must
determine if you will use the default handler resolver or
use a custom implementation of a handler resolver that is
registered on the service instance. A service instance uses
a handler resolver when creating binding providers. When
the binding providers are created, the handler resolver
that is registered with a service is used to create a
handler chain and the handler chain is subsequently used to
configure the binding provider.
- Configure the server handlers by setting the
@HandlerChain annotation on the service
endpoint interface or implementation class. When the
@HandlerChain annotation is configured on both
the service endpoint interface and the implementation
class, the implementation class takes priority.
- Create the handler chain configuration XML file. You
must create a handler chain configuration XML file for the
@HandlerChain to reference.
- Add the handler chain configuration XML file in the
class path for the service endpoint interface when
configuring the server or client handlers using the
@HandlerChain annotation. You must also
include the handler classes contained in the configuration
XML file in your class path.
- Write your handler implementation.
The following example illustrates the steps necessary to
configure JAX-WS handlers on a service endpoint interface
using the
@HandlerChain annotation.
The
@HandlerChain annotation has a file
attribute that points to a handler chain configuration XML
file that you create. The following file illustrates a
typical handler configuration file. The
protocol-bindings,
port-name-pattern, and
service-name-pattern elements are all filters
that are used to restrict which services can apply the
handlers.
<?xml version="1.0" encoding="UTF-8"?>
<jws:handler-chains xmlns:jws="http://java.sun.com/xml/ns/javaee">
<!-- Note: The '*" denotes a wildcard. -->
<jws:handler-chain name="MyHandlerChain">
<jws:protocol-bindings>##SOAP11_HTTP ##ANOTHER_BINDING</jws:protocol-bindings>
<jws:port-name-pattern
xmlns:ns1="http://handlersample.samples.apache.org/">ns1:MySampl*</jws:port-name-pattern>
<jws:service-name-pattern
xmlns:ns1="http://handlersample.samples.apache.org/">ns1:*</jws:service-name-pattern>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleLogicalHandler</jws:handler-class>
</jws:handler>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleProtocolHandler2</jws:handler-class>
</jws:handler>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleLogicalHandler</jws:handler-class>
</jws:handler>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleProtocolHandler2</jws:handler-class>
</jws:handler>
</jws:handler-chain>
</jws:handler-chains>
Make sure that you add the handler.xml file and the handler
classes contained in the handler.xml file in your class path.
The following example demonstrates a handler implementation:
package org.apache.samples.handlersample;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class SampleProtocolHandler implements
javax.xml.ws.handler.soap.SOAPHandler<SOAPMessageContext> {
public void close(MessageContext messagecontext) {
}
public Set<QName> getHeaders() {
return null;
}
public boolean handleFault(SOAPMessageContext messagecontext) {
return true;
}
public boolean handleMessage(SOAPMessageContext messagecontext) {
Boolean outbound = (Boolean) messagecontext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outbound) {
// Include your steps for the outbound flow.
}
return true;
}
}
You can use HTTP session management to
maintain user state information on the server, while passing
minimal information back to the user to track the session.
You can implement HTTP session management on the application
server using either session cookies or URL rewriting.
The interaction between the browser, application server, and
application is transparent to the user and the application
program. The application and the user are typically not aware
of the session identifier provided by the server.
Session cookies
The HTTP maintain session feature
uses a single cookie,
JSESSIONID, and this
cookie contains the session identifier. This cookie is used
to associate the request with information stored on the
server for that session. On subsequent requests from the
JAX-WS application, the session ID is transmitted as part of
the request header, which enables the application to
associate each request for a given session ID with prior
requests from that user. The JAX-WS client applications
retrieve the session ID from the HTTP response headers and
then use those IDs in subsequent requests by setting the
session ID in the HTTP request headers.
URL rewriting
URL rewriting works like a redirected
URL as it stores the session identifier in the URL. The
session identifier is encoded as a parameter on any link or
form that is submitted from a Web page. This encoded URL is
used for subsequent requests to the same server.
To enable HTTP session management:
- Configure the server to enable session tracking.
- Enable session management on the client by setting the
JAX-WS property,
javax.xml.ws.session.maintain, to true on the
BindingProvider.
Map<String, Object> rc = ((BindingProvider) port).getRequestContext();
...
...
rc.put(BindingProvider.SESSION_MAINTAIN_PROPERTY, Boolean.TRUE);
...
...
JAX-WS
supports the use of SOAP Message Transmission Optimized
Mechanism (MTOM) for sending binary attachment data. By
enabling MTOM, you can send and receive binary data optimally
without incurring the cost of data encoding to ensure the
data is included in the XML document.
JAX-WS applications can send binary data as base64 or
hexBinary encoded data contained within the XML document.
However, to take advantage of the optimizations provided by
MTOM, enable MTOM to send binary base64 data as attachments
contained outside the XML document. MTOM optimization is only
available for the xs:base64Binary data type. The MTOM option
is not enabled by default. JAX-WS applications require
separate configuration of both the client and the server
artifacts to enable MTOM support. For the server, MTOM can be
enabled on a JAX-WS JavaBeans endpoint only and not on a
provider-based endpoint.
To enable MTOM on an endpoint, use the @BindingType
(javax.xml.ws.BindingType) annotation on a server endpoint
implementation class to specify that the endpoint supports
one of the MTOM binding types so that the response messages
are MTOM-enabled. The javax.xml.ws.SOAPBinding class defines
two different constants, SOAP11HTTP_MTOM_BINDING and
SOAP12HTTP_MTOM_BINDING that you can use for the value of the
@BindingType annotation. For example:
// for SOAP version 1.1
@BindingType(value = SOAPBinding.SOAP11HTTP_MTOM_BINDING)
// for SOAP version 1.2
@BindingType(value = SOAPBinding.SOAP12HTTP_MTOM_BINDING)
Enable MTOM on the client by using the
javax.xml.ws.soap.SOAPBinding client-side API. Enabling MTOM
on the client optimizes the binary messages that are sent to
the server.
- Enable MTOM on a Dispatch client.
- The following example uses
SOAP version 1.1:
- First method: Using
SOAPBinding.setMTOMEnabled()
-
SOAPBinding binding = (SOAPBinding)dispatch.getBinding();
binding.setMTOMEnabled(true);
- Second method: Using Service.addPort()
-
Service svc = Service.create(serviceName);
svc.addPort(portName,SOAPBinding.SOAP11HTTP_MTOM_BINDING,endpointUrl);
- Enable MTOM on a Dynamic Proxy client.
-
// Create a BindingProvider bp from a proxy port.
Service svc = Service.create(serviceName);
MtomSample proxy = svc.getPort(portName, MtomSample.class);
BindingProvider bp = (BindingProvider) proxy;
//Enable MTOM
SOAPBinding binding = (SOAPBinding) bp.getBinding();
binding.setMTOMEnabled(true);