| <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="adv-userguide.html">Advance User's 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="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 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> |