<!--
  ~ 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>
</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>
  <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>
<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>
<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/">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>
