| <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
| "http://www.w3.org/TR/html4/loose.dtd"> |
| <html> |
| <head> |
| <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"> |
| <title>Axis2 User's Guide</title> |
| <meta name="generator" content="amaya 9.2.1, see http://www.w3.org/Amaya/"> |
| </head> |
| |
| <body lang="en-US" dir="ltr"> |
| <h4><a name="Axis2_User's_Guide">Axis2 User's Guide</a></h4> |
| |
| <p><i>Version 0.94</i></p> |
| <i>User Feedback: <a |
| href="mailto:axis-user@ws.apache.org">axis-user@ws.apache.org</a></i> |
| |
| <p align="right">Pages: <a href="userguide.html">Content</a>, <a |
| href="userguide1.html">1</a>, <a href="userguide2.html">2</a>, <b>3</b>, <a |
| href="userguide4.html">4</a>, <a href="userguide5.html">5</a></p> |
| |
| <p><b><font size="4">Note (on samples):</font></b> In this page of the user's |
| guide we will look at how to write Web Service Clients using Axis2. All the |
| user's guide samples are located at the <b><font |
| color="#000000">"samples/userguide/src"</font></b> directory of the binary |
| distribution. So... let's explore the samples.</p> |
| |
| <h2><a name="Web_Service_Clients_Using_Axis2">Web Service Clients Using |
| Axis2</a></h2> |
| |
| <p>Now let's see how we can write a Web Service Client to use this Web |
| Service.</p> |
| |
| <p>Web services can be used to provide wide range of functionality to the |
| users ranging from simple, less time consuming operations such as |
| "getStockQuote" to time consuming business services. When we utilize (invoke |
| using client applications) these Web Service we cannot use some simple |
| generic invocation paradigm that suites 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 and IN-OUT operation that take |
| long time to complete, then most of the time 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 in to play when we need them. Let's try to analyze some common |
| service invocation paradigms.</p> |
| |
| <p>Many web service engines provide the 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 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 <strong>Non-Blocking API</strong> as |
| <b>API Level Asynchrony.</b></p> |
| |
| <p>Both these mechanisms use single transport connection to send the request |
| and to receive the response. They severely lags the capability of using two |
| transport connections for the request and the response (either One-Way of |
| 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 <strong>two |
| separate transport connections for request and response</strong>. The |
| asynchronous behavior that we gain using this solution can be called |
| <b>Transport Level Asynchrony</b>.</p> |
| |
| <p>By combining API Level Asynchrony & Transport Level Asynchrony 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>Simplest and the 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. No 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>Below we describe how to write Web Services Clients using Axis2. This can |
| be done in two methods:</p> |
| <ol> |
| <li><a href="#Writing_Web_Service_Clients_using_Axis2's_Primary_APIs">Using |
| the Axis2's primary APIs</a></li> |
| <li><p><a |
| href="#Writing_Web_Service_Clients_using_Code_Generation_with_Data_Binding_Support">Using |
| stubs generated with data binding support</a>, making the life easy for |
| developers writing Web Service client applications</p> |
| </li> |
| </ol> |
| |
| <h3><a name="Writing_Web_Service_Clients_using_Axis2's_Primary_APIs">Writing |
| Web Service Clients Using Axis2's Primary APIs</a></h3> |
| |
| <h4><a name="EchoBlockingClient">EchoBlockingClient</a></h4> |
| |
| <p>Axis2 provides the user with several invocation patterns for Web Services, |
| ranging from pure blocking single channel invocations to a 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: #24C113"> |
| Options options = new Options(); |
| options.setTo(targetEPR); |
| options.setListenerTransportProtocol(Constants.TRANSPORT_HTTP); |
| options.setUseSeparateListener(false); |
| |
| ServiceClient serviceClient = new ServiceClient(); |
| serviceClient.setOptions(options); |
| |
| OMElement result = sender.sendReceive(payload); |
| </span> |
| StringWriter writer = new StringWriter(); |
| result.serializeWithCache(new OMOutput(XMLOutputFactory.newInstance().createXMLStreamWriter(writer))); |
| writer.flush(); |
| |
| System.out.println(writer.toString()); |
| |
| } catch (AxisFault axisFault) { |
| axisFault.printStackTrace(); |
| } catch (XMLStreamException e) { |
| e.printStackTrace(); |
| } |
| }</pre> |
| </source> |
| |
| <p>The green lines shows the set of operations that you need to perform |
| inorder to invoke a web service. The rest is used to create the OMElement |
| that needs to be sent and display the response OMElement. To test this |
| client, use the provided ant build file that can be found in the |
| "Axis2Home/samples" directory. Run the "testEchoBlockingClient" target . If |
| you can see the response OMElement printed in your command line, then you |
| have successfully tested the client. </p> |
| |
| <h4><a name="PingClient">PingClient</a></h4> |
| |
| <p>In the Web Service "MyService" we had a IN-ONLY operation with the name |
| "ping" (see <a href="userguide2.html#Web_Services_Using_Axis2">Web Services |
| Using Axis2</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); |
| |
| } |
| catch (AxisFault axisFault) { |
| axisFault.printStackTrace(); |
| }</pre> |
| |
| <p>Since we are accessing a IN-ONLY operation we can directly use the |
| "fireAndForget()" in ServiceClient to invoke this operation , and that will |
| not block the invocation, hence it will return the control immediately back |
| to the client. You can test this client by running the target |
| "testPingClient" of the ant build file at "Axis2Home/samples".</p> |
| |
| <p>We have invoked the two operations in our service. Are we done? No! There |
| are lot more to explore. Let's see some other ways to invoke the same |
| operations...</p> |
| |
| <h4><a name="EchoNonBlockingClient">EchoNonBlockingClient</a></h4> |
| |
| <p>In the EchoBlockingClient once the "serviceCleint.sendReceive(payload);" |
| is called, the client is blocked till the operation is completed. This |
| behavior is not desirable when there are many Web Service invocations to be |
| done in a single client application. 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 |
| "Axis2Home/samples/userguide/src/userguide/clients" with the name |
| EchoNonBlockingClient. If we consider the changes that user 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. 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 |
| invocations and provides the user 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 |
| "testEchoNonBlockingClient" target of the ant file found at the |
| "Axis2Home/samples" directory.</p> |
| |
| <h4><a name="EchoNonBlockingDualClient">EchoNonBlockingDualClient</a></h4> |
| |
| <p>The solution provided by the Non-Blocking API has one limitation when it |
| comes to Web Service invocations which takes long time to complete. The |
| limitation is due to the use of single transport connection to invoke the Web |
| Service and to retrieve the response. In other words, client API provides a |
| non blocking invocation mechanism for the users, but the request and the |
| response comes 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/Submission/ws-addressing/" |
| 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 |
| users 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();<br> options.setTo(targetEPR);<br> options.setListenerTransportProtocol(Constants.TRANSPORT_HTTP); |
| |
| //The boolean flag informs the axis2 engine to use two separate transport connection |
| //to retrieve the response. |
| <br> options.setUseSeparateListener(true); |
| |
| ServiceClient serviceClinet = new ServiceClinet(); |
| <br> serviceClinet.setOptions(options);</pre> |
| <pre> |
| //Callback to handle the response |
| Callback callback = new Callback() { |
| public void onComplete(AsyncResult result) { |
| try { |
| StringWriter writer = new StringWriter(); |
| result.serializeWithCache(new OMOutput(XMLOutputFactory.newInstance() |
| .createXMLStreamWriter(writer))); |
| writer.flush(); |
| |
| System.out.println(writer.toString()); |
| |
| } catch (XMLStreamException e) { |
| onError(e); |
| } |
| } |
| |
| public void onError(Exception e) { |
| e.printStackTrace(); |
| } |
| }; |
| |
| //Non-Blocking Invocation |
| serviceClinet.sendReceiveNonblocking(payload, callback); |
| |
| //Wait till the callback receives the response. |
| while (!callback.isComplete()) { |
| Thread.sleep(1000); |
| } |
| serviceClinet.finalizeInvoke(); |
| |
| } catch (AxisFault axisFault) { |
| axisFault.printStackTrace(); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| }</pre> |
| |
| <p><font color="#0000ff"><font color="#000000">The boolean flag (value true) |
| in the "<b>options.setUseSeparateListener(...)</b>" method informs the Axis2 |
| engine to use separate transport connections for request and response. |
| Finally "<b>serviceClinet.finalizeInvoke()</b>" informs the Axis2 engine to |
| stop the client side listener started to retrieve the |
| response.</font></font></p> |
| |
| <p>Before we run the sample client we have one more step to perform. As |
| mentioned earlier Axis2 uses addressing based correlation mechanism, hence we |
| need to "engage" addressing module in the server side as well. According to |
| the Axis2 architecture, addressing module is deployed in the |
| "<strong>pre-dispatch</strong>" phase (See <a |
| href="Axis2ArchitectureGuide.html" target="_blank">Architecture Guide</a> for |
| more details about phases) and hence "engaging" means simply adding module |
| reference in the "axis2.xml" (NOT the "services.xml"). Now add the following |
| line to the "axis2.xml" that you can find in the "/webapps/axis2/WEB-INF" |
| directory in the servlet container. </p> |
| <pre style="margin-bottom: 0.2in"> <module ref="addressing"/></pre> |
| |
| <p>Note: <font color="#000000">Once you change the "axis2.xml" you need to |
| restart the servlet container.</font></p> |
| |
| <p>This will enable the addressing in the server side. Now you can test the |
| "TestEchoNonBlockingDualClient" using the "testEchoNonBlockingDualClient" |
| target of the ant file found at "Axis2Home/samples" directory. If you see the |
| response OMElement printed in the client side, then you have successfully |
| tested the Non Blocking API with two transport channels at the client |
| side.</p> |
| |
| <h4><a name="EchoBlockingDualClient">EchoBlockingDualClient</a></h4> |
| |
| <p>This is again a Two-Way transport request/response client, but this time, |
| we use a Blocking API in the client code. Sample code for this can be found |
| in the "Axis2Home/samples/userguide/src/userguide/clients/" directory and the |
| explanation is similar to the <a |
| href="#EchoNonBlockingDualClient">EchoNonBlockingDualClient</a>, except that |
| here we do not use a callback object to handle response. This is a very |
| useful mechanism when the service invocation is IN-OUT in nature and the |
| transports are One-Way (e.g. SMTP). For the sample client we use two HTTP |
| connections for request and response. User can test this client using the |
| "echoBlockingDualClient" target of the ant build file found in the |
| "Axis2Home/samples" directory.</p> |
| |
| <p>See <a href="http-transport.html" target="_blank">Configuring |
| Transports</a> for use different transports.</p> |
| |
| <h3><a |
| name="Writing_Web_Service_Clients_using_Code_Generation_with_Data_Binding_Support">Writing |
| Web Service Clients using Code Generation with Data Binding Support</a></h3> |
| |
| <p>Axis2 provides the data binding support for Web Service client as well. |
| The user can generate the required stubs from a given WSDL with the other |
| supporting classes. Let's generate stubs for the WSDL used earlier to |
| generate the skeleton for the "Axis2SampleDocLitPortType". Simply run the |
| WSDL2Java tool that can be found in the bin directory of the Axis2 |
| distribution using the following command:</p> |
| <pre style="margin-bottom: 0.2in">WSDL2Java -uri ..\samples\wsdl\Axis2SampleDocLit.wsdl -o ..\samples\src -p org.apache.axis2.userguide</pre> |
| |
| <p>This will generate the required stub "Axis2SampleDocLitPortTypeStub.java" |
| that can be used to invoke the Web Service Axis2SampleDocLitPortType. Let's |
| see how we can use this stub to write Web Service clients to utilize the Web |
| Service Axis2SampleDocLitPortType (the service that we have already |
| deployed).</p> |
| |
| <h4><a name="Client_for_echoVoid_Operation">Client for echoVoid |
| Operation</a></h4> |
| |
| <p>Following code fragment shows the necessary code for utilizing the |
| echoVoid operation of the Axis2SampleDocLitPortType that we have already |
| deployed. In this operation, a blank SOAP body element is sent to the Web |
| Service and the same SOAP envelope is echoed back.</p> |
| <pre> try { |
| //Create the stub by passing the AXIS_HOME and target EPR. |
| //We pass null to the AXIS_HOME and hence the stub will use the current directory as the AXIS_HOME |
| Axis2SampleDocLitPortTypeStub stub = new Axis2SampleDocLitPortTypeStub(null, |
| "http://localhost:8080/axis2/services/Axis2SampleDocLitPortType"); |
| stub.echoVoid(); |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| }</pre> |
| |
| <h4><a name="Client_for_echoString_Operation">Client for echoString |
| Operation</a></h4> |
| |
| <p>Following code fragment shows the necessary code for utilizing the |
| echoString operation of the Axis2SampleDocLitPortType that we have already |
| deployed. The code is very simple to understand and the explanations are in |
| the form of comments.</p> |
| <pre>try { |
| //Create the stub by passing the AXIS_HOME and target EPR. |
| //We pass null to the AXIS_HOME and hence the stub will use the current directory as the AXIS_HOME |
| Axis2SampleDocLitPortTypeStub stub= new Axis2SampleDocLitPortTypeStub(null, |
| "http://localhost:8080/axis2/services/Axis2SampleDocLitPortType"); |
| //Create the request document to be sent. |
| EchoStringParamDocument reqDoc= EchoStringParamDocument.Factory.newInstance(); |
| reqDoc.setEchoStringParam("Axis2 Echo"); |
| //invokes the web service. |
| EchoStringReturnDocument resDoc=stub.echoString(reqDoc); |
| System.out.println(resDoc.getEchoStringReturn()); |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| }</pre> |
| |
| <p>Similarly following code fragments show client side code for |
| echoStringArray operation and echoStruct operation respectively.</p> |
| |
| <h4><a name="Client_for_echoStringArray_Operation">Client for echoStringArray |
| Operation</a></h4> |
| <pre>try { |
| //Create the stub by passing the AXIS_HOME and target EPR. |
| //We pass null to the AXIS_HOME and hence the stub will use the current directory as the AXIS_HOME |
| Axis2SampleDocLitPortTypeStub stub = new Axis2SampleDocLitPortTypeStub(null, |
| "http://localhost:8080/axis2/services/Axis2SampleDocLitPortType"); |
| |
| //Create the request document to be sent. |
| EchoStringArrayParamDocument reqDoc = EchoStringArrayParamDocument.Factory.newInstance(); |
| ArrayOfstringLiteral paramArray = ArrayOfstringLiteral.Factory.newInstance(); |
| |
| paramArray.addString("Axis2"); |
| paramArray.addString("Echo"); |
| |
| reqDoc.setEchoStringArrayParam(paramArray); |
| EchoStringArrayReturnDocument resDoc = stub.echoStringArray(reqDoc); |
| |
| //Get the response params |
| String[] resParams = resDoc.getEchoStringArrayReturn().getStringArray(); |
| |
| for (int i = 0; i < resParams.length; i++) { |
| System.out.println(resParams[i]); |
| } |
| } catch (Exception e) { |
| e.printStackTrace(); |
| }</pre> |
| |
| <h4><a name="Client_for_echoStruct_Operation">Client for echoStruct |
| Operation</a></h4> |
| <pre>try { |
| //Create the stub by passing the AXIS_HOME and target EPR. |
| //We pass null to the AXIS_HOME and hence the stub will use the current directory as the AXIS_HOME |
| Axis2SampleDocLitPortTypeStub stub = new Axis2SampleDocLitPortTypeStub(null, |
| "http://localhost:8080/axis2/services/Axis2SampleDocLitPortType"); |
| //Create the request Document |
| EchoStructParamDocument reqDoc = EchoStructParamDocument.Factory.newInstance(); |
| |
| //Create the complex type |
| SOAPStruct reqStruct = SOAPStruct.Factory.newInstance(); |
| |
| reqStruct.setVarFloat(100.50F); |
| reqStruct.setVarInt(10); |
| reqStruct.setVarString("High"); |
| |
| reqDoc.setEchoStructParam(reqStruct); |
| |
| //Service invocation |
| EchoStructReturnDocument resDoc = stub.echoStruct(reqDoc); |
| SOAPStruct resStruct = resDoc.getEchoStructReturn(); |
| |
| System.out.println("floot Value :" + resStruct.getVarFloat()); |
| System.out.println("int Value :" + resStruct.getVarInt()); |
| System.out.println("String Value :" + resStruct.getVarString()); |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| }</pre> |
| |
| <p align="right"><a href="userguide2.html"><img src="images/arrow_left.gif"> |
| Previous</a> | <a href="userguide4.html">Next <img |
| src="images/arrow_right.gif"></a></p> |
| |
| <p>Pages: <a href="userguide.html">Content</a>, <a |
| href="userguide1.html">1</a>, <a href="userguide2.html">2</a>, <b>3</b>, <a |
| href="userguide4.html">4</a>, <a href="userguide5.html">5</a></p> |
| </body> |
| </html> |