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. **/