blob: 95466aba8cf404a34305938f2ca059259bab2bbb [file] [log] [blame]
~ Licensed to the Apache Software Foundation (ASF) under one
~ or more contributor license agreements. See the NOTICE file
~ distributed with this work for additional information
~ regarding copyright ownership. The ASF licenses this file
~ to you under the Apache License, Version 2.0 (the
~ "License"); you may not use this file except in compliance
~ with the License. You may obtain a copy of the License at
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
<meta http-equiv="content-type" content=""/>
<a name="Web_Service_Clients_Using_Axis2"></a>
<h1>Writing Web Service Clients Using Axis2's Primary APIs</h1>
<p>This section presents a 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="adv-userguide.html">Advanced User's Guide</a>.</p>
<p>Web services can be used to provide a wide-range of functionality to the
user from simple, quick operations such as "getStockQuote" to time consuming
business services. When we utilize (invoke using client applications) these
Web services, we cannot always 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". Further, 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 Blocking and Non-Blocking
client APIs.</p>
<li><p style="margin-bottom: 0in"><b>Blocking API</b> - Once the service
invocation is called, the client application hangs, regaining control
only 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><p><b>Non-Blocking API </b>- This is a callback or polling based API.
Here, once a service invocation is called, the client application
immediately regains control and the response is retrieved using the
callback object provided. This approach allows the
client application to invoke several Web services simultaneously without
needing to wait for the response of previous operations.</p>
<p>Both these mechanisms work at the API level. Let's name the asynchronous
behavior that we can get using the Non-Blocking API as <b>API Level
<p>Both 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, as the transport connection may still 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
<p>By <strong>combining API Level Asynchrony and 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>
<td width="33%" height="19"><p><strong>API
<td width="33%"><p><strong>Dual Transports (Yes/No)</strong></p>
<td width="33%"><p><strong>Description</strong></p>
<td width="33%" height="19"><p>Blocking</p>
<td width="33%"><p>No</p>
<td width="33%"><p>The simplest and most familiar invocation pattern</p>
<td width="33%" height="19"><p>Non-Blocking</p>
<td width="33%"><p>No</p>
<td width="33%"><p>Using callbacks or polling</p>
<td width="33%" height="19"><p>Blocking</p>
<td width="33%"><p>Yes</p>
<td width="33%"><p>This is useful when the service operation is Request-Response
in nature but the transport used is One-Way (e.g. SMTP)</p>
<td width="33%" height="19"><p>Non-Blocking</p>
<td width="33%"><p>Yes</p>
<td width="33%"><p>This is can be used to gain the maximum asynchronous
behavior. Non blocking at the API level and also at the transport
<p>Axis2 provides the user with all these possibilities to invoke Web
<p>The following section presents clients that use some of the different
possibilities presented above to invoke a Web Service using
<code>ServiceClient</code>s. All the 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>
<li>Request-Response, Blocking Client</li>
<li>One Way Client, Non-Blocking</li>
<li>Request-Response, Non-Blocking that uses one transport connection</li>
<li>Request-Response, Non-Blocking that uses two transport connections</li>
<a name="EchoBlockingClient"></a>
<h4>Request-Response, Blocking Client</h4>
<p>The client code below will invoke the "echo" operation of
"MyService" using a pure blocking single-channel invocation.</p>
<pre> try {
<span style="color: rgb(36, 193, 19);">
OMElement payload = ClientUtil.getEchoOMElement();
Options options = new Options();
options.setTo(targetEPR); // this sets the location of MyService service
ServiceClient serviceClient = new ServiceClient();
OMElement result = serviceClient.sendReceive(payload);
} catch (AxisFault axisFault) {
<p>The lines highlighted in green show the set of operations that you need
to perform in order to invoke the Web service in this manner.</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, Non-Blocking</h4>
<p>In the Web service "MyService", we had an IN-ONLY operation with the name
"ping" (see <a href="adv-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>
try {
OMElement payload = ClientUtil.getPingOMElement();
Options options = new Options();
ServiceClient serviceClient = new ServiceClient();
* We need to wait some time for the message to be sent. Otherwise,
* if we immediately exit this function using the main thread,
* the request won't be sent.
} catch (AxisFault axisFault) {
<p>Since we are calling an IN-ONLY web service, we can directly use the
<code>fireAndForget()</code> in the 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
"" of the Ant build file at
<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
<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 the developer 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 developer is expected to override the onComplete() and onError() methods
of their Callback subclass. The Axis2 engine calls the onComplete()
method once the Web service response is received by the Axis2 Client API
(ServiceClient). This eliminates the blocking nature of the web service
request-response invocation.</p>
<p>To run the sample client ("EchoNonBlockingClient") you can simply use the
<code>run.client.nonblocking</code> target of the Ant file found in 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 above by the Non-Blocking API has one limitation when it
comes to Web service invocations that take a long time to complete. The
limitation is due to the use of single transport connections to invoke the
Web service and retrieve the response. In other words, the client API provides a
non-blocking invocation mechanism for developers, but the request and the response
still come in a single transport (Two-Way transport) connection like HTTP. Long
running Web service invocations or Web service invocations using One-Way
transports such as SMTP cannot be utilized by simply using a non-blocking
API invocation.</p>
<p>The simplest 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, however, is subsequently correlating each request with its response.
<a href="">WS-Addressing</a>
provides a neat solution to this using &lt;wsa:MessageID&gt; and
&lt;wsa:RelatesTo&gt; headers. Axis2 provides support for an addressing based
correlation mechanism and a complying Client API to invoke Web services with
two transport connections. (The core of Axis2 does not depend on
WS-Addressing, but contains a set of parameters, like in addressing, that can
be populated by any method. WS-Addressing is one of the uses that may
populate them. Even the transports can populate them. Hence, Axis2 has the
flexibility to use different addressing standards.)</p>
<p>Users can select between Blocking and 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. The 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>
try {
OMElement payload = ClientUtil.getEchoOMElement();
Options options = new Options();
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) {
public void onError(Exception e) {
//Non-Blocking Invocation
sender = new ServiceClient();
sender.engageModule(new QName(Constants.MODULE_ADDRESSING));
sender.sendReceiveNonBlocking(payload, callback);
//Wait till the callback receives the response.
while (!callback.isComplete()) {
} catch (AxisFault axisFault) {
} catch (Exception ex) {
} finally {
try {
//Close the Client Side Listener.
} catch (AxisFault axisFault) {
//have to ignore this
<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 the request and
response. Finally <b><code>sender.cleanup()</code></b> informs the Axis2
engine to stop the client side listener, which started to retrieve the
<p>To run the sample client ("EchoNonBlockingDualClient") you can simply use
the "run.client.nonblockingdual" target of the Ant file found in the
"<strong>Axis2_HOME/samples/userguide/</strong>" directory.</p>