With JAX-WS, Web services are called both synchronously and
asynchronously. JAX-WS adds support for both a polling and
callback mechanism when calling Web services asynchronously.
Using a polling model, a client can issue a request, get a
response object back, which 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. 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.
For example, a Web service interface might have methods for
both synchronous and asynchronous requests. Asynchronous
requests are identified in bold below:
@WebService
public interface CreditRatingService {
// sync operation
Score getCreditScore(Customer customer);
// async operation with polling
Response<Score> getCreditScoreAsync(Customer customer);
// async operation with callback
Future<?> getCreditScoreAsync(Customer customer,
AsyncHandler<Score> handler);
}
The asynchronous invocation that uses the callback mechanism
requires an additional input by the client programmer. The callback
is an object that contains the application code that will be
executed when an asynchronous response is received. The following
is a code example for an asynchronous callback handler:
CreditRatingService svc = ...;
Future<?> invocation = svc.getCreditScoreAsync(customerFred,
new AsyncHandler<Score>() {
public void handleResponse (
Response<Score> response)
{
Score score = response.get();
// do work here...
}
}
);
The following is a code example for an asynchronous polling
client:
CreditRatingService svc = ...;
Response<Score> response = svc.getCreditScoreAsync(customerFred);
while (!response.isDone()) {
// do something while we wait
}
// no cast needed, thanks to generics
Score score = response.get();
JAX-WS provides the wsgen and wsimport
command-line tools for generating portable artifacts for
JAX-WS Web services. When creating JAX-WS Web services, you
can start with either a WSDL file or an implementation bean
class. If you start with an implementation bean class, use
the wsgen command-line tool to generate all the Web services
server artifacts, including a WSDL file if requested. If you
start with a WSDL file, use the wsimport command-line tool to
generate all the Web services artifacts for either the server
or the client. The wsimport command line tool processes the
WSDL file with schema definitions to generate the portable
artifacts, which include the service class, the service
endpoint interface class, and the JAXB 2.0 classes for the
corresponding XML schema.
Java Architecture for XML Binding (JAXB) is a
Java technology that provides an easy and convenient way to
map Java classes and XML schema for simplified development of
Web services. JAXB leverages the flexibility of
platform-neutral XML data in Java applications to bind XML
schema to Java applications without requiring extensive
knowledge of XML programming.
Axis2 provides JAXB 2.0 standards.
JAXB is an XML to Java binding technology that supports
transformation between schema and Java objects and between
XML instance documents and Java object instances. JAXB
consists of a runtime application programming interface (API)
and accompanying tools that simplify access to XML documents.
JAXB also helps to build XML documents that both conform and
validate to the XML schema.
JAXB provides the xjc schema compiler tool, the
schemagen schema generator tool, and a runtime
framework. You can use the xjc schema compiler tool to
start with an XML schema definition (XSD) to create a set of
JavaBeans that map to the elements and types defined in the
XSD schema. You can also start with a set of JavaBeans and
use the schemagen schema generator tool to create the
XML schema. Once the mapping between XML schema and Java
classes exists, XML instance documents can be converted to
and from Java objects through the use of the JAXB binding
runtime API. Data stored in XML documents can be accessed
without the need to understand the data structure. You can
then use the resulting Java classes to assemble a Web
services application.
JAXB annotated classes and artifacts contain all the
information needed by the JAXB runtime API to process XML
instance documents. The JAXB runtime API supports marshaling
of JAXB objects to XML and unmarshaling the XML document back
to JAXB class instances. Optionally, you can use JAXB to
provide XML validation to enforce both incoming and outgoing
XML documents to conform to the XML constraints defined
within the XML schema.
JAXB is the default data binding technology used by the Java
API for XML Web Services (JAX-WS) 2.0 tooling and
implementation within this product. You can develop JAXB
objects for use within JAX-WS applications.
You can also use JAXB independently of JAX-WS when you want
to leverage the XML data binding technology to manipulate XML
within your Java applications.
The following diagram illustrates the JAXB
architecture.
When developing a JAX-WS Web service
starting from JavaBeans, you can use a bean that already
exists and then enable the implementation for JAX-WS Web
services. The use of annotations simplifies the enabling of a
bean for Web services. Adding the @WebService
annotation to the bean defines the application as a Web
service and how a client can access the Web service.
JavaBeans can have a service endpoint interface, but it is
not required. Enabling JavaBeans for Web services includes
annotating the bean and the optional service endpoint
interface, assembling all artifacts required for the Web
service, and deploying the application into Axis2. You are
not required to develop a WSDL file because the use of
annotations can provide all of the WSDL information necessary
to configure the service endpoint or the client. It is,
however, a best practice to develop a WSDL file.
- Develop a service endpoint interface.
-
Java API for XML-Based Web Services (JAX-WS) supports two
different service endpoint implementations types, the
standard JavaBeans service endpoint interface and a new
Provider
interface to enable services to
work at the XML message level. By using annotations on
the service endpoint or client, you can define the
service endpoint as a Web service.
JavaBeans endpoints in JAX-WS are similar to the endpoint
implementations in the Java API for XML-based RPC
(JAX-RPC) specification. Unlike JAX-RPC, the requirement
for a service endpoint interface (SEI) is optional for
JavaBeans-based services. JAX-WS services that do not
have an associated SEI are regarded as having an implicit
SEI, whereas services that have an associated SEI are
regarded as having an explicit SEI. The service endpoint
interfaces required by JAX-WS are also more generic than
the service endpoint interfaces required by JAX-RPC. With
JAX-WS, the SEI is not required to extend the
java.rmi.Remote interface as required by the JAX-RPC
specification.
The JAX-WS programming model also leverages support for
annotating Java classes with metadata to define a service
endpoint application as a Web service and define how a
client can access the Web service. JAX-WS supports
annotations based on the Metadata Facility for the Java
Programming Language (JSR 175) specification, the Web
Services Metadata for the Java Platform (JSR 181)
specification and annotations defined by the JAX-WS 2.0
(JSR 224) specification, which includes Java Architecture
for XML Binding (JAXB) annotations. Using annotations,
the service endpoint implementation can independently
describe the Web service without requiring a WSDL file.
Annotations can provide all of the WSDL information
necessary to configure your service endpoint
implementation or Web services client. You can specify
annotations on the service endpoint interface used by the
client and the server, or on the server-side service
implementation class.
To develop a JAX-WS Web service, you must annotate your
Java class with the javax.jws.WebService
annotation for JavaBeans endpoints or the
javax.jws.WebServiceProvider
annotation for
a Provider endpoint. These annotations define the Java
class as a Web service endpoint. For a JavaBeans
endpoint, the service endpoint interface or service
endpoint implementation is a Java interface or class,
respectively, that declares the business methods provided
by a particular Web service. The only methods on a
JavaBeans endpoint that can be invoked by a Web services
client are the business methods that are defined in the
explicit or implicit service endpoint interface.
All JavaBeans endpoints are required to have the
@WebService (javax.jws.WebService)
annotation included on the bean class. If the service
implementation bean also uses an SEI, then that endpoint
interface must be referenced by the endpointInterface
attribute on that annotation. If the service
implementation bean does not use an SEI, then the service
is described by the implicit SEI defined in the
bean.
The JAX-WS programming model introduces the new Provider
API, javax.xml.ws.Provider
, as an
alternative to service endpoint interfaces. The
Provider
interface supports a more messaging
oriented approach to Web services. With the
Provider
interface, you can create a Java
class that implements a simple interface to produce a
generic service implementation class. The
Provider
interface has one method, the
invoke method, which uses generics to control both the
input and output types when working with various messages
or message payloads. All Provider endpoints must be
annotated with the @WebServiceProvider
(javax.xml.ws.WebServiceProvider)
annotation. A
service implementation cannot specify the
@WebService
annotation if it implements the
javax.xml.ws.Provider
interface.
So the steps involved are:
- Identify your service endpoint requirements for
your Web services application.
-
First determine if the service implementation is a
JavaBeans endpoint or a Provider endpoint. If you
choose to use a JavaBeans endpoint, then determine if
you want to use an explicit SEI or if the bean itself
will have an implicit SEI.
A Java class that implements a Web service must
specify either the javax.jws.WebService
or javax.xml.ws.WebServiceProvider
annotation. Both annotations must not be present on a
Java class. The
javax.xml.ws.WebServiceProvider
annotation is only supported on classes that
implement the javax.xml.ws.Provider
interface.
- If you have an explicit service endpoint
interface with the Java class, then use the
endpointInterface parameter to specify the service
endpoint interface class name to the
javax.jws.WebService
annotation. You
can add the @WebMethod
annotation to
methods of a service endpoint interface to
customize the Java-to-WSDL mappings. All public
methods are considered as exposed methods
regardless of whether the @WebMethod
annotation is specified or not. It is incorrect to
have an @WebMethod
annotation on an
service endpoint interface that contains the
exclude
attribute.
- If you have an implicit service endpoint
interface with the Java class, then the
javax.jws.WebService
annotation will
use the default values for the
serviceName
, portName
,
and targetNamespace
parameters. To
override these default values, specify values for
these parameters in the @WebService
annotation. If the @WebMethod
annotation is not specified, all public methods are
exposed including the inherited methods with the
exception of methods inherited from
java.lang.Object
. The
exclude
parameter of the
@WebMethod
annotation can be used to
control which methods are exposed.
- If you are using the
Provider
interface, use the
javax.xml.ws.WebServiceProvider
annotation on the Provider endpoint.
- Annotate the service endpoints.
- Implement your service.
When using a bottom-up approach to develop JAX-WS Web
services, use the wsgen command-line tool when starting
from a service endpoint implementation. The wsgen tool
processes a compiled service endpoint implementation
class as input and generates the following portable
artifacts:
- any additional Java Architecture for XML Binding
(JAXB) classes that are required to marshal and
unmarshal the message contents. The additional classes
include classes that are represented by the
@RequestWrapper annotation and the
@ResponseWrapper
annotation for a wrapped
method.
- a WSDL file if the optional
-wsdl
argument is specified. The wsgen command does not
automatically generate the WSDL file. The WSDL file is
automatically generated when you deploy the service
endpoint.
You are not required to develop a WSDL file when
developing JAX-WS Web services using the bottom-up
approach of starting with JavaBeans. The use of
annotations provides all of the WSDL information
necessary to configure the service endpoint or the
client. Axis2 supports WSDL 1.1 documents that comply
with Web Services-Interoperability (WS-I) Basic Profile
1.1 specifications and are either Document/Literal style
documents or RPC/Literal style documents. Additionally,
WSDL documents with bindings that declare a USE attribute
of value LITERAL
are supported while the
value, ENCODED
, is not supported. For WSDL
documents that implement a Document/Literal wrapped
pattern, a root element is declared in the XML schema and
is used as an operation wrapper for a message flow.
Separate wrapper element definitions exist for both the
request and the response.
To ensure the wsgen command does not miss inherited
methods on a service endpoint implementation bean, you
must either add the @WebService
annotation
to the desired superclass or you can override the
inherited method in the implementation class with a call
to the superclass method. Implementation classes only
expose methods from superclasses that are annotated with
the @WebService
annotation.
Note: The wsgen command does not differentiate the
XML namespace between multiple XMLType
annotations that have the same @XMLType
name
defined within different Java packages. When this
scenario occurs, the following error is produced:
Error: Two classes have the same XML type name ....
Use @XmlType.name and @XmlType.namespace to assign different names to them...
This error indicates you have class names or
@XMLType.name
values that have the same name, but
exist within different Java packages. To prevent this error, add
the @XML.Type.namespace
class to the existing
@XMLType
annotation to differentiate between the
XML types.
- Develop the Java artifacts.
- Package and deploy your service.
You can use a top-down development
approach to create a JAX-WS Web service with an existing WSDL
file using JavaBeans.
You can use the JAX-WS tool, wsimport, to process a
WSDL file and generate portable Java artifacts that are used
to create a Web service. The portable Java artifacts created
using the wsimport tool are:
- Service endpoint interface (SEI)
- Service class
- Exception class that is mapped from the
wsdl:fault
class (if any)
- Java Architecture for XML Binding (JAXB) generated type
values which are Java classes mapped from XML schema
types
Run the
wsimport -keep -verbose wsdl_URL
command to generate the portable artifacts. The
-keep
option tells the tool not to delete the
generated files, and the -verbose
option tells it to
list the files that were created. The ObjectFactory.java file that
is created contains factory methods for each Java content interface
and Java element interface generated in the associated package. The
package-info.java file takes the targetNamespace
value
and creates the directory structure.
You must now provide an implementation for the SEI created by
the tool.
Axis2 provides two
mechanisms for deploying JAX-WS services:
- The service may be packaged and deployed as an AAR,
just like any other service within Axis2. Like with all
AARs, a services.xml file containing the relevant metadata
is required for the service to deploy correctly.
- The service may be packaged in a jar file and placed
into the
servicejars
directory. The
JAXWSDeployer
will examine all jars within
that directory and deploy those classes that have JAX-WS
annotations which identify them as Web services.
The Java API for XML-Based Web
Services (JAX-WS) Web service client programming model
supports both the Dispatch client API and the Dynamic Proxy
client API. The Dispatch client API is a dynamic client
programming model, whereas the static client programming
model for JAX-WS is the Dynamic Proxy client. The Dispatch
and Dynamic Proxy clients enable both synchronous and
asynchronous invocation of JAX-WS Web services.
- Dispatch client: Use this client when you want to work
at the XML message level or when you want to work without
any generated artifacts at the JAX-WS level.
- Dynamic Proxy client: Use this client when you want to
invoke a Web service based on a service endpoint
interface.
Dispatch client
XML-based Web services use XML
messages for communications between Web services and Web
services clients. The JAX-WS APIs provide high-level methods
to simplify and hide the details of converting between Java
method invocations and their associated XML messages.
However, in some cases, you might desire to work at the XML
message level. Support for invoking services at the XML
message level is provided by the Dispatch client API. The
Dispatch client API, javax.xml.ws.Dispatch
, is a
dynamic JAX-WS client programming interface. To write a
Dispatch client, you must have expertise with the Dispatch
client APIs, the supported object types, and knowledge of the
message representations for the associated WSDL file. The
Dispatch client can send data in either MESSAGE
or PAYLOAD
mode. When using the
javax.xml.ws.Service.Mode.MESSAGE
mode, the
Dispatch client is responsible for providing the entire SOAP
envelope including the <soap:Envelope>
,
<soap:Header>
, and
<soap:Body>
elements. When using the
javax.xml.ws.Service.Mode.PAYLOAD
mode, the
Dispatch client is only responsible for providing the
contents of the <soap:Body>
and JAX-WS
includes the payload in a <soap:Envelope>
element.
The Dispatch client API requires application clients to
construct messages or payloads as XML which requires a
detailed knowledge of the message or message payload. The
Dispatch client supports the following types of objects:
javax.xml.transform.Source
: Use
Source
objects to enable clients to use XML
APIs directly. You can use Source
objects with
SOAP or HTTP bindings.
- JAXB objects: Use JAXB objects so that clients can use
JAXB objects that are generated from an XML schema to
create and manipulate XML with JAX-WS applications. JAXB
objects can only be used with SOAP or HTTP bindings.
javax.xml.soap.SOAPMessage
: Use
SOAPMessage
objects so that clients can work
with SOAP messages. You can only use
SOAPMessage
objects with SOAP bindings.
javax.activation.DataSource
: Use
DataSource
objects so that clients can work
with Multipurpose Internet Mail Extension (MIME) messages.
Use DataSource
only with HTTP bindings.
For example, if the input parameter type is
javax.xml.transform.Source, the call to the Dispatch client
API is similar to the following code example:
Dispatch<Source> dispatch = … create a Dispatch<Source>
Source request = … create a Source object
Source response = dispatch.invoke(request);
The Dispatch parameter value determines the return type of
the invoke()
method.
The Dispatch client is invoked in one of three ways:
- Synchronous invocation for requests and responses using
the
invoke
method
- Asynchronous invocation for requests and responses
using the
invokeAsync
method with a callback
or polling object
- One-way invocation using the
invokeOneWay
methods
Refer to Chapter 4, section 3 of the JAX-WS 2.0 specification
for more information on using a Dispatch client.
Dynamic Proxy client
The static client programming
model for JAX-WS is the called the Dynamic Proxy client. The
Dynamic Proxy client invokes a Web service based on a Service
Endpoint Interface (SEI) which must be provided. The Dynamic
Proxy client is similar to the stub client in the Java API
for XML-based RPC (JAX-RPC) programming model. Although the
JAX-WS Dynamic Proxy client and the JAX-RPC stub client are
both based on the Service Endpoint Interface (SEI) that is
generated from a WSDL file , there is a major difference. The
Dynamic Proxy client is dynamically generated at run time
using the Java 5 Dynamic Proxy functionality, while the
JAX-RPC-based stub client is a non-portable Java file that is
generated by tooling. Unlike the JAX-RPC stub clients, the
Dynamic Proxy client does not require you to regenerate a
stub prior to running the client on an application server for
a different vendor because the generated interface does not
require the specific vendor information.
The Dynamic Proxy instances extend the
java.lang.reflect.Proxy
class and leverage the
Dynamic Proxy function in the base Java Runtime Environment
Version 5. The client application can then provide an
interface that is used to create the proxy instance while the
runtime is responsible for dynamically creating a Java object
that represents the SEI.
The Dynamic Proxy client is invoked in one of three
ways:
- Synchronous invocation for requests and responses using
the
invoke
method
- Asynchronous invocation for requests and responses
using the
invokeAsync
method with a callback
or polling object
- One-way invocation using the
invokeOneWay
methods
Refer to Chapter 4 of the JAX-WS 2.0 specification for more
information on using Dynamic Proxy clients.
Java API for
XML-Based Web Services (JAX-WS) tooling supports generating
Java artifacts you need to develop static JAX-WS Web services
clients when starting with a Web Services Description
Language (WSDL) file.
The static client programming model for JAX-WS is the called
the dynamic proxy client. The dynamic proxy client invokes a
Web service based on a service endpoint interface that is
provided. After you create the proxy, the client application
can invoke methods on the proxy just like a standard
implementation of those interfaces. For JAX-WS Web service
clients using the dynamic proxy programming model, use the
JAX-WS tool, wsimport, to process a WSDL file and
generate portable Java artifacts that are used to create a
Web service client.
Create the following portable Java artifacts using the
wsimport tool:
- Service endpoint interface (SEI)
- Service class
- Exception class that is mapped from the wsdl:fault
class (if any)
- Java Architecture for XML Binding (JAXB) generated type
values which are Java classes mapped from XML schema
types
The steps to creating a dynamic proxy client are:
- (Optional) If you are using WSDL or schema
customizations, use the -b option with the
wsimport command to specify an external binding
files that contain your customizations.
For example: wsimport -b binding.xml
wsdlfile.wsdl.
You can customize the bindings in your WSDL file to enable
asynchronous mappings or attachments. To generate
asynchronous interfaces, add the client-side only
customization enableAsyncMapping
binding
declaration to the wsdl:definitions
element or
in an external binding file that is defined in the WSDL
file. Use the enableMIMEContent
binding
declaration in your custom client or server binding file to
enable or disable the default mime:content
mapping rules. For additional information on custom binding
declarations, see chapter 8 the JAX-WS specification.
- Run the wsimport -keep wsdl_URL command
to generate the portable client artifacts. Use the
-verbose option to see a list of generated files
when you run the command.
Best practice: When you run the wsimport tool, the
location of your WSDL file must either be omitted or point
to a valid WSDL document. A best practice for ensuring that
you produce a JAX-WS Web services client that is portable
to other systems is to package the WSDL document within the
application module such as a Web services client Java
archive (JAR) file or a Web archive (WAR) file. You can
specify a relative URI for the location of your WSDL file
by using the-wsdllocation
annotation
attribute. For example, if your MyService.wsdl file is
located in the META-INF/wsdl/ directory, then run the
wsimport tool and use the -wsdllocation
option
to specify the value to be used for the location of the
WSDL file.
wsimport -keep
-wsdllocation=META-INF/wsdl/MyService.wsdl
JAX-WS provides a
new dynamic Dispatch client API that is more generic and
offers more flexibility than the existing Java API for
XML-based RPC (JAX-RPC)-based Dynamic Invocation Interface
(DII). The Dispatch client interface,
javax.xml.ws.Dispatch
, is an XML messaging
oriented client that is intended for advanced XML developers
who prefer to work at the XML level using XML constructs. To
write a Dispatch client, you must have expertise with the
Dispatch client APIs, the supported object types, and
knowledge of the message representations for the associated
WSDL file.
The Dispatch API can send data in either PAYLOAD
or MESSAGE
mode. When using the
PAYLOAD
mode, the Dispatch client is only
responsible for providing the contents of the
<soap:Body>
and JAX-WS includes the input
payload in a <soap:Envelope>
element. When
using the MESSAGE
mode, the Dispatch client is
responsible for providing the entire SOAP envelope.
The Dispatch client API requires application clients to
construct messages or payloads as XML and requires a detailed
knowledge of the message or message payload. The Dispatch
client can use HTTP bindings when using Source
objects, Java Architecture for XML Binding (JAXB) objects, or
data source objects. The Dispatch client supports the
following types of objects:
javax.xml.transform.Source
: Use
Source
objects to enable clients to use XML
APIs directly. You can use Source
objects with
SOAP and HTTP bindings.
- JAXB objects: Use JAXB objects so that clients can use
JAXB objects that are generated from an XML schema to
create and manipulate XML with JAX-WS applications. JAXB
objects can only be used with SOAP and HTTP bindings.
javax.xml.soap.SOAPMessage
: Use
SOAPMessage
objects so that clients can work
with SOAP messages. You can only use
SOAPMessage
objects with SOAP version 1.1 or
SOAP version 1.2 bindings.
javax.activation.DataSource
: Use
DataSource
objects so that clients can work
with Multipurpose Internet Mail Extension (MIME) messages.
Use DataSource
only with HTTP bindings.
The Dispatch API uses the concept of generics that are
introduced in Java Runtime Environment Version 5. For each of
the invoke() methods on the Dispatch interface, generics are
used to determine the return type.
The steps to creating a dynamic client are:
- Determine if you want your dynamic client to send data
in
PAYLOAD
or MESSAGE
mode.
- Create a service instance and add at least one port to
it. The port carries the protocol binding and service
endpoint address information.
- Create a
Dispatch<T>
object using
either the Service.Mode.PAYLOAD
method or the
Service.Mode.MESSAGE
method.
- Configure the request context properties on the
javax.xml.ws.BindingProvider
interface. Use
the request context to specify additional properties such
as enabling HTTP authentication or specifying the endpoint
address.
- Compose the client request message for the dynamic
client.
- Invoke the service endpoint with the Dispatch client
either synchronously or asynchronously.
- Process the response message from the service.
The following example illustrates the steps to create a
Dispatch client and invoke a sample EchoService service
endpoint.
String endpointUrl = ...;
QName serviceName = new QName("http://org/apache/ws/axis2/sample/echo/",
"EchoService");
QName portName = new QName("http://org/apache/ws/axis2/sample/echo/",
"EchoServicePort");
/** Create a service and add at least one port to it. **/
Service service = Service.create(serviceName);
service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointUrl);
/** Create a Dispatch instance from a service.**/
Dispatch<SOAPMessage> dispatch = service.createDispatch(portName,
SOAPMessage.class, Service.Mode.MESSAGE);
/** Create SOAPMessage request. **/
// compose a request message
MessageFactory mf = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
// Create a message. This example works with the SOAPPART.
SOAPMessage request = mf.createMessage();
SOAPPart part = request.getSOAPPart();
// Obtain the SOAPEnvelope and header and body elements.
SOAPEnvelope env = part.getEnvelope();
SOAPHeader header = env.getHeader();
SOAPBody body = env.getBody();
// Construct the message payload.
SOAPElement operation = body.addChildElement("invoke", "ns1",
"http://org/apache/ws/axis2/sample/echo/");
SOAPElement value = operation.addChildElement("arg0");
value.addTextNode("ping");
request.saveChanges();
/** Invoke the service endpoint. **/
SOAPMessage response = dispatch.invoke(request);
/** Process the response. **/
A JAX-WS client may be started from the
command line like any other Axis2-based client, including
through the use of the axis2
shell scripts in
the bin
directory of the installed runtime.
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.