...
Basic HelloWorld WSDL contract
#Example1 The below shows the HelloWorld WSDL contract. This contract defines a single port type, Greeter
, with a SOAP binding, Greeter_SOAPBinding
, and a service, SOAPService
, which has a single port, SoapPort
.
Code Block |
---|
title | Example 1:HelloWorld WSDL Contract |
---|
|
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="HelloWorld" targetNamespace="http://apache.org/hello_world_soap_http"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://apache.org/hello_world_soap_http"
xmlns:x1="http://apache.org/hello_world_soap_http/types"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<schema targetNamespace="http://apache.org/hello_world_soap_http/types"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://apache.org/hello_world_soap_http/types"
elementFormDefault="qualified">
<simpleType name="MyStringType">
<restriction base="string">
<maxLength value="30" />
</restriction>
</simpleType>
<element name="sayHi">
<complexType/>
</element>
<element name="sayHiResponse">
<complexType>
<sequence>
<element name="responseType" type="string"/>
</sequence>
</complexType>
</element>
<element name="greetMe">
<complexType>
<sequence>
<element name="requestType" type="tns:MyStringType"/>
</sequence>
</complexType>
</element>
<element name="greetMeResponse">
<complexType>
<sequence>
<element name="responseType" type="string"/>
</sequence>
</complexType>
</element>
<element name="greetMeOneWay">
<complexType>
<sequence>
<element name="requestType" type="string"/>
</sequence>
</complexType>
</element>
<element name="pingMe">
<complexType/>
</element>
<element name="pingMeResponse">
<complexType/>
</element>
<element name="faultDetail">
<complexType>
<sequence>
<element name="minor" type="short"/>
<element name="major" type="short"/>
</sequence>
</complexType>
</element>
</schema>
</wsdl:types>
<wsdl:message name="sayHiRequest">
<wsdl:part element="x1:sayHi" name="in"/>
</wsdl:message>
<wsdl:message name="sayHiResponse">
<wsdl:part element="x1:sayHiResponse" name="out"/>
</wsdl:message>
<wsdl:message name="greetMeRequest">
<wsdl:part element="x1:greetMe" name="in"/>
</wsdl:message>
<wsdl:message name="greetMeResponse">
<wsdl:part element="x1:greetMeResponse" name="out"/>
</wsdl:message>
<wsdl:message name="greetMeOneWayRequest">
<wsdl:part element="x1:greetMeOneWay" name="in"/>
</wsdl:message>
<wsdl:message name="pingMeRequest">
<wsdl:part name="in" element="x1:pingMe"/>
</wsdl:message>
<wsdl:message name="pingMeResponse">
<wsdl:part name="out" element="x1:pingMeResponse"/>
</wsdl:message>
<wsdl:message name="pingMeFault">
<wsdl:part name="faultDetail" element="x1:faultDetail"/>
</wsdl:message>
<wsdl:portType name="Greeter">
<wsdl:operation name="sayHi">
<wsdl:input message="tns:sayHiRequest" name="sayHiRequest"/>
<wsdl:output message="tns:sayHiResponse" name="sayHiResponse"/>
</wsdl:operation>
<wsdl:operation name="greetMe">
<wsdl:input message="tns:greetMeRequest" name="greetMeRequest"/>
<wsdl:output message="tns:greetMeResponse" name="greetMeResponse"/>
</wsdl:operation>
<wsdl:operation name="greetMeOneWay">
<wsdl:input message="tns:greetMeOneWayRequest" name="greetMeOneWayRequest"/>
</wsdl:operation>
<wsdl:operation name="pingMe">
<wsdl:input name="pingMeRequest" message="tns:pingMeRequest"/>
<wsdl:output name="pingMeResponse" message="tns:pingMeResponse"/>
<wsdl:fault name="pingMeFault" message="tns:pingMeFault"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="Greeter_SOAPBinding" type="tns:Greeter">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="sayHi">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="sayHiRequest">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="sayHiResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="greetMe">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="greetMeRequest">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="greetMeResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="greetMeOneWay">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="greetMeOneWayRequest">
<soap:body use="literal"/>
</wsdl:input>
</wsdl:operation>
<wsdl:operation name="pingMe">
<soap:operation style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="pingMeFault">
<soap:fault name="pingMeFault" use="literal"/>
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SOAPService">
<wsdl:port binding="tns:Greeter_SOAPBinding" name="SoapPort">
<soap:address location="http://localhost:9000/SoapContext/SoapPort"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
|
The Greeter
port type from #Example1 defines the following WSDL operations:
sayHi
- has a single output parameter, of xsd:string
.greetMe
- has an input parameter, of xsd:string
, and an output parameter, of xsd:string
.greetMeOneWay
- has a single input parameter, of xsd:string
. Because this operation has no output parameters, CXF can optimize this call to be a oneway invocation (that is, the client does not wait for a response from the server).pingMe
- has no input parameters and no output parameters, but it can raise a fault exception.
#Example1 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 #Example1the 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.
...
This section describes how to write the code for a simple Java client, based on the WSDL contract from #Example1 above. To implement the client, you need to use the following stub classes:
- Service class (that is,
SOAPService
). - Service endpoint interface (that is,
Greeter
).
Generated service class
#Example2 The below shows the typical outline for a generated service class, ServiceName
, which extends the javax.xml.ws.Service
base class.
Code Block |
---|
title | Example 2:Outline of a Generated Service Class |
---|
|
public class ServiceName extends javax.xml.ws.Service
{
...
public ServiceName(URL wsdlLocation, QName serviceName) { }
public ServiceName() { }
public Greeter getPortName() { }
.
.
.
}
|
The ServiceName
class in #Example2 defines the following methods:
...
- The input parameters are mapped to method arguments.
- The first output parameter is mapped to a return value.
- If there is more than one output parameter, the second and subsequent output parameters map to method arguments (moreover, the values of these arguments must be passed using Holder types).
For example, #Example3 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 |
---|
title | Example 3:The Greeter Service Endpoint Interface |
---|
|
/* 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;
}
|
Client main function
#Example4 shows the Here is Java code that implements the HelloWorld client. In summary, the client connects to the SoapPort
port on the SOAPService
service and then proceeds to invoke each of the operations supported by the Greeter
port type.
Code Block |
---|
title | Example 4:Client Implementation Code |
---|
|
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);
}
}
|
The Client.main()
function from #Example4 proceeds as follows:</para>
...
To set a particular request context property, ContextPropertyName, to the value, PropertyValue, use the code shown in #Example4.here:
Code Block |
---|
title | Example 4:Setting a Request Context Property on the Client Side |
---|
|
// Set request context property.
java.util.Map<String, Object> requestContext =
((javax.xml.ws.BindingProvider)port).getRequestContext();
requestContext.put(ContextPropertyName, PropertyValue);
// Invoke an operation.
port.SomeOperation();
|
...
To retrieve a particular response context property, ContextPropertyName, use the code shown in #Example5.here:
Code Block |
---|
title | Example 5:Reading a Response Context Property on the Client Side |
---|
|
// Invoke an operation.
port.SomeOperation();
// Read response context property.
java.util.Map<String, Object> responseContext =
((javax.xml.ws.BindingProvider)port).getResponseContext();
PropertyType propValue = (PropertyType) responseContext.get(ContextPropertyName);
|
...
Contract for asynchronous example
#Example6 The following example shows the WSDL contract that is used for the asynchronous example. The contract defines a single port type, GreeterAsync
, which contains a single operation, greetMeSometime
.
Code Block |
---|
title | Example 6:HelloWorld WSDL Contract for Asynchronous Example |
---|
|
<wsdl:definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://apache.org/hello_world_async_soap_http"
xmlns:x1="http://apache.org/hello_world_async_soap_http/types"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://apache.org/hello_world_async_soap_http"
name="HelloWorld">
<wsdl:types>
<schema targetNamespace="http://apache.org/hello_world_async_soap_http/types"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:x1="http://apache.org/hello_world_async_soap_http/types"
elementFormDefault="qualified">
<element name="greetMeSometime">
<complexType>
<sequence>
<element name="requestType" type="xsd:string"/>
</sequence>
</complexType>
</element>
<element name="greetMeSometimeResponse">
<complexType>
<sequence>
<element name="responseType" type="xsd:string"/>
</sequence>
</complexType>
</element>
</schema>
</wsdl:types>
<wsdl:message name="greetMeSometimeRequest">
<wsdl:part name="in" element="x1:greetMeSometime"/>
</wsdl:message>
<wsdl:message name="greetMeSometimeResponse">
<wsdl:part name="out" element="x1:greetMeSometimeResponse"/>
</wsdl:message>
<wsdl:portType name="GreeterAsync">
<wsdl:operation name="greetMeSometime">
<wsdl:input name="greetMeSometimeRequest" message="tns:greetMeSometimeRequest"/>
<wsdl:output name="greetMeSometimeResponse" message="tns:greetMeSometimeResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="GreeterAsync_SOAPBinding" type="tns:GreeterAsync">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="greetMeSometime">
<soap:operation style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SOAPService">
<wsdl:port name="SoapPort" binding="tns:GreeterAsync_SOAPBinding">
<soap:address location="http://localhost:9000/SoapContext/SoapPort"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
|
...
This section considers only the first approach, the external binding declaration. The template for a binding declaration file that switches on asynchronous invocations is shown in #Example7.next:
Code Block |
---|
title | Example 7:Template for an Asynchronous Binding Declaration |
---|
|
<bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
wsdlLocation="<at:var at:name="WSDL_LOCATION" />/hello_world_async.wsdl"
xmlns="http://java.sun.com/xml/ns/jaxws">
<bindings node="wsdl:definitions">
<enableAsyncMapping>true</enableAsyncMapping>
</bindings>
</bindings>
|
...
When you run the wsdl2java command, you specify the location of the binding declaration file using the -b option. After generating the stub code in this way, the GreeterAsync
service endpoint interface (in the file GreeterAsync.java
) is defined as shown in #Example8.below:
Code Block |
---|
title | Example 8:Service Endpoint Interface with Methods for Asynchronous Invocations |
---|
|
/* Generated by WSDLToJava Compiler. */
package org.apache.hello_world_async_soap_http;
...
import java.util.concurrent.Future;
import javax.xml.ws.AsyncHandler;
import javax.xml.ws.Response;
...
public interface GreeterAsync {
public Future<?> greetMeSometimeAsync(
java.lang.String requestType,
AsyncHandler<org.apache.hello_world_async_soap_http.types.GreetMeSometimeResponse> asyncHandler
);
public Response<org.pache.hello_world_async_soap_http.types.GreetMeSometimeResponse> greetMeSometimeAsync(
java.lang.String requestType
);
public java.lang.String greetMeSometime(
java.lang.String requestType
);
}
|
...
Implementing an asynchronous client with the polling approach
#Example9 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 |
---|
title | Example 9:Polling Approach for an Asynchronous Operation Call |
---|
|
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);
}
}
|
...
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. #Example10 The following shows an outline of the AsyncHandler
interface that you need to implement.
Code Block |
---|
title | Example10: The javax.xml.ws.AsyncHandler Interface |
---|
|
package javax.xml.ws;
public interface AsyncHandler<T>
{
void handleResponse(Response<T> res);
}
|
In this example, a callback class, TestAsyncHandler
, is defined as shown in #Example11below.
Code Block |
---|
title | Example 11: The TestAsyncHandler Callback Class |
---|
|
package demo.hw.client;
import javax.xml.ws.AsyncHandler;
import javax.xml.ws.Response;
import org.apache.hello_world_async_soap_http.types.GreetMeSometimeResponse;
public class TestAsyncHandler implements AsyncHandler<GreetMeSometimeResponse> {
private GreetMeSometimeResponse reply;
public void handleResponse(Response<GreetMeSometimeResponse> response) {
try {
reply = response.get();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public String getResponse() {
return reply.getResponseType();
}
}
|
...