...
This WSDL also defines a binding, Greeter_SOAPBinding
, for the SOAP protocol. In practice, the binding is normally generated
automatically - for example, by running either of the CXF wsdl2soap or wsdl2xml utilities. Likewise, the SOAPService
service can be generated automatically by running the CXF wsdl2service utility.
...
Where ClientDir is the location of a directory where you would like to put the generated files and hello_world.wsdl
is a file containing the contract shown in the WSDL above. The -ant
option generates an ant build.xml
file, for use with the ant build utility. The -client
option generates starting point code for a client main()
method.
...
org.apache.hello_world_soap_http
This package name is generated from thehttp://apache.org/hello_world_soap_http
target namespace. All of the WSDL entities defined in this target namespace (for example, the Greeter port type and the SOAPService service) map to Java classes in the corresponding Java package.org.apache.hello_world_soap_http.types
This package name is generated from thehttp://apache.org/hello_world_soap_http/types
target namespace. All of the XML types defined in this target namespace (that is, everything defined in thewsdl:types
element of the HelloWorld contract) map to Java classes in the corresponding Java package.
...
- Classes representing WSDL entities (in the
org.apache.hello_world_soap_http
package) - the following classes are generated to represent WSDL entities:Greeter
is a Java interface that represents the Greeter WSDL port type. In JAX-WS terminology, this Java interface is a service endpoint interface.SOAPService
is a Java class that represents the SOAPService WSDLservice
element.PingMeFault
is a Java exception class (extendingjava.lang.Exception
) that represents the pingMeFault WSDLfault
element.
- Classes representing XML types (in the
org.apache.hello_world_soap_http.types
package) - in the HelloWorld example, the only generated types are the various wrappers for the request and reply messages. Some of these data types are useful for the
asynchronous invocation model.
...
This section describes how to write the code for a simple Java client, based on the WSDL contract above. To implement the client, you need to use the following stub classes:
...
Code Block | ||
---|---|---|
| ||
public class ServiceName extends javax.xml.ws.Service { ... public ServiceName(URL wsdlLocation, QName serviceName) { } public ServiceName() { } public Greeter getPortName() { } . . . } |
...
For example, the below shows the Greeter service endpoint interface, which is generated from the Greeter port type defined in #Example1. For simplicity, #Example3 omits the standard JAXB and JAX-WS annotations.
...
Code Block | ||
---|---|---|
| ||
/* Generated by WSDLToJava Compiler. */ package org.objectweb.hello_world_soap_http; ... public interface Greeter { public java.lang.String sayHi(); public java.lang.String greetMe(java.lang.String requestType); public void greetMeOneWay(java.lang.String requestType); public void pingMe() throws PingMeFault; } |
...
Code Block | ||
---|---|---|
| ||
package demo.hw.client; import java.io.File; import java.net.URL; import javax.xml.namespace.QName; import org.apache.hello_world_soap_http.Greeter; import org.apache.hello_world_soap_http.PingMeFault; import org.apche.hello_world_soap_http.SOAPService; public final class Client { private static final QName SERVICE_NAME = new QName("http://apache.org/hello_world_soap_http", "SOAPService"); private Client() { } public static void main(String args[]) throws Exception { if (args.length == 0) { System.out.println("please specify wsdl"); System.exit(1); } URL wsdlURL; File wsdlFile = new File(args[0]); if (wsdlFile.exists()) { wsdlURL = wsdlFile.toURL(); } else { wsdlURL = new URL(args[0]); } System.out.println(wsdlURL); SOAPService ss = new SOAPService(wsdlURL, SERVICE_NAME); Greeter port = ss.getSoapPort(); String resp; System.out.println("Invoking sayHi..."); resp = port.sayHi(); System.out.println("Server responded with: " + resp); System.out.println(); System.out.println("Invoking greetMe..."); resp = port.greetMe(System.getProperty("user.name")); System.out.println("Server responded with: " + resp); System.out.println(); System.out.println("Invoking greetMeOneWay..."); port.greetMeOneWay(System.getProperty("user.name")); System.out.println("No response from server as method is OneWay"); System.out.println(); try { System.out.println("Invoking pingMe, expecting exception..."); port.pingMe(); } catch (PingMeFault ex) { System.out.println("Expected exception: PingMeFault has occurred."); System.out.println(ex.toString()); } System.exit(0); } } |
...
CXF supports the following context properties:
Context Property Name | Context Property Type |
---|---|
|
|
Asynchronous Invocation Model
...
Customization enables you to modify the way the wsdl2java utility generates stub code. In particular, it enables you to modify the WSDL-to-Java mapping and to switch on certain features. Here, customization is used to switch on the asynchronous invocation feature. Customizations are specified using a binding declaration, which you define using a jaxws:bindings
tag (where the jaxws prefix is tied to the http://java.sun.com/xml/ns/jaxws
namespace). There are two alternative ways of specifying a binding declaration:
...
For example, if you want to generate asynchronous methods only for the GreeterAsync
port type, you could specify <bindings node="wsdl:definitions/wsdl:portType@name='GreeterAsync'">
in the preceding binding declaration.
...
The below sample illustrates the polling approach to making an asynchronous operation call. Using this approach, the client invokes the
operation by calling the special Java method, _OperationName_Async()
, that returns a javax.xml.ws.Response<T>
object, where T is the type of the operation's response message. The Response<T>
object can be polled at a later stage to check whether the operation's response message has arrived.
...
Code Block | ||
---|---|---|
| ||
package demo.hw.client; import java.io.File; import java.util.concurrent.Future; import javax.xml.namespace.QName; import javax.xml.ws.Response; import org.apache.hello_world_async_soap_http.GreeterAsync; import org.apache.hello_world_async_soap_http.SOAPService; import org.apche.hello_world_async_soap_http.types.GreetMeSometimeResponse; public final class Client { private static final QName SERVICE_NAME = new QName("http://objectweb.org/hello_world_async_soap_http", "SOAPService"); private Client() {} public static void main(String args[]) throws Exception { ... // Polling approach: Response<GreetMeSometimeResponse> greetMeSomeTimeResp = port.greetMeSometimeAsync(System.getProperty("user.name")); while (!greetMeSomeTimeResp.isDone()) { Thread.sleep(100); } GreetMeSometimeResponse reply = greetMeSomeTimeResp.get(); ... System.exit(0); } } |
The greetMeSometimeAsync()
method invokes the greetMeSometimes
operation, transmitting the input parameters to the remote service and returning a reference to a javax.xml.ws.Response<GreetMeSometimeResponse>
object. The Response
class is defined by extending the standard java.util.concurrency.Future<T>
interface, which is specifically designed for polling the outcome of work performed by a concurrent thread. There are essentially two basic approaches to polling using the Response
object:
Non-blocking polling - before attempting to get the result, check whether the response has arrived by calling the non-blocking
Response<T>.isDone()
method. For example:Code Block Response<GreetMeSometimeResponse> greetMeSomeTimeResp = ...; if (greetMeSomeTimeResp.isDone()) { GreetMeSometimeResponse reply = greetMeSomeTimeResp.get(); }
Blocking polling - call
Response<T>.get()
right away and block until the response arrives (optionally specifying a timeout). For example, to poll for a response, with a 60 second timeout:Code Block Response<GreetMeSometimeResponse> greetMeSomeTimeResp = ...; GreetMeSometimeResponse reply = greetMeSomeTimeResp.get( 60L, java.util.concurrent.TimeUnit.SECONDS );
Implementing an asynchronous client with the callback approach
An alternative approach to making an asynchronous operation invocation is to implement a callback class, by deriving from the javax.xml.ws.AsyncHandler
interface. This callback class must implement a handleResponse()
method, which is called by the CXF runtime to notify the client that the response has arrived. The following shows an outline of the AsyncHandler
interface that you need to implement.
...
The implementation of handleResponse()
shown in #Example11 simply gets the response data and stores it in a member variable, reply
. The extra getResponse()
method is just a convenience method that extracts the sole output parameter (that is, responseType
) from the response.
#Example12 illustrates the callback approach to making an asynchronous operation call. Using this approach, the client invokes the operation by calling the special Java method, _OperationName_Async()
, that returns a java.util.concurrency.Future<?>
object and takes an extra parameter of AsyncHandler<T>
.
...
The Future<?>
object returned by greetMeSometimeAsync()
can be used only to test whether or not a response has arrived yet - for example, by calling response.isDone()
. The value of the response is only made available to the callback object, testAsyncHandler
.
Warning |
---|
Please be careful when using asynchronous consumers along with reactive / non-blocking libraries. There is certain amount of intialization code (usually, on the first asynchronous invocation) which may cause unnecessary blocking. |