Developing a dynamic client using JAX-WS APIs
Java™ API for XML-Based Web Services (JAX-WS) provides support for the dynamic invocation of service endpoint operations.
About this task
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 Web Services Description Language (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.
- 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.
invoke()
methods on the
Dispatch interface, generics are used to determine the return type.Procedure
Results
JAX-WS dynamic
ports, which are those added using the service method addPort, might
have additional memory requirements starting in WebSphere® Application Server Version 8.0. In
previous releases, a single instance of a dynamic port could be shared
across multiple service instances. In version 8.x, dynamic ports are
now scoped to the instance of the service that added them. If a JAX-WS
client has multiple service instances which refer to a dynamic port
of the same name, those instances are no longer shared. This can potentially
increase the memory requirements for that client. The memory used
by dynamic ports is released when the service instance goes out of
scope. However, if you encounter issues related to increased memory
usage, it is possible to revert the behavior so that dynamic ports
are again shared across service instances. To do this, set the system
property jaxws.share.dynamic.ports.enable
to the
value true
. However, note that doing so can cause
some other issues, such as having policy set attachments incorrectly
applied across shared dynamic ports. If you set this flag to true
and
encounter some of these issues, then you should remove the flag setting.
In
previous releases, if a SOAP Action was not provided by the Dispatch
client application, the correct SOAP Action was not sent on the outbound
message. Instead, the SOAP action was set to an anonymous operation.
Starting in WebSphere Application Server Version
8, if the SOAP Action is not provided by the Dispatch client application,
the JAX-WS runtime environment parses the outgoing message. It determines
the operation being invoked and uses that information to determine
the appropriate value for the SOAP Action. The operation resolution
of the outbound message is based on the SOAP Body and the message
encoding, for example, Doc/Lit/Bare, Doc/Lit/Wrapped. Since this parsing
can be expensive, a property can be set. To always disable the parsing,
set the property at the System level. To disable parsing on a per-message
basis, set the property on the JAX-WS Request Message Context. The
property is defined as a constant org.apache.axis2.jaxws.Constants.DISPATCH_CLIENT_OUTBOUND_RESOLUTION
with
a String value of jaxws.dispatch.outbound.operation.resolution.enable
.
The default value of the property is null which is interpreted as
the String true, which enables the outbound
operation resolution. Setting the property to false disables
the outbound operation resolution. If parsing is disabled, then the
SOAP Action in the outbound message is set to an anonymous operation
as in previous releases. If the client provides a SOAP Action through
the JAX-WS javax.xml.ws.BindingProvider
properties, SOAPACTION_USE_PROPERTY
and SOAPACTION_URI_PROPERTY
,
then that SOAP Action is used. Therefore, parsing of the outbound
message does not occur regardless of the setting of the property.
Setting a SOAP Action explicitly by the client is considered a best
practice, particularly for performance on the service-provider. This
practice prevents the inbound message from being parsed, to be routed
to the correct endpoint operation.
Example
String endpointUrl = ...;
QName serviceName = new QName("http://com/ibm/was/wssample/echo/",
"EchoService");
QName portName = new QName("http://com/ibm/was/wssample/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://com/ibm/was/wssample/echo/");
SOAPElement value = operation.addChildElement("arg0");
value.addTextNode("ping");
request.saveChanges();
/** Invoke the service endpoint. **/
SOAPMessage response = dispatch.invoke(request);
/** Process the response. **/