Develop 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.
JAX-WS provides a new dynamic Dispatch client API that is more generic and offers more flexibility than the existing 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, we 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.
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. Use Source objects with SOAP and HTTP bindings.
- JAXB objects: Use JAXB objects so that clients can use JAXB objects 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. We 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 introduced in Java SE Runtime Environment (JRE) 6. For each of the invoke() methods on the Dispatch interface, generics are used to determine the return type.
Tasks
- Determine if we want our 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.
- Optional: Set the jaxws.response.throwExceptionIfSOAPFault property on the RequestContext option for the Dispatch API to Boolean.TRUE if we do not want the JAX-WS runtime to throw a SOAPFaultException.
The following example illustrates how to specify this property on the RequestContext option for the Dispatch API
Dispatch<OMElement> dispatch = service.createDispatch( portName, OMElement.class, Mode.MESSAGE); BindingProvider bp = (BindingProvider)dispatch; bp.getRequestContext().put( "jaxws.response.throwExceptionIfSOAPFault", Boolean.FALSE);- 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.
We have developed a dynamic JAX-WS client using the Dispatch API. Refer to Chapter 4, section 3 of the JAX-WS 2.0 specification for more information on using a Dispatch client.
JAX-WS dynamic ports, which are those added using the service method addPort, might have additional memory requirements starting in WebSphere Application Server v8.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 we 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 we set this flag to true and encounter some of these issues, then we 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 WAS 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
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://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 essageFactory 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. **/
Related:
JAX-WS JAX-WS client programming model Implement static JAX-WS web services clients Developing a JAX-WS client from a WSDL file Invoking JAX-WS web services asynchronously Developing JAX-WS web services with annotations Web services specifications and APIs Java API for XML Web Services (JAX-WS) API documentation Java API for XML Web Services (JAX-WS) API User's Guide documentation