<!--
  ~ 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
  ~
  ~ http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing,
  ~ software distributed under the License is distributed on an
  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  ~ KIND, either express or implied. See the License for the
  ~ specific language governing permissions and limitations
  ~ under the License.
  -->

<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 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>
<ul>
  <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>
  <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>
  </li>
</ul>

<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
Asynchrony.</b></p>

<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
Asynchrony</b>.</p>

<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>

<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 most 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 Request-Response
        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 at the API level and also at the transport
        level.</p>
      </td>
    </tr>
  </tbody>
</table>

<p>Axis2 provides the user with all these possibilities to invoke Web
services.</p>

<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>
<ol>
  <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>
</ol>
<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>
<source>
<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();
      serviceClient.setOptions(options);

      OMElement result = serviceClient.sendReceive(payload);
      </span>
      System.out.println(result);
   } catch (AxisFault axisFault) {
      axisFault.printStackTrace();
   } 
}</pre>
</source>
<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>
<pre> 
   try {
      OMElement payload = ClientUtil.getPingOMElement();
      Options options = new Options();
      options.setTo(targetEPR);
      ServiceClient serviceClient = new ServiceClient();
      serviceClient.setOptions(options);
      serviceClient.fireAndForget(payload);
      /**
       * 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.
       */
      Thread.sleep(500);
   } catch (AxisFault axisFault) {
      axisFault.printStackTrace();
   }
</pre>

<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
"run.client.ping" of the Ant build file at
"<strong>Axis2Home/samples/userguide</strong>".</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 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="http://www.w3.org/2002/ws/addr/" target="_blank">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>
<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);            
      }               
   } catch (AxisFault axisFault) {            
     axisFault.printStackTrace();
   } catch (Exception ex) {
     ex.printStackTrace();
   } finally {
      try {
         //Close the Client Side Listener.
         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 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
response.</p>

<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>
</body>
</html>
