| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
| <html> |
| <head> |
| <meta http-equiv="content-type" content=""> |
| <title>Axis2 User's Guide</title> |
| </head> |
| |
| <body lang="en-US" dir="ltr"> |
| <h1 align="center"><a name="_Toc96697849" id="_Toc96697849">Apache</a> Axis2 |
| User's Guide</h1> |
| |
| <p>This guide will help you get started with Axis2, the next generation of |
| Apache Axis! It describes in details how to write Web services and Web |
| service clients using Axis2; how to write custom modules and how to use them |
| with a Web service. Advanced Topics and Samples which are shipped with the |
| binary distribution of Axis2, are also discussed.</p> |
| |
| <h2>Content</h2> |
| <ul> |
| <li><p><a href="#Introduction">Introduction</a></p> |
| </li> |
| <li><p><a href="#Web_Services_Using_Axis2">Web Services Using Axis2</a></p> |
| <ul> |
| <li><a href="#Getting_started">Getting Started</a></li> |
| <li><a href="#Writing_Web_Services_Using Axis2's_Primary_APIs">Writing |
| Web Services using Axis2 APIs</a> |
| <ul> |
| <li><a href="#How_to_write_the_Web_Service_">How to write the Web |
| Service?</a> |
| <ul> |
| <li><a href="#Step1_:Write_the_Implementation_Class">Step1 |
| :Write the Implementation Class</a></li> |
| <li><a href="#Step2_:Write_the_services_xml_file">Step2 :Write |
| the services.xml file</a></li> |
| <li><a href="#Step3_:Create_the_Web_Service_Archive">Step3 |
| :Create the Web Service Archive</a></li> |
| <li><a href="#Step4_:Deploy_the_Web_Service">Step4 :Deploy the |
| Web Service</a></li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li><p><a |
| href="#Writing_Web_Services_by_Code_Generating_Skeleton">Writing Web |
| Services by Code Generating Skeleton</a></p> |
| <ul> |
| <li><a href="#How_to_write_the_Web_Service_2">How to write the Web |
| Service?</a> |
| <ul> |
| <li><a href="#Step1_:Generate_skeleton">Step 1: Generate |
| Skeleton Code</a></li> |
| <li><a href="#Step2_Implement_Business_Logic">Step2 :Implement |
| Business Logic</a></li> |
| <li><a href="#Step3_:Verify_services_xml">Step3 :Verify |
| services.xml file</a></li> |
| <li><a href="#Step4_Create_archive">Step4 :Create the Web |
| Service Archive file</a></li> |
| <li><a href="#Step5_Deploy_web_service">Step5 :Deploy the Web |
| Service</a></li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| <ul> |
| <li><p><a href="#Web_Service_Clients_Using_Axis2">Web Service Clients Using |
| Axis2</a></p> |
| <ul> |
| <li><a |
| href="#Writing_Web_Service_Clients_using_Axis2's_Primary_APIs">Writing |
| Web Service Clients using Axis2's Primary APIs</a> |
| <ul> |
| <li><a href="#EchoBlockingClient">EchoBlockingClient</a></li> |
| <li><a href="#PingClient">PingClient</a></li> |
| <li><a href="#EchoNonBlockingClient">EchoNonBlockingClient</a></li> |
| <li><a |
| href="#EchoNonBlockingDualClient">EchoNonBlockingDualClient</a></li> |
| <li><a |
| href="#EchoBlockingDualClient">EchoBlockingDualClient</a></li> |
| </ul> |
| </li> |
| <li><p><a |
| href="#Writing_Web_Service_Clients_using_Code_Generation_with_Data_Binding_Support">Writing |
| Web Service Clients using Code Generation with Data Binding |
| Support</a></p> |
| <ul> |
| <!--<li><a href="#Client_for_echoVoid_Operation">Client |
| for echoVoid Operation</a></li>--> |
| <li><a href="#Client_for_echoString_Operation">Client for |
| echoString Operation</a></li> |
| <li><a href="#Client_for_echoStringArray_Operation">Client for |
| echoStringArray Operation</a></li> |
| <li><a href="#Client_for_echoStruct_Operation">Client for |
| echoStruct Operation</a></li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li><p><a href="#Modules">Modules</a></p> |
| <ul> |
| <li><a href="#MyService_with_a_Logging_Module">MyService with a Logging |
| Module</a> |
| <ul> |
| <li><a href="#Step1_:_LoggingModule_Class">Step1 : LoggingModule |
| Class</a></li> |
| <li><a href="#Step2_:_LogHandler">Step2 : LogHandler</a></li> |
| <li><a href="#Step3_:_module_xml">Step3 : module.xml</a></li> |
| <li><a href="#Step_4:_Modify_the_"axis2_xml"">Step 4: |
| Modify the "axis2.xml"</a></li> |
| <li><a href="#Step5_:_Modify_the_"services_xml"">Step5 : |
| Modify the "services.xml"</a></li> |
| <li><a href="#Step6_:_Packaging">Step6 : Packaging</a></li> |
| <li><a href="#Step7_:_Deploy_the_Module_in_Axis2">Step7 : Deploy |
| the Module in Axis2</a></li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li><p><a href="#Other_Samples">Other Samples</a></p> |
| <ul> |
| <li><a href="#Google_Spell_Checker_Sample">Google Spell Checker |
| Sample</a></li> |
| <li><a href="#Google_Search_Sample">Google Search Sample</a></li> |
| <li><a href="#Amazon_Queuing_Service">Amazon Queuing Service</a></li> |
| </ul> |
| </li> |
| <li><p>Advanced Topics</p> |
| <ul> |
| <li><a href="rest-ws.html" target="_blank">RESTful Web Services</a></li> |
| <li><a href="tcp-transport.html" target="_blank">TCP Transport</a></li> |
| <li><a href="mail-transport.html" target="_blank">Mail |
| Transport</a></li> |
| <li><a href="http-transport.html" target="_blank">HTTP |
| Transports</a></li> |
| <li><a href="jms-transport.html" target="_blank">JMS Transports</a></li> |
| <li><a href="mtom-guide.html" target="_blank">MTOM with Axis2</a></li> |
| <li><a href="../modules/wss4j/1_0/security-module.html" |
| target="_blank">Securing SOAP Messages with Apache Rampart</a></li> |
| </ul> |
| </li> |
| </ul> |
| |
| <h2><a name="Introduction">Introduction</a></h2> |
| |
| <p>This User's Guide is written based on <a |
| href="../download/1_1/download.html/#std-bin">Axis2 standard binary |
| distribution</a>. The standard binary distribution can be directly <a |
| href="[preferred]/ws/axis2/1_1/axis2-std-1.1-bin.zip" |
| title="[preferred]/ws/axis2/1_1/axis2-std-1.1-bin.zip">downloaded</a> or |
| built using the <a href="../download/1_1/download.html#src">standard source |
| distribution</a>. If you choose to go for the latter, then <a |
| href="installationguide.html">Installation Guide</a> will instruct you on how |
| to build Axis2 Standard Binary Distribution using the Source.</p> |
| |
| <p>We hope you enjoy using Axis2. Please note that this is an open-source |
| effort. If you feel the code could use some new features or fixes, please get |
| involved and lend us a hand! The Axis developer community welcomes your |
| participation.</p> |
| |
| <p>Let us know what you think! Send your feedback on Axis2 to "<a |
| href="mailto:axis-user@ws.apache.org">axis-user@ws.apache.org</a>". Make sure |
| to prefix the subject of the mail with [Axis2].</p> |
| |
| <h2><a name="Web_Services_Using_Axis2">Web Services Using Axis2</a></h2> |
| |
| <p>In this section, we will learn how to write and deploy Web services using |
| Axis2. All the samples mentioned in this giude are located in the |
| <b>"samples\userguide\src"</b> directory of <a |
| href="../download/1_1/download.html/#std-bin">Axis2 standard binary |
| distribution</a>.</p> |
| |
| <h3><a name="Getting_started">Getting Started</a></h3> |
| |
| <p>Please deploy axis2.war in your servlet container and ensure that it works |
| fine. <a href="installationguide.html" target="_blank">Installation Guide</a> |
| gives you step by step instructions on just how to build axis2.war and deploy |
| it in your servlet container.</p> |
| |
| <p>Users can use either one of the following methods to write Web services |
| using Axis2.</p> |
| <ol> |
| <li><a href="#Writing_Web_Services_Using Axis2's_Primary_APIs">Use Axis2's |
| primary interfaces (APIs) and implement the business logic.</a></li> |
| <li><p><a href="#Writing_Web_Services_by_Code_Generating_Skeleton">Start |
| from the WSDL -> Code generate the Skeleton -> Implement the |
| Business Logic.</a></p> |
| </li> |
| </ol> |
| |
| <p>The complete code of the example Web service - MyService which will be |
| used in this exercise is found in the "Axis2_HOME/samples/userguide/src" |
| directory of Axis2 binary distribution, under "userguide/example1" |
| package.</p> |
| |
| <h3><a name="Writing_Web_Services_Using Axis2's_Primary_APIs">1. Writing Web |
| Services Using Axis2's Primary APIs</a></h3> |
| In our example, the web service will have two operations. |
| <pre>public void ping(OMElement element){} //IN-ONLY operation, just accepts the OMElement and does some processing. |
| public OMElement echo(OMElement element){}//IN-OUT operation, accepts an OMElement and |
| // sends back the same again </pre> |
| |
| <h4><a name="How_to_write_the_Web_Service_">How to write a Web |
| Service?</a></h4> |
| Writing a new Web service with Axis2 involves four steps: |
| <ol> |
| <li><p style="margin-bottom: 0in">Write the Implementation Class</p> |
| </li> |
| <li><p style="margin-bottom: 0in">Write a services.xml file to explain the |
| Web service</p> |
| </li> |
| <li><p style="margin-bottom: 0in">Create a *.aar archive (Axis Archive) for |
| the Web service</p> |
| </li> |
| <li><p style="margin-bottom: 0in">Deploy the Web service</p> |
| </li> |
| </ol> |
| |
| <h4><a name="Step1_:Write_the_Implementation_Class">Step1 :Write the |
| Implementation Class</a></h4> |
| |
| <p>An implementation class has the business logic for the Web service and |
| implements the operations provided by the Web service. Unless you have data |
| binding, the signature of the methods can have only one parameter of type |
| OMElement.</p> |
| |
| <p><span style="color: #FF0000">OMElement is .... </span>For more details see |
| <a href="http://ws.apache.org/commons/axiom/OMTutorial.html">OM |
| Tutorial</a>.</p> |
| <pre>public class MyService{ |
| public void ping(OMElement element){ |
| // Business Logic |
| ...... |
| } |
| public OMElement echo(OMElement element){ |
| ...... |
| } |
| }</pre> |
| |
| <h4><a name="Step2_:Write_the_services_xml_file">Step2 :Write the |
| services.xml file</a></h4> |
| |
| <p>"services.xml" has the configuration for a web Service. Each web service, |
| deployed in Axis2 , must have its configuration in "services.xml". The |
| configuration for MyService is as follows:</p> |
| <pre><service > |
| <description> |
| This is a sample Web service with two operations, echo and ping. |
| </description> |
| <parameter name="ServiceClass" locked="false">userguide.example1.MyService</parameter> |
| <operation name="echo"> |
| <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> |
| <actionMapping>urn:echo</actionMapping> |
| </operation> |
| <operation name="ping"> |
| <messageReceiver class="org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver"/> |
| <actionMapping>urn:ping</actionMapping> |
| </operation> |
| </service></pre> |
| |
| <p><em>The above XML tags can be explained as follows:</em></p> |
| |
| <p>1. The description of the service class is provided in the description |
| tag.</p> |
| <pre><service > |
| <description> |
| This is a sample Web service with two operations, echo and ping. |
| </description></pre> |
| |
| <p>2. The name of the service class is provided as a parameter.</p> |
| <pre><parameter name="serviceClass" locked="false">userguide.example1.MyService</parameter></pre> |
| |
| <p>3. The "operation" xml tag describes the operations that are available in |
| this service with respective message receivers.</p> |
| <pre> <operation name="echo"> |
| <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> |
| <actionMapping>urn:echo</actionMapping> |
| </operation> |
| <operation name="ping"> |
| <messageReceiver class="org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver"/> |
| <actionMapping>urn:ping</actionMapping> |
| </operation></pre> |
| |
| <p>4. Every operation must map to a corresponding MessageReceiver class. |
| After a message is processed by the handlers, Axis2 engine hands it over to a |
| MessageReceiver.</p> |
| |
| <p>5. For the "echo" operation, we have used a |
| <strong>RawXMLINOutMessageReceiver</strong> since it is an IN-OUT operation. |
| For IN-ONLY operation "ping", we have used |
| <strong>RawXMLINOnlyMessageReceiver</strong> as the message receiver.</p> |
| |
| <p>6. The actionMapping is required only if you want to enable WS-Addressing. |
| This will be used later in this user guide.</p> |
| |
| <p>7. You can write a services.xml file to include a group of services |
| instead of a single service. This makes management and deployment of a set of |
| related services very easy. At runtime you can share information between |
| these services within a single interaction using the ServiceGroupContext. If |
| you hope to use this functionality, the services.xml file should have the |
| following format.</p> |
| <pre><serviceGroup> |
| <service name="Service1"> |
| <!-- details for Service1 --> |
| </service> |
| <service name="Service2"> |
| <!-- details for Service2 --> |
| </service> |
| <module ref="ModuleName" /> |
| <parameter name="serviceGroupParam1" locked="false">value 1</parameter> |
| </serviceGroup></pre> |
| |
| <p>Note : name of the service is a compulsory attribute.</p> |
| |
| <h4><a name="Step3_:Create_the_Web_Service_Archive">Step3 : Create the Web |
| Service Archive</a></h4> |
| |
| <p>Axis2 uses ".aar" (Axis Archive) file as the deployment package for Web |
| services. Therefore, for MyService we will use "MyService.aar" with the |
| "services.xml" packaged in the META-INF in directory structure shown below. |
| Please note that the name of the archive file will be same as that of the |
| service only if the services.xml contains only one service element.</p> |
| |
| <p><img src="images/userguide/ServiceItems.jpg" name="Graphic1" |
| align="bottom" width="176" height="91" border="0"></p> |
| |
| <p>To create the archive file, you can create a jar file containing all the |
| necessary files and then rename it to .aar file.This archive file can be |
| found in the "Axis2_HOME/samples/userguide" directory. This file now has to |
| be deployed.</p> |
| |
| <h4><a name="Step4_:Deploy_the_Web_Service">Step4 : Deploy the Web |
| Service</a></h4> |
| |
| <p>The service can be deployed by dropping dropping the ".aar" file in to |
| "services" directory in "/webapps/axis2/WEB-INF" of your servlet container. |
| Start the servlet container (if you have not already started) and check the |
| link "Services" on the <a href="http://localhost:8080/axis2/" |
| target="_blank">Home Page of Axis2 Web Application</a> |
| (http://localhost:8080/axis2) and see whether the MyService is deployed |
| properly. If you can see the following output then you have successfully |
| deployed MyService on Axis2. Congratulations !!</p> |
| |
| <p align="center"><img src="images/userguide/MyServiceDeployed.jpg" |
| name="Graphic2" align="bottom" border="0"></p> |
| |
| <p>Note: Axis2 provides an easy way to deploy Web services using the "Upload |
| Service" tool on Axis2 Web Application's Administration module. Please refer |
| to the <a href="webadminguide.html" target="_blank">Web Administration |
| Guide</a> for more information.</p> |
| |
| <h3><a name="Writing_Web_Services_by_Code_Generating_Skeleton">2. Writing Web |
| Services by Code Generating Skeleton</a></h3> |
| |
| <p>This is the second method of writing Web services using Axis2. In this |
| method, we generate the skeleton from a given WSDL and implement the business |
| logic in the classes generated. For this example, we will use |
| Axis2SampleDocLit.wsdl. This can be found in the <b>"samples\wsdl</b>" |
| directory of the binary distribution.</p> |
| |
| <h4><a name="How_to_write_the_Web_Service_2">How to write a Web |
| Service?</a></h4> |
| This method of writing a Web service with Axis2 involves five steps: |
| <ol> |
| <li><p style="margin-bottom: 0in">Generate the skeleton code</p> |
| </li> |
| <li><p style="margin-bottom: 0in">Add business logic</p> |
| </li> |
| <li><p style="margin-bottom: 0in">Verify generated services.xml</p> |
| </li> |
| <li><p style="margin-bottom: 0in">Create a *.aar archive (Axis Archive) for |
| the Web service</p> |
| </li> |
| <li><p style="margin-bottom: 0in">Deploy the Web service</p> |
| </li> |
| </ol> |
| |
| <h4><a name="Step1_:Generate_skeleton">Step1 : Generate Skeleton Code</a></h4> |
| |
| <p>To generate the skeleton and required classes, you can use the WSDL2Java |
| tool provided in Axis2. This tool is located in the bin directory of the |
| distribution and can be executed using the provided scripts (.bat or .sh). |
| The tool's parameter list is as follows and users can specify these values |
| depending on their requirements.</p> |
| <pre>Usage WSDL2Code -uri <Location of WSDL> : WSDL file location |
| -o <output Location> : output file location |
| -a : Generate async style code only. Default is off |
| -s : Generate sync style code only. Default is off. takes precedence over -a |
| -p <package name> : set custom package name |
| -l <language> : valid languages are java and csharp. Default is java |
| -t : Generate TestCase to test the generated code |
| -ss : Generate server side code (i.e. skeletons). Default is off |
| -sd : Generate service descriptor (i.e. services.xml). Default is off. Valid with -ss |
| -d <databinding> : valid databinding(s) are adb, xmlbeans and jaxme. Default is adb |
| -g Generates all the classes. valid only with the -ss |
| -pn <port_name> : name of port in the presence of multiple ports |
| -sn <service_name> : name of service in the presence of multiple services |
| -u : unpacks the databinding classes |
| -r <repository_path> : path of the repository against which code is generated</pre> |
| |
| <p>The parameters for wsdl2java tool in our example are as follows:</p> |
| <strong>Windows</strong> <!--<p>Windows users can use the following command in the console:</p> --> |
| |
| <pre style="margin-bottom: 0.2in">WSDL2Java.bat -uri ..\samples\wsdl\Axis2SampleDocLit.wsdl -ss -sd -d xmlbeans -o ..\samples -p org.apache.axis2.userguide</pre> |
| <strong>Linux</strong> <!--<p>Linux users should switch the file separator:</p> --> |
| |
| <pre style="margin-bottom: 0.2in">WSDL2Java.sh -uri ../samples/wsdl/Axis2SampleDocLit.wsdl -ss -sd -d xmlbeans -o ../samples -p org.apache.axis2.userguide</pre> |
| |
| <p>This will generate the required classes in the <b>"sample\src"</b> |
| directory, and the schema classes in |
| <strong>"samples\resources\schemaorg_apache_xmlbeans"</strong> |
| directory<strong></strong>. Note that these are not source files and should |
| be available in the class path in order to compile the generated classes.</p> |
| |
| <h4><a name="Step2_Implement_Business_Logic">Step 2: Implement Business |
| Logic</a></h4> |
| |
| <p>Implement the business logic in the skeleton class. The skeleton class |
| "Axis2SampleDocLitServiceSkeleton.java" can be found in |
| <strong>"samples/src/org/apache/axis2/userguide</strong>" directory. Our |
| sample WSDL-Axis2SampleDocLit.wsdl in <strong>"samples/wsdl"</strong> |
| directory has three operations: <!--<li><p style="margin-bottom: 0in">echoVoid  - Operation that does not |
| accept any input parameters and also provide no out put parameters. Just |
| perform some task </p> |
| </li>--> |
| </p> |
| <ul> |
| <li><p style="margin-bottom: 0in">echoString - echoes a String value </p> |
| </li> |
| <li><p style="margin-bottom: 0in">echoStringArray - echoes a String |
| Array</p> |
| </li> |
| <li><p style="margin-bottom: 0in">echoStruct - echoes a Struct</p> |
| </li> |
| </ul> |
| <!--<h4>echoVoid  </h4> |
| |
| <p>Locate the following code segment in |
| "Axis2SampleDocLitServiceSkeleton.java"Â and add the business logic. For |
| the explanation purpose we do not need anything to be implemented here.</p> |
| <pre>public void echoVoid(){ |
| //Todo fill this with the necessary business logic |
| }</pre> --> |
| |
| <h4><a name="echoString">echoString</a></h4> |
| |
| <p>Locate the following code segment in |
| "Axis2SampleDocLitServiceSkeleton.java"Â and add the business logic as shown |
| below.</p> |
| <pre> public org.apache.axis2.userguide.xsd.EchoStringReturnDocument echoString |
| (org.apache.axis2.userguide.xsd.EchoStringParamDocument param4 ){ |
| //Todo fill this with the necessary business logic |
| throw new java.lang.UnsupportedOperationException(); |
| } |
| </pre> |
| |
| <p>Once the business logic is added, the source code appears as below:</p> |
| <pre>public org.apache.axis2.userguide.xsd.EchoStringReturnDocument echoString |
| (org.apache.axis2.userguide.xsd.EchoStringParamDocument param4) throws Exception { |
| //Use the factory to create the output document. |
| EchoStringReturnDocument retDoc = EchoStringReturnDocument.Factory.newInstance(); |
| //send the string back. |
| retDoc.setEchoStringReturn(param4.getEchoStringParam()); |
| return retDoc; |
| }</pre> |
| |
| <h4><a name="echoStringArray">echoStringArray</a></h4> |
| |
| <p>The code segment for echoStringArray is shown below:</p> |
| <pre>public org.apache.axis2.userguide.xsd.EchoStringArrayReturnDocument echoStringArray |
| (org.apache.axis2.userguide.xsd.EchoStringArrayParamDocument param0) throws Exception { |
| //Use the factory to create the output document. |
| EchoStringArrayReturnDocument retDoc = EchoStringArrayReturnDocument.Factory.newInstance(); |
| //Get the String array from the input parameters. |
| String[] inParams = param0.getEchoStringArrayParam().getStringArray(); |
| ArrayOfstringLiteral retParams = ArrayOfstringLiteral.Factory.newInstance(); |
| //Set the input parameters to the output parameters for echoing. |
| for (int i = 0; i < inParams.length; i++) { |
| retParams.addString(inParams[i]); |
| } |
| //return the output document. |
| retDoc.setEchoStringArrayReturn(retParams); |
| return retDoc; |
| }</pre> |
| |
| <h4><a name="echoStruct">echoStruct</a></h4> |
| |
| <p>The code segment for echoStruct is shown below:</p> |
| <pre>public org.apache.axis2.userguide.xsd.EchoStructReturnDocument echoStruct |
| (org.apache.axis2.userguide.xsd.EchoStructParamDocument param2) throws Exception { |
| //Use the factory to create the output document. |
| EchoStructReturnDocument retDoc = EchoStructReturnDocument.Factory.newInstance(); |
| |
| //Get the SOAPStrcut from the incoming parameters |
| SOAPStruct inStruct = param2.getEchoStructParam(); |
| |
| //Struct for the sending back |
| SOAPStruct outStruct = SOAPStruct.Factory.newInstance(); |
| |
| //Fill the outgoing struct |
| outStruct.setVarFloat(inStruct.getVarFloat()); |
| outStruct.setVarInt(inStruct.getVarInt()); |
| outStruct.setVarString(inStruct.getVarString()); |
| //Set the outgoing document. |
| retDoc.setEchoStructReturn(outStruct); |
| |
| return retDoc; |
| }</pre> |
| |
| <h4><a name="Step3_:Verify_services_xml">Step3 : Verify Generated |
| services.xml</a></h4> |
| |
| <p>As mentioned earlier, "services.xml" file holds all the configuration |
| information for a Web service. When the skeleton is generated using the |
| WSDL2Java tool, the services.xml file is also generated. This file can be |
| found in the same directory as the skeleton. The generated services.xml is as |
| follows.</p> |
| <pre><!-- This file was auto-generated from WSDL --> |
| <!-- by the Apache Axis2 version: #axisVersion# #today# --> |
| <serviceGroup> |
| <service name="Axis2SampleDocLitService"> |
| <messageReceivers> |
| <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" |
| class="org.apache.axis2.userguide.Axis2SampleDocLitServiceMessageReceiverInOut"/> |
| </messageReceivers> |
| <parameter locked="false" name="ServiceClass"> |
| org.apache.axis2.userguide.Axis2SampleDocLitServiceSkeleton</parameter> |
| <operation name="echoStringArray" mep="http://www.w3.org/2004/08/wsdl/in-out"> |
| <actionMapping>echoStringArray</actionMapping> |
| </operation> |
| <operation name="echoStruct" mep="http://www.w3.org/2004/08/wsdl/in-out"> |
| <actionMapping>echoStruct</actionMapping> |
| </operation> |
| <operation name="echoString" mep="http://www.w3.org/2004/08/wsdl/in-out"> |
| <actionMapping>echoString</actionMapping> |
| </operation> |
| </service> |
| </serviceGroup></pre> |
| |
| <p>1. First line of the "services.xml" gives the name of the Web service. |
| This is used in the URL to the service as the service name.</p> |
| |
| <p>2. Next comes the description and the service class.</p> |
| |
| <p>3. The following xml tags describe the operations that are available in |
| this service with respective message receivers.</p> |
| |
| <h4><a name="Step4_Create_archive">Step 4: Create Archive File</a></h4> |
| |
| <p>The next step is to package the classes in an .aar (axis2 archive) and |
| deploy it in Axis2. When the WSDL2Java tool generates the skeleton, it will |
| also generate the required data binding classes. These schema related classes |
| are located in the |
| <strong>"samples\resources\schemaorg_apache_xmlbeans</strong>" directory of |
| the generated code. Copy this to your class path, compile the skeleton and |
| the supporting classes. To create the .aar file, create the following |
| directory structure with the required files and then jar it up.</p> |
| |
| <p><img src="images/userguide/DirectoryStructure.jpg" align="bottom" |
| border="0"></p> |
| |
| <p>Go to the top level directory where you can find the class files for the |
| above service (i.e. one level up on the directory structure shown above), |
| then run the following on the command line</p> |
| <pre style="margin-bottom: 0.2in">jar -cf Axis2SampleDocLitService.aar</pre> |
| |
| <h4><a name="Step5_Deploy_web_service">Step 5: Deploy Web Service</a></h4> |
| |
| <p>The service can be deployed by dropping dropping the ".aar" file in to |
| "services" directory in "/webapps/axis2/WEB-INF" of your servlet |
| container.Start the servlet container (if you have not already started) and |
| check the link "Services" on the <a href="http://localhost:8080/axis2/" |
| target="_blank">Home Page of Axis2 Web Application</a> |
| (http://localhost:8080/axis2) and see whether the Axis2SampleDocLitService is |
| deployed properly. If you can see the following output then you have |
| successfully deployed Axis2SampleDocLitService on Axis2. Congratulations |
| !!</p> |
| |
| <p align="center"><img src="images/userguide/ServiceDeployed.jpg" |
| name="Graphic4" align="bottom" border="0"></p> |
| |
| <p>Note: Axis2 provides an easy way to deploy Web Services using the "Upload |
| Service" tool on Axis2 Web Application's Administration module. (See the <a |
| href="webadminguide.html" target="_blank">Web Administration Guide</a> for |
| more information on this)</p> |
| |
| <h2><a name="Web_Service_Clients_Using_Axis2">Web Service Clients Using |
| Axis2</a></h2> |
| |
| <p>Let's see how we can write a Web service Client using Axis2 in order to |
| use a Web service. All samples mentioned in this guide are located at the |
| <b><font color="#000000">"samples\userguide\src"</font></b> directory of the |
| binary distribution. So let's get started!</p> |
| |
| <p>Web services can be used to provide a wide-range of functionality to 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 in to |
| 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>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 life easier for |
| developers writing Web service client applications</p> |
| </li> |
| </ol> |
| |
| <h3><a name="Writing_Web_Service_Clients_using_Axis2's_Primary_APIs">1. |
| 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 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 |
| "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 an 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); |
| /** |
| * 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 |
| "fireAndForget()" 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 "testPingClient" 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> |
| |
| <h4><a name="EchoNonBlockingClient">EchoNonBlockingClient</a></h4> |
| |
| <p>In the EchoBlockingClient once the "serviceClient.sendReceive(payload);" |
| 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 |
| "testEchoNonBlockingClient" target of the ant file found at the |
| "<strong>Axis2_HOME/samples</strong>" 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 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.finalizeInvoke(); |
| } catch (AxisFault axisFault) { |
| //have to ignore this |
| } |
| }</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>service.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" the addressing module in both client and server sides.</p> |
| |
| <h5>Engaging Addressing in the Server Side</h5> |
| According to the Axis2 architecture, addressing module put its handlers in |
| the "<strong>pre-dispatch</strong>" phase (See <a |
| href="Axis2ArchitectureGuide.html#incomingsoap">Architecture Guide</a> for |
| more details on 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 |
| "<strong>/webapps/axis2/WEB-INF/conf</strong>" directory in the servlet |
| container. |
| <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> |
| |
| <h5>Engaging Addressing in the Client Side</h5> |
| There are two ways of doing this:<br> |
| |
| <ol> |
| <li>One is to get the addressing-<version>.mar from modules folder of |
| the standard binary distribution. And then making that available in your |
| classpath.</li> |
| <li>The second method is to create a ConfigurationContext giving a |
| repository location. Axis2 has the concept of a repository to keep the |
| services and modules.</li> |
| </ol> |
| |
| <p>You can use the extracted <a |
| href="../download/1_1/download.html/#std-bin">standard binary |
| distribution</a> itself as the repository as it contains the proper structure |
| of an Axis2 repository (having the services and modules folders inside it). |
| ConfigurationContext has the runtime context information of the Axis2 system. |
| <br> |
| </p> |
| |
| <p>If you have extracted the standard binary distribution to, say, |
| $user_home/axis2/dist, then put the following line just before sender = new |
| ServiceClient();</p> |
| <pre>ConfigurationContext configContext = ConfigurationContextFactory.createConfigurationContextFromFileSystem(< Axis2RepositoryLocation >, null);</pre> |
| Then replace "sender = new ServiceClient();" line with "sender = new |
| ServiceClient(configContext, null);" |
| |
| <p>This will enable addressing in both client and server sides. Now you can |
| test the "TestEchoNonBlockingDualClient" using the |
| "testEchoNonBlockingDualClient" target of the ant file found at |
| "<strong>Axis2_HOME/samples/userguide</strong>" 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 "<strong>Axis2_HOME/samples/userguide/src/userguide/clients/</strong>" |
| 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 the 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. Users can test this client using the |
| "echoBlockingDualClient" target of the ant build file found in the |
| "<strong>Axis2_HOME/samples/userguide</strong>" directory.</p> |
| |
| <p>See <a href="http-transport.html" target="_blank">Configuring |
| Transports</a> for using different transports.</p> |
| |
| <h3><a |
| name="Writing_Web_Service_Clients_using_Code_Generation_with_Data_Binding_Support">2. |
| Writing Web Service Clients using Code Generation with Data Binding |
| Support</a></h3> |
| |
| <p>Axis2 provides the data binding support for Web service clients as well. |
| The user can generate the required stubs from a given WSDL with other |
| supporting classes. Let's generate stubs for the WSDL used earlier to |
| generate the skeleton for the "Axis2SampleDocLitService". Simply run the |
| WSDL2Java tool that can be found in the bin directory of the Axis2 |
| distribution using the following command:</p> |
| |
| <p>Windows users can use the following command in the console:</p> |
| <pre style="margin-bottom: 0.2in">WSDL2Java.bat -uri ..\samples\wsdl\Axis2SampleDocLit.wsdl -d xmlbeans -o ..\samples\src -p org.apache.axis2.userguide</pre> |
| |
| <p>Linux users should switch the file separator to:</p> |
| <pre style="margin-bottom: 0.2in">WSDL2Java.sh -uri ../samples/wsdl/Axis2SampleDocLit.wsdl -d xmlbeans -o ../samples/src -p org.apache.axis2.userguide</pre> |
| |
| <p>This will generate the required stub "Axis2SampleDocLitServiceStub.java" |
| that can be used to invoke the Web service Axis2SampleDocLitService. Let's |
| see how we can use this stub to write Web service clients to utilize the Web |
| service Axis2SampleDocLitService (This is 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>The following code fragment shows the necessary code for utilizing the |
| echoString operation of the Axis2SampleDocLitService 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/Axis2SampleDocLitService"); |
| //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 the 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/Axis2SampleDocLitService"); |
| |
| //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/Axis2SampleDocLitService"); |
| //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> |
| |
| <h2><a name="Modules"></a>Modules</h2> |
| |
| <p>Axis2 provides extended support for modules (See <a |
| href="Axis2ArchitectureGuide.html" target="_blank">Architecture Guide</a> for |
| more details about modules in Axis2). Let's create a custom module and deploy |
| it to MyService which we created earlier.</p> |
| |
| <p>Following steps show the actions that need to be performed to deploy a |
| custom module for a given Web service:</p> |
| <ol> |
| <li><p style="margin-bottom: 0in">Create the Module Implementation</p> |
| </li> |
| <li><p style="margin-bottom: 0in">Create the Handlers</p> |
| </li> |
| <li><p style="margin-bottom: 0in">Create the module.xml</p> |
| </li> |
| <li><p style="margin-bottom: 0in">Modify the "axis2.xml" (if you need |
| custom phases)</p> |
| </li> |
| <li><p style="margin-bottom: 0in">Modify the "services.xml" to engage |
| modules at the deployment time.</p> |
| </li> |
| <li><p style="margin-bottom: 0in">Package in a ".mar" (Module Archive)</p> |
| </li> |
| <li><p>Deploy the module in Axis2</p> |
| </li> |
| </ol> |
| |
| <h3><a name="MyService_with_a_Logging_Module">MyService with a Logging |
| Module</a></h3> |
| |
| <p>Let's write a simple logging module for our sample located at |
| <b>"samples\userguide\src"</b> directory of the binary distribution. This |
| module contains one handler that just logs the message that is passed through |
| it. Axis2 uses ".mar" (Module Archive) to deploy modules in Axis2. Following |
| diagram shows the file structure inside which needs to be there in the ".mar" |
| archive. Let's create all these and see how it works.</p> |
| |
| <p><img src="images/userguide/ModuleView.jpg" name="Graphic5" align="bottom" |
| border="0"></p> |
| |
| <h4><a name="Step1_:_LoggingModule_Class">Step1 : LoggingModule Class</a></h4> |
| |
| <p>LoggingModule is the implementation class of the Axis2 module. Axis2 |
| modules should implement the "<a |
| href="http://svn.apache.org/viewcvs.cgi/webservices/axis2/trunk/java/modules/core/src/org/apache/axis2/modules/Module.java?rev=396785&view=log">org.apache.axis2.modules.Module</a>" |
| interface with the following methods.</p> |
| <pre>public void init(ConfigurationContext configContext, AxisModule module) throws AxisFault;//Initialize the module |
| public void shutdown(AxisConfiguration axisSystem) throws AxisFault;//End of module processing |
| public void engageNotify(AxisDescription axisDescription) throws AxisFault;</pre> |
| |
| <p>These methods can be used to control the module initialization and the |
| termination. With the input parameter AxisConfiguration, the user is provided |
| with the complete configuration hierarchy. This can be used to fine-tune the |
| module behavior by the module writers. For the simple logging service we can |
| keep these methods blank in our implementation class.</p> |
| |
| <h4><a name="Step2_:_LogHandler">Step2 : LogHandler</a></h4> |
| |
| <p>A module in Axis2 can contain, one or more handlers that perform various |
| SOAP header processing at different phases. (See<a |
| href="Axis2ArchitectureGuide.html#incomingsoap" target="_blank"> Architecture |
| Guide</a> for more information on phases). To write a handler one should |
| implement <a |
| href="http://svn.apache.org/viewcvs.cgi/webservices/axis2/trunk/java/modules/core/src/org/apache/axis2/engine/Handler.java?rev=357187&view=log">org.apache.axis2.engine.Handler</a>. |
| But for convenience, <a |
| href="http://svn.apache.org/viewcvs.cgi/webservices/axis2/trunk/java/modules/core/src/org/apache/axis2/handlers/AbstractHandler.java?rev=396788&view=log">org.apache.axis2.handlers.AbstractHandler</a> |
| provides an abstract implementation of the Handler interface.</p> |
| |
| <p>For the logging module we will write a handler with the following methods. |
| "public void invoke(MessageContext ctx);" is the method that is called by |
| Axis2 engine when the control is passed to the handler. "public void |
| revoke(MessageContext ctx);" is called when the handlers are revoked by the |
| Axis2 engine.</p> |
| <pre>public class LogHandler extends AbstractHandler implements Handler { |
| private Log log = LogFactory.getLog(getClass()); |
| private QName name; |
| |
| public QName getName() { |
| return name; |
| } |
| |
| public void invoke(MessageContext msgContext) throws AxisFault { |
| log.info(msgContext.getEnvelope().toString()); |
| } |
| |
| public void setName(QName name) { |
| this.name = name; |
| } |
| }</pre> |
| |
| <h4><a name="Step3_:_module_xml">Step3 : module.xml</a></h4> |
| |
| <p>"module.xml" contains the deployment configurations for a particular |
| module. It contains details such as Implementation class of the module (in |
| this example it is the "LoggingModule" class and various handlers that will |
| run in different phases). "module.xml" for the logging module will be as |
| follows:</p> |
| <pre><module name="logging" class="userguide.loggingmodule.LoggingModule "> |
| <inflow> |
| <handler name="InFlowLogHandler" class="userguide.loggingmodule.LogHandler"> |
| <order phase="loggingPhase" /> |
| </handler> |
| </inflow> |
| |
| <outflow> |
| <handler name="OutFlowLogHandler" class="userguide.loggingmodule.LogHandler"> |
| <order phase="loggingPhase"/> |
| </handler> |
| </outflow> |
| |
| <Outfaultflow> |
| <handler name="FaultOutFlowLogHandler" class="userguide.loggingmodule.LogHandler"> |
| <order phase="loggingPhase"/> |
| </handler> |
| </Outfaultflow> |
| |
| <INfaultflow> |
| <handler name="FaultInFlowLogHandler" class="userguide.loggingmodule.LogHandler"> |
| <order phase="loggingPhase"/> |
| </handler> |
| </INfaultflow> |
| </module></pre> |
| |
| <p>As you can see there are four flows defined in this "module.xml"</p> |
| <ol> |
| <li>inflow - Represents the handler chain that will run when a message is |
| coming in. </li> |
| <li><p style="margin-bottom: 0in">outflow - Represents the handler chain |
| that will run when the message is going out. </p> |
| </li> |
| <li><p style="margin-bottom: 0in">Outfaultflow - Represents the handler |
| chain that will run when there is a fault and the fault is going out</p> |
| </li> |
| <li><p>INfaultflow - Represents the handler chain that will run when there |
| is a fault and the fault is coming in </p> |
| </li> |
| </ol> |
| |
| <p>Following set of tags describe the name of the handler, handler class and |
| the phase in which this handler is going to run. "InFlowLogHandler" is the |
| name given for the particular instance of this handler class. The value of |
| class attribute is the actual implementation class for this handler. Since we |
| are writing logging handler, we can reuse the same handler in all these |
| phases. However this may not be the same for all the modules. "<order |
| phase="loggingPhase" />" describes the phase in which this handler |
| runs.</p> |
| <pre><handler name="InFlowLogHandler" class="userguide.loggingmodule.LogHandler"> |
| <order phase="loggingPhase" /> |
| </handler></pre> |
| |
| <p>To learn more about Phase rules, check out the article <a |
| href="http://www.developer.com/java/web/article.php/3529321" |
| target="_blank">Axis2 Execution Framework</a></p> |
| |
| <h4><a name="Step_4:_Modify_the_"axis2_xml"">Step 4: Modify the |
| "axis2.xml"</a></h4> |
| |
| <p>In this handler, the phase "loggingPhase", is defined by the module |
| writer. It is not a pre-defined handler phase, hence the module writer should |
| introduce it to the "axis2.xml" (NOT the services.xml) so that the Axis2 |
| engine knows where to place the handler in different "flows" ( inFlow, |
| outFlow, etc.). Following xml lines show the respective changes made to the |
| "axis2.xml" in order to deploy this logging module in the Axis2 engine. This |
| is an extract of the phase section of "axis2.xml".</p> |
| <pre><!-- ================================================= --> |
| <!-- Phases --> |
| <!-- ================================================= --> |
| |
| <phaseOrder type="inflow"> |
| <!-- System pre defined phases --> |
| <phase name="TransportIn"/> |
| <phase name="PreDispatch"/> |
| <phase name="Dispatch" class="org.apache.axis2.engine.DispatchPhase"> |
| <handler name="AddressingBasedDispatcher" |
| class="org.apache.axis2.engine.AddressingBasedDispatcher"> |
| <order phase="Dispatch"/> |
| </handler> |
| |
| <handler name="RequestURIBasedDispatcher" |
| class="org.apache.axis2.engine.RequestURIBasedDispatcher"> |
| <order phase="Dispatch"/> |
| </handler> |
| |
| <handler name="SOAPActionBasedDispatcher" |
| class="org.apache.axis2.engine.SOAPActionBasedDispatcher"> |
| <order phase="Dispatch"/> |
| </handler> |
| |
| <handler name="SOAPMessageBodyBasedDispatcher" |
| class="org.apache.axis2.engine.SOAPMessageBodyBasedDispatcher"> |
| <order phase="Dispatch"/> |
| </handler> |
| <handler name="InstanceDispatcher" |
| class="org.apache.axis2.engine.InstanceDispatcher"> |
| <order phase="PostDispatch"/> |
| </handler> |
| </phase> |
| <!-- System pre defined phases --> |
| <!-- After Postdispatch phase module author or service author can add any phase he wants --> |
| <phase name="OperationInPhase"/> |
| <phase name="<span style="color: rgb(36, 193, 19);">loggingPhase</span>"/> |
| </phaseOrder> |
| <phaseOrder type="outflow"> |
| <!-- user can add his own phases to this area --> |
| <phase name="OperationOutPhase"/> |
| <phase name="<span style="color: rgb(36, 193, 19);">loggingPhase</span>"/> |
| <!--system predefined phases--> |
| <!--these phases will run irrespective of the service--> |
| <phase name="PolicyDetermination"/> |
| <phase name="MessageOut"/> |
| </phaseOrder/> |
| <phaseOrder type="INfaultflow"> |
| <!-- user can add his own phases to this area --> |
| <phase name="OperationInFaultPhase"/> |
| <phase name="<span style="color: rgb(36, 193, 19);">loggingPhase</span>"/> |
| </phaseOrder> |
| <phaseOrder type="Outfaultflow"> |
| <!-- user can add his own phases to this area --> |
| <phase name="OperationOutFaultPhase"/> |
| <phase name="<span style="color: rgb(36, 193, 19);">loggingPhase</span>"/> |
| <phase name="PolicyDetermination"/> |
| <phase name="MessageOut"/> |
| </phaseOrder> |
| </pre> |
| |
| <p>The text in green, the custom phase "loggingPhase" is placed in all the |
| flows, hence that phase will be called in all the message flows in the |
| engine. Since our module is associated with this phase, the LogHandler inside |
| the module will now be executed in this phase.</p> |
| |
| <h4><a name="Step5_:_Modify_the_"services_xml"">Step5 : Modify the |
| "services.xml"</a></h4> |
| |
| <p>Up to this point we have created the required classes and configuration |
| descriptions for the logging module and by changing the "axis2.xml" we have |
| created the required phases for the logging module.</p> |
| |
| <p>Next step is to "<b>engage</b>" (use) this module in one of our services. |
| For this, let's use the same Web service that we have used throughout the |
| user's guide- MyService. However, since we need to modify the "services.xml" |
| of MyService in order to engage this module, we use a separate Web service, |
| but with the similar operations.</p> |
| |
| <p>The code for this service can be found in the |
| "<strong>Axis2_HOME/samples/userguide/src/userguide/example2</strong>" |
| directory. The simple changes that we have done to "services.xml' are shown |
| in green in the following lines of xml.</p> |
| <pre><service name="<span style="color: rgb(36, 193, 19);">MyServiceWithModule</span>"> |
| <description> |
| This is a sample Web service with a logging module engaged. |
| </description> |
| <span style="color: rgb(36, 193, 19);"><module ref="logging"/></span> |
| <parameter name="ServiceClass" locked="xsd:false">userguide.example2.MyService</parameter> |
| <operation name="echo"> |
| <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> |
| </operation> |
| <operation name="ping"> |
| <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> |
| </operation> |
| </service></pre> |
| |
| <p>In this example we have changed the service name (the implementation class |
| is very similar to what we have used earlier although it is in a different |
| package). In addition we have added the line <b>"<module |
| ref="logging"/>"</b> to "services.xml". This informs the Axis2 engine that |
| the module "logging" should be engaged for this service. The handler inside |
| the module will be executed in their respective phases as described by the |
| "module.xml".</p> |
| |
| <p><b><a name="Step6_:_Packaging">Step6 : Packaging</a></b></p> |
| |
| <p>Before deploying the module we need to create the ".mar" file for this |
| module. This can be done, using the "jar" command and then renaming the |
| created jar file. Or you can find the "logging.mar" that is already created |
| for you in the "<strong>Axis2_HOME/samples/userguide</strong>" directory.</p> |
| |
| <h4><a name="Step7_:_Deploy_the_Module_in_Axis2">Step7 : Deploy the Module in |
| Axis2</a></h4> |
| |
| <p>Deploying a module in Axis2 require the user to create a directory with |
| the name "modules" in the "webapps/axis2/WEB-INF" directory of their servlet |
| container and then copying the ".mar" file to that directory. So let's first |
| create the "modules" directory and drop the "logging.mar" in to this |
| directory.</p> |
| |
| <p>Although the required changes to the "services.xml" is very little, we |
| have created a separate service archive (MyServiceWithModule.aar) for users |
| to deploy and see.</p> |
| |
| <p>Deploy this service using the same steps that you used to <a |
| href="#Step4_:Deploy_the_Web_Service">deploy "MyService"</a> and copy the |
| "logging.mar" file to the "modules" directory.</p> |
| |
| <p>Then run using the "TestWebServiceWithModuleClient.bat" or |
| "TestWebServiceWithModuleClient.sh" in the |
| "<strong>Axis2Home/samples/userguide/src/userguide/clients/bin</strong>" |
| directory.</p> |
| |
| <p>Note: To see logs, the user needs to modify the "log4j.properties" to log |
| INFO. The property file is located in |
| "<strong>webapps/axis2/WEB-INF/classes</strong>" of your servlet container. |
| Change the line "log4j.rootCategory= ERROR, LOGFILE" to |
| "log4j.rootCategory=INFO, ERROR, LOGFILE".</p> |
| |
| <h2><a name="Other_Samples">Other Samples</a></h2> |
| |
| <p>To show the power of usage of Axis2, three standard samples are shipped |
| with the standard binary distribution. These are meant to interact with |
| outside Web services and prove the capabilities of the Axis2 system.</p> |
| |
| <p>The included samples are</p> |
| <ul> |
| <li><style="margin-bottom: 0in">Google spell checker sample</li> |
| <li><p style="margin-bottom: 0in">Google search sample</p> |
| </li> |
| <li><p style="margin-bottom: 0in">Amazon queuing sample</p> |
| </li> |
| </ul> |
| |
| <p>A simple introduction to each of the above samples are given below. Each |
| sample contains it's own <strong>help document</strong> that speaks about |
| the usage and the advanced operations of that particular sample.</p> |
| |
| <p>The most obvious place to look for the samples are the <a |
| href="Axis2 standard binary distribution#std-bin">standard binary |
| distribution</a>. All these samples are included in the |
| <strong>samples</strong> directory in the binary distribution. The shell |
| scripts and the batch files are in fact written to use the binary |
| distribution's root directory as the home in order to find the libraries.</p> |
| |
| <p>The alternate method is to build the samples from <a |
| href="Axis2 standard binary distribution#src">standard source |
| distribution</a>. Moving to the "<strong>Axis2_HOME/modules/samples</strong>" |
| of the source distribution and running maven will create the samples in the |
| "<strong>Axis2_HOME/target/samples</strong>" directory. However, if the |
| samples need to be started using the shell scripts (or the batch files) then |
| the Axis2_HOME environment need to be set.( the "guessed" Axis2_HOME would |
| not be correct in this case)</p> |
| |
| <h3><a name="Google_Spell_Checker_Sample">Google Spell Checker Sample</a></h3> |
| |
| <p>This includes a spell checker program that uses the Google spell checking |
| service. It demonstrates the blocking and non-blocking modes of calling the |
| service. This sample can be found at the |
| "<strong>Axis2_HOME/samples/googleSpellcheck</strong>" directory in the Axis2 |
| standard binary distribution and can be easily started using either the batch |
| file or the shell script.</p> |
| |
| <h3><a name="Google_Search_Sample">Google Search Sample</a></h3> |
| |
| <p>This includes a search program that uses the familiar Google search over |
| the SOAP API. It utilizes the non-blocking mode of the client API. This |
| sample can be found at "<strong>Axis2_HOME/samples/googleSearch</strong>" |
| directory of the standard binary distribution and can be easily started using |
| either the batch file or the shell script.</p> |
| |
| <h3><a name="Amazon_Queuing_Service">Amazon Queuing Service</a></h3> |
| |
| <p>Amazon queuing service sample shows how to use the Amazon queuing service. |
| It has two user interfaces, one to enqueue and the other to dequeue. This |
| sample is included in "<strong>Axis2_HOME/samples/amazonQS</strong>" |
| directory of the standard binary distribution with the required batch/shell |
| scripts to run the sample.</p> |
| |
| <h2>Advanced Topics</h2> |
| <ul> |
| <li><a href="rest-ws.html" target="_blank">RESTful Web Services</a></li> |
| <li><a href="tcp-transport.html" target="_blank">TCP Transport</a></li> |
| <li><a href="mail-transport.html" target="_blank">Mail Transport</a></li> |
| <li><a href="http-transport.html" target="_blank">HTTP Transports</a></li> |
| <li><a href="jms-transport.html" target="_blank">JMS Transports</a></li> |
| <li><a href="mtom-guide.html" target="_blank">MTOM with Axis2</a></li> |
| <li><a href="../modules/wss4j/1_0/security-module.html" |
| target="_blank">Securing SOAP Messages with Apache Rampart</a></li> |
| </ul> |
| </body> |
| </html> |