<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | |
"http://www.w3.org/TR/html4/loose.dtd"> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1"> | |
<title>Axis2 User's Guide</title> | |
<meta name="generator" content="amaya 9.3, see http://www.w3.org/Amaya/"> | |
</head> | |
<body lang="en-US" dir="ltr"> | |
<h4><a name="Axis2_User's_Guide">Axis2 User's Guide</a></h4> | |
<p><i>Version 0.95</i></p> | |
<i>User Feedback: <a | |
href="mailto:axis-user@ws.apache.org">axis-user@ws.apache.org</a></i> | |
<p align="right">Pages: <a href="userguide.html">Content</a>, <a | |
href="userguide1.html">1</a>, <a href="userguide2.html">2</a>, <b>3</b>, <a | |
href="userguide4.html">4</a>, <a href="userguide5.html">5</a></p> | |
<p><b><font size="4">Note (on samples):</font></b> In this page of the user's | |
guide we will look at how to write Web Service Clients using Axis2. All the | |
user's guide samples are located at the <b><font | |
color="#000000">"samples/userguide/src"</font></b> directory of the binary | |
distribution. So... let's explore the samples.</p> | |
<h2><a name="Web_Service_Clients_Using_Axis2">Web Service Clients Using | |
Axis2</a></h2> | |
<p>Now let's see how we can write a Web Service Client to use this Web | |
Service.</p> | |
<p>Web services can be used to provide wide range of functionality to the | |
users ranging from simple, less time consuming operations such as | |
"getStockQuote" to time consuming business services. When we utilize (invoke | |
using client applications) these Web Service we cannot use some simple | |
generic invocation paradigm that suites all the timing complexities involved | |
in the service operations. For example, if we use a single transport channel | |
(such as HTTP) to invoke a Web Service with and IN-OUT operation that take | |
long time to complete, then most of the time we may end up with "connection | |
time outs". On the other hand, if there are simultaneous service invocations | |
that we need to perform from a single client application, then the use of a | |
"blocking" client API will degrade the performance of the client application. | |
Similarly there are various other consequences such as One-Way transports | |
that come in to play when we need them. Let's try to analyze some common | |
service invocation paradigms.</p> | |
<p>Many web service engines provide the users with a Blocking and | |
Non-Blocking client APIs.</p> | |
<ul> | |
<li><p style="margin-bottom: 0in"><b>Blocking API</b> -Once the service | |
invocation is called, the client application hangs and only gets control | |
back when the operation completes, after which client receives a response | |
or a fault. This is the simplest way of invoking Web Services and it also | |
suites many business situations.</p> | |
</li> | |
<li><p><b>Non-Blocking API </b>- This is a callback or polling based API, | |
hence once a service invocation is called, the client application | |
immediately gets the control back and the response is retrieved using the | |
callback object provided. This approach provides the flexibility to the | |
client application to invoke several Web Services simultaneously without | |
blocking the operation already invoked.</p> | |
</li> | |
</ul> | |
<p>Both these mechanisms work in the API level. Let's name the asynchronous | |
behavior that we can get using the <strong>Non-Blocking API</strong> as | |
<b>API Level Asynchrony.</b></p> | |
<p>Both these mechanisms use single transport connection to send the request | |
and to receive the response. They severely lags the capability of using two | |
transport connections for the request and the response (either One-Way of | |
Two-Way). So both these mechanisms fail to address the problem of long | |
running transactions (the transport connection may time-out before the | |
operation completes). A possible solution would be to use <strong>two | |
separate transport connections for request and response</strong>. The | |
asynchronous behavior that we gain using this solution can be called | |
<b>Transport Level Asynchrony</b>.</p> | |
<p>By combining API Level Asynchrony & Transport Level Asynchrony we can | |
obtain four different invocation patterns for web services as shown in the | |
following table.</p> | |
<a name="table1"></a> | |
<table width="100%" border="1" cellpadding="0" cellspacing="0"> | |
<tbody> | |
<tr> | |
<td width="33%" height="19"><p><strong>API | |
(Blocking/Non-Blocking)</strong></p> | |
</td> | |
<td width="33%"><p><strong> Dual Transports (Yes/No)</strong></p> | |
</td> | |
<td width="33%"><p><strong>Description</strong></p> | |
</td> | |
</tr> | |
<tr> | |
<td width="33%" height="19"><p>Blocking</p> | |
</td> | |
<td width="33%"><p>No</p> | |
</td> | |
<td width="33%"><p>Simplest and the familiar invocation pattern</p> | |
</td> | |
</tr> | |
<tr> | |
<td width="33%" height="19"><p>Non-Blocking</p> | |
</td> | |
<td width="33%"><p>No</p> | |
</td> | |
<td width="33%"><p>Using callbacks or polling</p> | |
</td> | |
</tr> | |
<tr> | |
<td width="33%" height="19"><p>Blocking</p> | |
</td> | |
<td width="33%"><p>Yes</p> | |
</td> | |
<td width="33%"><p>This is useful when the service operation is IN-OUT | |
in nature but the transport used is One-Way (e.g. SMTP)</p> | |
</td> | |
</tr> | |
<tr> | |
<td width="33%" height="19"><p>Non-Blocking</p> | |
</td> | |
<td width="33%"><p>Yes</p> | |
</td> | |
<td width="33%"><p>This is can be used to gain the maximum asynchronous | |
behavior. No blocking in the API level and also in the transport | |
level</p> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
<p>Axis2 provides the user with all these possibilities to invoke Web | |
Services.</p> | |
<p>Below we describe how to write Web Services Clients using Axis2. This can | |
be done in two methods:</p> | |
<ol> | |
<li><a href="#Writing_Web_Service_Clients_using_Axis2's_Primary_APIs">Using | |
the Axis2's primary APIs</a></li> | |
<li><p><a | |
href="#Writing_Web_Service_Clients_using_Code_Generation_with_Data_Binding_Support">Using | |
stubs generated with data binding support</a>, making the life easy for | |
developers writing Web Service client applications</p> | |
</li> | |
</ol> | |
<h3><a name="Writing_Web_Service_Clients_using_Axis2's_Primary_APIs">Writing | |
Web Service Clients Using Axis2's Primary APIs</a></h3> | |
<h4><a name="EchoBlockingClient">EchoBlockingClient</a></h4> | |
<p>Axis2 provides the user with several invocation patterns for Web Services, | |
ranging from pure blocking single channel invocations to a non-blocking dual | |
channel invocations. Let's first see how we can write a client to invoke | |
"echo" operation of "MyService" using the simplest blocking invocation. The | |
client code you need to write is as follows.</p> | |
<source><pre> try { | |
OMElement payload = ClientUtil.getEchoOMElement(); | |
<span style="color: #24C113"> | |
Options options = new Options(); | |
options.setTo(targetEPR); | |
options.setListenerTransportProtocol(Constants.TRANSPORT_HTTP); | |
options.setUseSeparateListener(false); | |
ServiceClient serviceClient = new ServiceClient(); | |
serviceClient.setOptions(options); | |
OMElement result = sender.sendReceive(payload); | |
</span> | |
StringWriter writer = new StringWriter(); | |
result.serializeWithCache(new OMOutput(XMLOutputFactory.newInstance().createXMLStreamWriter(writer))); | |
writer.flush(); | |
System.out.println(writer.toString()); | |
} catch (AxisFault axisFault) { | |
axisFault.printStackTrace(); | |
} catch (XMLStreamException e) { | |
e.printStackTrace(); | |
} | |
}</pre> | |
</source> | |
<p>The green lines shows the set of operations that you need to perform | |
inorder to invoke a web service. The rest is used to create the OMElement | |
that needs to be sent and display the response OMElement. To test this | |
client, use the provided ant build file that can be found in the | |
"Axis2Home/samples" directory. Run the "testEchoBlockingClient" target . If | |
you can see the response OMElement printed in your command line, then you | |
have successfully tested the client. </p> | |
<h4><a name="PingClient">PingClient</a></h4> | |
<p>In the Web Service "MyService" we had a IN-ONLY operation with the name | |
"ping" (see <a href="userguide2.html#Web_Services_Using_Axis2">Web Services | |
Using Axis2</a>). Let's write a client to invoke this operation. The client | |
code is as follows:</p> | |
<pre> try { | |
OMElement payload = ClientUtil.getPingOMElement(); | |
Options options = new Options(); | |
options.setTo(targetEPR); | |
ServiceClient serviceClient = new ServiceClient(); | |
serviceClient.setOptions(options); | |
serviceClient.fireAndForget(payload); | |
/** | |
* We have to bock this thread untill we send the request , the problem | |
* is if we go out of the main thread , then request wont send ,so | |
* you have to wait some time :) | |
*/ | |
Thread.sleep(500); | |
} | |
catch (AxisFault axisFault) { | |
axisFault.printStackTrace(); | |
}</pre> | |
<p>Since we are accessing a IN-ONLY operation we can directly use the | |
"fireAndForget()" in ServiceClient to invoke this operation , and that will | |
not block the invocation, hence it will return the control immediately back | |
to the client. You can test this client by running the target | |
"testPingClient" of the ant build file at "Axis2Home/samples".</p> | |
<p>We have invoked the two operations in our service. Are we done? No! There | |
are lot more to explore. Let's see some other ways to invoke the same | |
operations...</p> | |
<h4><a name="EchoNonBlockingClient">EchoNonBlockingClient</a></h4> | |
<p>In the EchoBlockingClient once the "serviceCleint.sendReceive(payload);" | |
is called, the client is blocked till the operation is completed. This | |
behavior is not desirable when there are many Web Service invocations to be | |
done in a single client application. A solution would be to use a | |
Non-Blocking API to invoke web services. Axis2 provides a callback based | |
non-blocking API for users.</p> | |
<p>A sample client for this can be found under | |
"Axis2Home/samples/userguide/src/userguide/clients" with the name | |
EchoNonBlockingClient. If we consider the changes that user may have to do | |
with respect to the "EchoBlockingClient" that we have already seen, it will | |
be as follows:</p> | |
<pre style="margin-bottom: 0.2in">serviceClient.sendReceiveNonblocking(payload, callback);</pre> | |
<p>The invocation accepts a callback object as a parameter. Axis2 client API | |
provides an abstract Callback with the following methods:</p> | |
<pre>public abstract void onComplete(AsyncResult result); | |
public abstract void onError(Exception e); | |
public boolean isComplete() {}</pre> | |
<p>The user is expected to implement the "onComplete " and "onError " methods | |
of their extended call back class. Axis2 engine calls the onComplete method | |
once the Web Service response is received by the Axis2 Client API | |
(ServiceClient). This will eliminate the blocking nature of the Web Service | |
invocations and provides the user with the flexibility to use Non Blocking | |
API for Web Service Clients.</p> | |
<p>To run the sample client ( EchoNonBlockingClient) you can simply use the | |
"testEchoNonBlockingClient" target of the ant file found at the | |
"Axis2Home/samples" directory.</p> | |
<h4><a name="EchoNonBlockingDualClient">EchoNonBlockingDualClient</a></h4> | |
<p>The solution provided by the Non-Blocking API has one limitation when it | |
comes to Web Service invocations which takes long time to complete. The | |
limitation is due to the use of single transport connection to invoke the Web | |
Service and to retrieve the response. In other words, client API provides a | |
non blocking invocation mechanism for the users, but the request and the | |
response comes in a single transport (Two-Way transport) connection (like | |
HTTP). Long running Web Service invocations or Web Service invocations using | |
One-Way transports (like SMTP) cannot be utilized by simply using a non | |
blocking invocation. </p> | |
<p>The trivial solution is to use separate transport connections (either | |
One-Way or Two-Way) for the request and response. The next problem that needs | |
to be solved is the correlation (correlating the request and the response). | |
<a href="http://www.w3.org/Submission/ws-addressing/" | |
target="_blank">WS-Addressing</a> provides a neat solution to this using | |
<wsa:MessageID> and <wsa:RelatesTo> headers. Axis2 provides | |
support for addressing based correlation mechanism and a complying Client | |
API to invoke Web Services with two transport connections. (Core of Axis2 | |
does not depend on WS-Addressing, but contains a set of parameters like in | |
addressing that can be populated in any means. WS-Addressing is one of the | |
users that may populate them. Even the transports can populate these. Hence | |
Axis2 has the flexibility to use different versions of addressing)</p> | |
<p>Users can select between Blocking or Non-Blocking APIs for the Web Service | |
clients with two transport connections. By simply using a boolean flag, the | |
same API can be used to invoke web services (IN-OUT operations) using two | |
separate transport connections. Let's see how it's done using an example. | |
Following code fragment shows how to invoke the same "echo" operation using | |
Non-Blocking API with two transport connections<strong>. The ultimate | |
asynchrony!!</strong></p> | |
<pre> try { | |
OMElement payload = ClientUtil.getEchoOMElement(); | |
Options options = new Options();<br> options.setTo(targetEPR); | |
//The boolean flag informs the axis2 engine to use two separate transport connection | |
//to retrieve the response. | |
<br> options.setUseSeparateListener(true); | |
options.setAction("urn:echo"); | |
ServiceClient serviceClinet = new ServiceClinet(); | |
<br> serviceClinet.setOptions(options);</pre> | |
<pre> | |
//Callback to handle the response | |
Callback callback = new Callback() { | |
public void onComplete(AsyncResult result) { | |
try { | |
StringWriter writer = new StringWriter(); | |
result.serializeWithCache(new OMOutput(XMLOutputFactory.newInstance() | |
.createXMLStreamWriter(writer))); | |
writer.flush(); | |
System.out.println(writer.toString()); | |
} catch (XMLStreamException e) { | |
onError(e); | |
} | |
} | |
public void onError(Exception e) { | |
e.printStackTrace(); | |
} | |
}; | |
//Non-Blocking Invocation | |
serviceClinet.sendReceiveNonBlocking(payload, callback); | |
//Wait till the callback receives the response. | |
while (!callback.isComplete()) { | |
Thread.sleep(1000); | |
} | |
serviceClinet.finalizeInvoke(); | |
} catch (AxisFault axisFault) { | |
axisFault.printStackTrace(); | |
} catch (Exception ex) { | |
ex.printStackTrace(); | |
}</pre> | |
<p><font color="#0000ff"><font color="#000000">The boolean flag (value true) | |
in the "<b>options.setUseSeparateListener(...)</b>" method informs the Axis2 | |
engine to use separate transport connections for request and response. | |
Finally "<b>serviceClinet.finalizeInvoke()</b>" informs the Axis2 engine to | |
stop the client side listener started to retrieve the | |
response.</font></font></p> | |
<p>Before we run the sample client we have one more step to perform. As | |
mentioned earlier Axis2 uses addressing based correlation mechanism, hence we | |
need to "engage" addressing module in the server side as well. According to | |
the Axis2 architecture, addressing module put its handlers in the | |
"<strong>pre-dispatch</strong>" phase (See <a | |
href="Axis2ArchitectureGuide.html" target="_blank">Architecture Guide</a> for | |
more details about phases) and hence "engaging" means simply adding module | |
reference in the "axis2.xml" (NOT the "services.xml"). Now add the following | |
line to the "axis2.xml" that you can find in the "/webapps/axis2/WEB-INF" | |
directory in the servlet container. </p> | |
<pre style="margin-bottom: 0.2in"> <module ref="addressing"/></pre> | |
<p>Note: <font color="#000000">Once you change the "axis2.xml" you need to | |
restart the servlet container.</font></p> | |
<p>This will enable the addressing in the server side. Now you can test the | |
"TestEchoNonBlockingDualClient" using the "testEchoNonBlockingDualClient" | |
target of the ant file found at "Axis2Home/samples" directory. If you see the | |
response OMElement printed in the client side, then you have successfully | |
tested the Non Blocking API with two transport channels at the client | |
side.</p> | |
<h4><a name="EchoBlockingDualClient">EchoBlockingDualClient</a></h4> | |
<p>This is again a Two-Way transport request/response client, but this time, | |
we use a Blocking API in the client code. Sample code for this can be found | |
in the "Axis2Home/samples/userguide/src/userguide/clients/" directory and the | |
explanation is similar to the <a | |
href="#EchoNonBlockingDualClient">EchoNonBlockingDualClient</a>, except that | |
here we do not use a callback object to handle response. This is a very | |
useful mechanism when the service invocation is IN-OUT in nature and the | |
transports are One-Way (e.g. SMTP). For the sample client we use two HTTP | |
connections for request and response. User can test this client using the | |
"echoBlockingDualClient" target of the ant build file found in the | |
"Axis2Home/samples" directory.</p> | |
<p>See <a href="http-transport.html" target="_blank">Configuring | |
Transports</a> for use different transports.</p> | |
<h3><a | |
name="Writing_Web_Service_Clients_using_Code_Generation_with_Data_Binding_Support">Writing | |
Web Service Clients using Code Generation with Data Binding Support</a></h3> | |
<p>Axis2 provides the data binding support for Web Service client as well. | |
The user can generate the required stubs from a given WSDL with the other | |
supporting classes. Let's generate stubs for the WSDL used earlier to | |
generate the skeleton for the "Axis2SampleDocLitPortType". Simply run the | |
WSDL2Java tool that can be found in the bin directory of the Axis2 | |
distribution using the following command:</p> | |
<pre style="margin-bottom: 0.2in">WSDL2Java -uri ..\samples\wsdl\Axis2SampleDocLit.wsdl -o ..\samples\src -p org.apache.axis2.userguide</pre> | |
<p>This will generate the required stub "Axis2SampleDocLitPortTypeStub.java" | |
that can be used to invoke the Web Service Axis2SampleDocLitPortType. Let's | |
see how we can use this stub to write Web Service clients to utilize the Web | |
Service Axis2SampleDocLitPortType (the service that we have already | |
deployed).</p> | |
<h4><a name="Client_for_echoVoid_Operation">Client for echoVoid | |
Operation</a></h4> | |
<p>Following code fragment shows the necessary code for utilizing the | |
echoVoid operation of the Axis2SampleDocLitPortType that we have already | |
deployed. In this operation, a blank SOAP body element is sent to the Web | |
Service and the same SOAP envelope is echoed back.</p> | |
<pre> try { | |
//Create the stub by passing the AXIS_HOME and target EPR. | |
//We pass null to the AXIS_HOME and hence the stub will use the current directory as the AXIS_HOME | |
Axis2SampleDocLitPortTypeStub stub = new Axis2SampleDocLitPortTypeStub(null, | |
"http://localhost:8080/axis2/services/Axis2SampleDocLitPortType"); | |
stub.echoVoid(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
}</pre> | |
<h4><a name="Client_for_echoString_Operation">Client for echoString | |
Operation</a></h4> | |
<p>Following code fragment shows the necessary code for utilizing the | |
echoString operation of the Axis2SampleDocLitPortType that we have already | |
deployed. The code is very simple to understand and the explanations are in | |
the form of comments.</p> | |
<pre>try { | |
//Create the stub by passing the AXIS_HOME and target EPR. | |
//We pass null to the AXIS_HOME and hence the stub will use the current directory as the AXIS_HOME | |
Axis2SampleDocLitPortTypeStub stub= new Axis2SampleDocLitPortTypeStub(null, | |
"http://localhost:8080/axis2/services/Axis2SampleDocLitPortType"); | |
//Create the request document to be sent. | |
EchoStringParamDocument reqDoc= EchoStringParamDocument.Factory.newInstance(); | |
reqDoc.setEchoStringParam("Axis2 Echo"); | |
//invokes the web service. | |
EchoStringReturnDocument resDoc=stub.echoString(reqDoc); | |
System.out.println(resDoc.getEchoStringReturn()); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
}</pre> | |
<p>Similarly following code fragments show client side code for | |
echoStringArray operation and echoStruct operation respectively.</p> | |
<h4><a name="Client_for_echoStringArray_Operation">Client for echoStringArray | |
Operation</a></h4> | |
<pre>try { | |
//Create the stub by passing the AXIS_HOME and target EPR. | |
//We pass null to the AXIS_HOME and hence the stub will use the current directory as the AXIS_HOME | |
Axis2SampleDocLitPortTypeStub stub = new Axis2SampleDocLitPortTypeStub(null, | |
"http://localhost:8080/axis2/services/Axis2SampleDocLitPortType"); | |
//Create the request document to be sent. | |
EchoStringArrayParamDocument reqDoc = EchoStringArrayParamDocument.Factory.newInstance(); | |
ArrayOfstringLiteral paramArray = ArrayOfstringLiteral.Factory.newInstance(); | |
paramArray.addString("Axis2"); | |
paramArray.addString("Echo"); | |
reqDoc.setEchoStringArrayParam(paramArray); | |
EchoStringArrayReturnDocument resDoc = stub.echoStringArray(reqDoc); | |
//Get the response params | |
String[] resParams = resDoc.getEchoStringArrayReturn().getStringArray(); | |
for (int i = 0; i < resParams.length; i++) { | |
System.out.println(resParams[i]); | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
}</pre> | |
<h4><a name="Client_for_echoStruct_Operation">Client for echoStruct | |
Operation</a></h4> | |
<pre>try { | |
//Create the stub by passing the AXIS_HOME and target EPR. | |
//We pass null to the AXIS_HOME and hence the stub will use the current directory as the AXIS_HOME | |
Axis2SampleDocLitPortTypeStub stub = new Axis2SampleDocLitPortTypeStub(null, | |
"http://localhost:8080/axis2/services/Axis2SampleDocLitPortType"); | |
//Create the request Document | |
EchoStructParamDocument reqDoc = EchoStructParamDocument.Factory.newInstance(); | |
//Create the complex type | |
SOAPStruct reqStruct = SOAPStruct.Factory.newInstance(); | |
reqStruct.setVarFloat(100.50F); | |
reqStruct.setVarInt(10); | |
reqStruct.setVarString("High"); | |
reqDoc.setEchoStructParam(reqStruct); | |
//Service invocation | |
EchoStructReturnDocument resDoc = stub.echoStruct(reqDoc); | |
SOAPStruct resStruct = resDoc.getEchoStructReturn(); | |
System.out.println("floot Value :" + resStruct.getVarFloat()); | |
System.out.println("int Value :" + resStruct.getVarInt()); | |
System.out.println("String Value :" + resStruct.getVarString()); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
}</pre> | |
<p align="right"><a href="userguide2.html"><img src="images/arrow_left.gif"> | |
Previous</a> | <a href="userguide4.html">Next <img | |
src="images/arrow_right.gif"></a></p> | |
<p>Pages: <a href="userguide.html">Content</a>, <a | |
href="userguide1.html">1</a>, <a href="userguide2.html">2</a>, <b>3</b>, <a | |
href="userguide4.html">4</a>, <a href="userguide5.html">5</a></p> | |
</body> | |
</html> |