<html> | |
<head> | |
<meta http-equiv="content-type" content=""> | |
<title></title> | |
<link href="../css/axis-docs.css" rel="stylesheet" type="text/css" media="all" /> | |
</head> | |
<body> | |
<a name="Web_Service_Clients_Using_Axis2"></a> | |
<h1>Writing Web Service Clients Using Axis2's Primary APIs</h1> | |
<p>This section presents complex yet powerful <strong>XML based client | |
API</strong> which is intended for advanced users. However if you are a new | |
user we recommend using code generation given in the <a | |
href="userguide.html">user guide</a>.</p> | |
<p>Web services can be used to provide a wide-range of functionality to the | |
user from simple, less time consuming operations such as "getStockQuote" to | |
time consuming business services. When we utilize (invoke using client | |
applications) these Web services we cannot use simple generic invocation | |
paradigms that suite 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 an IN-OUT operation that takes a long time to | |
complete, then most often 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 into play | |
when we need them. Let's try to analyze some common service invocation | |
paradigms.</p> | |
<p>Many Web service engines provide 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 the 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 Non-Blocking API as <b>API Level | |
Asynchrony.</b></p> | |
<p>Both these mechanisms use single transport connections to send the request | |
and to receive the response. They severely lag the capability of using two | |
transport connections for the request and the response (either One-Way or | |
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 two separate | |
transport connections for request and response. The asynchronous behavior | |
that we gain using this solution can be called <b>Transport Level | |
Asynchrony</b>.</p> | |
<p>By <strong>combining API Level Asynchrony & Transport Level | |
Asynchrony</strong> 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>The simplest and more 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. Non 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>Following section present clients that use different possibilities | |
presented above to invoke a Web Service using <code>ServiceClient</code>s. | |
All samples mentioned in this guide are located at the <b><font | |
color="#000000">"samples\userguide\src"</font></b> directory of the binary | |
distribution.</p> | |
<p>This section presents four types of clients.</p> | |
<ol> | |
<li>Request-Response, Blocking Client</li> | |
<li>One Way Client</li> | |
<li>Request-Response, Non-Blocking that uses one transport connection</li> | |
<li>Request-Response, Non-Blocking that uses two transport connections</li> | |
</ol> | |
<a name="EchoBlockingClient"></a> | |
<h4>Request-Response, Blocking Client</h4> | |
<p>Axis2 provides the user with several invocation patterns for Web services, | |
ranging from pure blocking single channel invocations to 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: rgb(36, 193, 19);"> | |
Options options = new Options(); | |
options.setTo(targetEPR); // this sets the location of MyService service | |
ServiceClient serviceClient = new ServiceClient(); | |
serviceClient.setOptions(options); | |
OMElement result = serviceClient.sendReceive(payload); | |
</span> | |
System.out.println(result); | |
} catch (AxisFault axisFault) { | |
axisFault.printStackTrace(); | |
} | |
}</pre> | |
</source> | |
<p>1. The lines highlighted in green lines show the set of operations that | |
you need to perform in order to invoke a Web service.</p> | |
<p>2. The rest is used to create the OMElement that needs to be sent and | |
display the response OMElement.</p> | |
<p>To test this client, use the provided ant build file that can be found in | |
the "<strong>Axis2_HOME/samples/userguide</strong>" directory. Run the | |
"run.client.blocking" target. If you can see the response OMElement printed | |
in your command line, then you have successfully tested the client.</p> | |
<a name="PingClient"></a> | |
<h4>One Way Client</h4> | |
<p>In the Web service "MyService" we had an IN-ONLY operation with the name | |
"ping" (see <a href="userguide.html#Web_Services_Using_Axis2">Creating a New Web Service</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 block 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 an IN-ONLY operation we can directly use the | |
<code>fireAndForget()</code> in ServiceClient to invoke this operation. This | |
will not block the invocation and will return the control immediately back to | |
the client. You can test this client by running the target "run.client.ping" | |
of the ant build file at "<strong>Axis2Home/samples/userguide</strong>".</p> | |
<p>We have now invoked the two operations in our service. Are we done? No! | |
There's a lot more to explore. Let's see some other ways to invoke the same | |
operations.</p> | |
<a name="EchoNonBlockingClient"></a> | |
<h4>Request-Response, Non-Blocking that uses one transport connection</h4> | |
<p>In the "EchoBlockingClient" once the | |
<code>serviceClient.sendReceive(payload);</code> is called, the client is | |
blocked till the operation is complete. This behavior is not desirable when | |
there are many Web service invocations to be done in a single client | |
application or within a GUI. 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 | |
"<strong>Axis2_HOME/samples/userguide/src/userguide/clients</strong>" with | |
the name "EchoNonBlockingClient". If we consider the changes that users 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. The 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 | |
invocation and provide users 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 | |
<code>run.client.nonblocking</code> target of the ant file found at the | |
"<strong>Axis2_HOME/samples/userguide</strong>" directory.</p> | |
<a name="EchoNonBlockingDualClient"></a> | |
<h4>Request-Response, Non-Blocking that uses two transport connections</h4> | |
<p>The solution provided by the Non-Blocking API has one limitation when it | |
comes to Web service invocations which take a long time to complete. The | |
limitation is due to the use of single transport connections to invoke the | |
Web service and to retrieve the response. In other words, client API provides | |
a non blocking invocation mechanism for users, but the request and the | |
response come 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/2002/ws/addr/" 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 uses 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(); | |
options.setTo(targetEPR); | |
options.setTransportInProtocol(Constants.TRANSPORT_HTTP); | |
options.setUseSeparateListener(true); | |
options.setAction("urn:echo"); // this is the action mapping we put within the service.xml | |
//Callback to handle the response | |
Callback callback = new Callback() { | |
public void onComplete(AsyncResult result) { | |
System.out.println(result.getResponseEnvelope()); | |
} | |
public void onError(Exception e) { | |
e.printStackTrace(); | |
} | |
}; | |
//Non-Blocking Invocation | |
sender = new ServiceClient(); | |
sender.engageModule(new QName(Constants.MODULE_ADDRESSING)); | |
sender.setOptions(options); | |
sender.sendReceiveNonBlocking(payload, callback); | |
//Wait till the callback receives the response. | |
while (!callback.isComplete()) { | |
Thread.sleep(1000); | |
} | |
//Need to close the Client Side Listener. | |
} catch (AxisFault axisFault) { | |
axisFault.printStackTrace(); | |
} catch (Exception ex) { | |
ex.printStackTrace(); | |
} finally { | |
try { | |
sender.cleanup(); | |
} catch (AxisFault axisFault) { | |
//have to ignore this | |
} | |
}</pre> | |
<p>The boolean flag (value true) in the | |
<b><code>options.setUseSeparateListener(...)</code></b> method informs the | |
Axis2 engine to use separate transport connections for request and response. | |
Finally <b><code>sender.cleanup()</code></b> informs the Axis2 engine to stop | |
the client side listener started to retrieve the response.</p> | |
<p>To run the sample client ("EchoNonBlockingDualClient") you can simply use | |
the "run.client.nonblockingdual" target of the ant file found at the | |
"<strong>Axis2_HOME/samples/userguide/</strong>" directory.</p> | |
</body> | |
</html> |