As intern at WSO2 we learn lot about Apache Axis 2, because my team at WSO2 works on a product called Application Server
which is based on Axis2. So we have to play a lot with Axis2. The most
interesting thing I have done with Axis2 is extending by writing a
module to it. Here I am going to talk about how to do it. I will explain
how I did it.
Before read this article about Writing a Module, Better you read these articles to get a better picture about Apache Axis 2 and it's underlining architecture,
What is Apache Axis2 :
http://axis.apache.org/axis2/java/core/
How to write a Apache Axis2 Web Service :
http://wso2.org/library/95
What is a Apache Axis2 Module :
http://axis.apache.org/axis2/java/core/docs/Axis2ArchitectureGuide.html
Also there is a interesting book written by Mr Afkham Azeez and Mr Deepal Jayasinghe. It explain all about Apache Axis2. Please read it to have 100% understanding about Axis 2. The book is Apache Axis2 Web Services, 2nd Edition.
If you have read those articles or had prior knowledge you can understand that a module will add some functionality to the execution chain of axis2 handlers. Single module can have more than one handler. So here in this example I will explain how I wrote my simple axis2 module 2 print the SOAP message content to the info log.
To follow this article you need to have a web services hosted in the simple axis2 server provided by the axis2 distribution. I have add a simple web service to my axis2 server and it is up and running when I start writing the module. Here are the steps I followed to create and run my web Service.
Definition of My Web Services :
My services.xml file :
TestWebService >
TestWebService.java
Temp>
META-INF>
services.xml
org>
wso2>
testws>
TestWebService.class
After having all these I build my TestWebService.aar file using this command,
jar -cvf TestWebService.aar *
Then I copied that archive to the repository/services folder of the axis2 home folder. Then I run the axis2server.sh script to run the simple server. Then you can see that my new service is successfully deployed.
After that we can start the development of the Axis2 Module. For that purpose I use the Eclipse IDE. Create a new java project in Eclipse and have the following structure in your project.
Here you can see that Axis2 has been added as a library to the project. To do it, right click on the project and got to Build Path > Configure Build Path. There you can find a button called Add Library, click on it and select User Library in the appearing screen. There go to new and add all the jar files in the lib folder in the axis2 home folder.
Then the definition of the TestModule.java is this,
The definition of the TestHandler.java is this,
After doing these, go the eclipse project folder in your machine, then in the TestModule folder you can find a folder called bin which has the generated class files of the project. Go inside it and create a folder called META-INF. In side it create the module.xml file. This is the definition of that file,
jar -cvf TestModule.mar *
It will create the archive file needed. Copy it to the repository/modules folder of your axis2 home folder. Now your module is ready to be deployed. Now you have to do some configuration to execute your module. Conceptually Apache Axis2 modules can be executed in two ways,
After doing that you are successfully introduced the phase you have created manually, Now it is time to define the execution type of your module,
To excute it globally, add the <module ref="TestModule"/> entry to to the Global section of the axis2.xml.
Now your custom module is sucessfully deployed. Now you can start your axis2server again. It will show following log message if your module is successfully loaded.
[INFO] Deploying module: TestModule - file:/home/andunslg/My_Works/Axis2_Code/modules/distribution/target/axis2-1.7.0-SNAPSHOT/repository/modules/TestModule.mar
After that to check it's functionality use the soapUI. Copy your web service's WSDL files link and create a soapUI project using that. If you are successful you will have a project which looks like this,
Double click on add, it will show you are SOAP message. Add parameters to the add function and send it. The web service will reply to your message if you have successfully did all the things. If it is this kind of reply will come,
To see what your module to you have to see in to your terminal where you run the axis2server. In that you can see that following log entries are shown. Those are generated by the module you have created.
[INFO] The web service TestWebService.
[INFO] The operation is org.apache.axis2.description.InOutAxisOperation@2ce99681.
[INFO] This is the SOAP envelop : <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tes="http://testws.wso2.org"><soapenv:Body>
<tes:add>
<tes:args0>3</tes:args0>
<tes:args1>2</tes:args1>
</tes:add>
</soapenv:Body></soapenv:Envelope>
[INFO] The web service TestWebService.
[INFO] The operation is org.apache.axis2.description.InOutAxisOperation@2ce99681.
[INFO] This is the SOAP envelop : <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><ns:addResponse xmlns:ns="http://testws.wso2.org"><ns:return>5</ns:return></ns:addResponse></soapenv:Body></soapenv:Envelope>
Up to now you have added custom module to AXIS2 to extend it. You can define any task in side your handler definition to o in your module. If you have any problem please contact me.
Before read this article about Writing a Module, Better you read these articles to get a better picture about Apache Axis 2 and it's underlining architecture,
What is Apache Axis2 :
http://axis.apache.org/axis2/java/core/
How to write a Apache Axis2 Web Service :
http://wso2.org/library/95
What is a Apache Axis2 Module :
http://axis.apache.org/axis2/java/core/docs/Axis2ArchitectureGuide.html
Also there is a interesting book written by Mr Afkham Azeez and Mr Deepal Jayasinghe. It explain all about Apache Axis2. Please read it to have 100% understanding about Axis 2. The book is Apache Axis2 Web Services, 2nd Edition.
If you have read those articles or had prior knowledge you can understand that a module will add some functionality to the execution chain of axis2 handlers. Single module can have more than one handler. So here in this example I will explain how I wrote my simple axis2 module 2 print the SOAP message content to the info log.
To follow this article you need to have a web services hosted in the simple axis2 server provided by the axis2 distribution. I have add a simple web service to my axis2 server and it is up and running when I start writing the module. Here are the steps I followed to create and run my web Service.
Definition of My Web Services :
package org.wso2.testws; public class TestWebService { public String sayHello(String name) { return "Hello " + name; } public int add(int x,int y){ return x+y; } }
My services.xml file :
<service name="TestWebService" > <Description> This web Service is written for test the functionlity of a AXIS2 Module </Description> <messageReceivers> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" /> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/> </messageReceivers> <parameter name="ServiceClass" locked="false">org.wso2.testws.TestWebService</parameter> </service>My Folder Stricture :
TestWebService >
TestWebService.java
Temp>
META-INF>
services.xml
org>
wso2>
testws>
TestWebService.class
After having all these I build my TestWebService.aar file using this command,
jar -cvf TestWebService.aar *
Then I copied that archive to the repository/services folder of the axis2 home folder. Then I run the axis2server.sh script to run the simple server. Then you can see that my new service is successfully deployed.
After that we can start the development of the Axis2 Module. For that purpose I use the Eclipse IDE. Create a new java project in Eclipse and have the following structure in your project.
Here you can see that Axis2 has been added as a library to the project. To do it, right click on the project and got to Build Path > Configure Build Path. There you can find a button called Add Library, click on it and select User Library in the appearing screen. There go to new and add all the jar files in the lib folder in the axis2 home folder.
Then the definition of the TestModule.java is this,
package org.wso2.testa2m; import org.apache.axis2.AxisFault; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.description.AxisDescription; import org.apache.axis2.description.AxisModule; import org.apache.axis2.modules.Module; import org.apache.neethi.Assertion; import org.apache.neethi.Policy; public class TestModule implements Module{ public void init(ConfigurationContext configContext, AxisModule module) throws AxisFault { } public void engageNotify(AxisDescription axisDescription) throws AxisFault { } public void shutdown(ConfigurationContext configurationContext) throws AxisFault { } public String[] getPolicyNamespaces() { return null; } public void applyPolicy(Policy policy, AxisDescription axisDescription) throws AxisFault { } public boolean canSupportAssertion(Assertion assertion) { return true; } }
The definition of the TestHandler.java is this,
package org.wso2.testa2m; import org.apache.axis2.AxisFault; import org.apache.axis2.context.MessageContext; import org.apache.axis2.engine.Handler; import org.apache.axis2.handlers.AbstractHandler; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class TestHandler extends AbstractHandler implements Handler{ private static final Log log = LogFactory.getLog(TestHandler.class); private String name; public String getName() { return name; } public InvocationResponse invoke(MessageContext msgContext) throws AxisFault { log.info("The web service "+msgContext.getAxisService().toString()+"."); log.info("The operation is "+msgContext.getAxisOperation().toString()+"."); log.info("This is the SOAP envelop : "+msgContext.getEnvelope().toString()); return InvocationResponse.CONTINUE; } public void revoke(MessageContext msgContext) { log.info("The web service "+msgContext.getAxisService().toString()+"."); log.info("The operation is "+msgContext.getAxisOperation().toString()+"."); log.info("This is the SOAP envelop : "+msgContext.getEnvelope().toString()); } public void setName(String name) { this.name = name; } }
After doing these, go the eclipse project folder in your machine, then in the TestModule folder you can find a folder called bin which has the generated class files of the project. Go inside it and create a folder called META-INF. In side it create the module.xml file. This is the definition of that file,
<module name="TestModule" class="org.wso2.testa2m.TestModule"> <InFlow> <handler name="InFlowLogHandler" class="org.wso2.testa2m.TestHandler"> <order phase="TestPhase"/> </handler> </InFlow> <OutFlow> <handler name="OutFlowLogHandler" class="org.wso2.testa2m.TestHandler"> <order phase="TestPhase"/> </handler> </OutFlow> <OutFaultFlow> <handler name="FaultOutFlowLogHandler" class="org.wso2.testa2m.TestHandler"> <order phase="TestPhase"/> </handler> </OutFaultFlow> <InFaultFlow> <handler name="FaultInFlowLogHandler" class="org.wso2.testa2m.TestHandler"> <order phase="TestPhase"/> </handler> </InFaultFlow> </module>After doing that your now in a position to create your module archive file. Go to bin folder of your project using terminal and execute foll wing command,
jar -cvf TestModule.mar *
It will create the archive file needed. Copy it to the repository/modules folder of your axis2 home folder. Now your module is ready to be deployed. Now you have to do some configuration to execute your module. Conceptually Apache Axis2 modules can be executed in two ways,
- Globally for all the services hosted in Axis2. To do this you have to edit the axis2.xml file
- Per Service. To do this you have to edit the services.xml file also.
<!-- ================================================= --> <!-- Phases --> <!-- ================================================= --> <phaseOrder type="InFlow"> <!-- System predefined phases --> <phase name="Transport"> <handler name="RequestURIBasedDispatcher" class="org.apache.axis2.dispatchers.RequestURIBasedDispatcher"> <order phase="Transport"/> </handler> <handler name="SOAPActionBasedDispatcher" class="org.apache.axis2.dispatchers.SOAPActionBasedDispatcher"> <order phase="Transport"/> </handler> </phase> <phase name="Addressing"> <handler name="AddressingBasedDispatcher" class="org.apache.axis2.dispatchers.AddressingBasedDispatcher"> <order phase="Addressing"/> </handler> </phase> <phase name="Security"/> <!-- +++++++Cutome Pahse I have Added+++++++ --> <phase name="TestPhase"/> <!-- +++++++++++++++++++++++++++++++++++++++ --> <phase name="PreDispatch"/> <phase name="Dispatch" class="org.apache.axis2.engine.DispatchPhase"> <handler name="RequestURIBasedDispatcher" class="org.apache.axis2.dispatchers.RequestURIBasedDispatcher"/> <handler name="SOAPActionBasedDispatcher" class="org.apache.axis2.dispatchers.SOAPActionBasedDispatcher"/> <handler name="RequestURIOperationDispatcher" class="org.apache.axis2.dispatchers.RequestURIOperationDispatcher"/> <handler name="SOAPMessageBodyBasedDispatcher" class="org.apache.axis2.dispatchers.SOAPMessageBodyBasedDispatcher"/> <handler name="HTTPLocationBasedDispatcher" class="org.apache.axis2.dispatchers.HTTPLocationBasedDispatcher"/> <handler name="GenericProviderDispatcher" class="org.apache.axis2.jaxws.dispatchers.GenericProviderDispatcher"/> <handler name="MustUnderstandValidationDispatcher" class="org.apache.axis2.jaxws.dispatchers.MustUnderstandValidationDispatcher"/> </phase> <phase name="RMPhase"/> <!-- System predefined phases --> <!-- After Postdispatch phase module author or service author can add any phase he want --> <phase name="OperationInPhase"> <handler name="MustUnderstandChecker" class="org.apache.axis2.jaxws.dispatchers.MustUnderstandChecker"> <order phase="OperationInPhase"/> </handler> </phase> <phase name="soapmonitorPhase"/> </phaseOrder> <phaseOrder type="OutFlow"> <!-- user can add his own phases to this area --> <phase name="soapmonitorPhase"/> <phase name="OperationOutPhase"/> <!--system predefined phase--> <!--these phase will run irrespective of the service--> <phase name="RMPhase"/> <phase name="PolicyDetermination"/> <phase name="MessageOut"/> <phase name="Security"/> <!-- +++++++Cutome Pahse I have Added+++++++ --> <phase name="TestPhase"/> <!-- +++++++++++++++++++++++++++++++++++++++ --> </phaseOrder> <phaseOrder type="InFaultFlow"> <phase name="Addressing"> <handler name="AddressingBasedDispatcher" class="org.apache.axis2.dispatchers.AddressingBasedDispatcher"> <order phase="Addressing"/> </handler> </phase> <phase name="Security"/> <!-- +++++++Cutome Pahse I have Added+++++++ --> <phase name="TestPhase"/> <!-- +++++++++++++++++++++++++++++++++++++++ --> <phase name="PreDispatch"/> <phase name="Dispatch" class="org.apache.axis2.engine.DispatchPhase"> <handler name="RequestURIBasedDispatcher" class="org.apache.axis2.dispatchers.RequestURIBasedDispatcher"/> <handler name="SOAPActionBasedDispatcher" class="org.apache.axis2.dispatchers.SOAPActionBasedDispatcher"/> <handler name="RequestURIOperationDispatcher" class="org.apache.axis2.dispatchers.RequestURIOperationDispatcher"/> <handler name="SOAPMessageBodyBasedDispatcher" class="org.apache.axis2.dispatchers.SOAPMessageBodyBasedDispatcher"/> <handler name="HTTPLocationBasedDispatcher" class="org.apache.axis2.dispatchers.HTTPLocationBasedDispatcher"/> <handler name="GenericProviderDispatcher" class="org.apache.axis2.jaxws.dispatchers.GenericProviderDispatcher"/> <handler name="MustUnderstandValidationDispatcher" class="org.apache.axis2.jaxws.dispatchers.MustUnderstandValidationDispatcher"/> </phase> <phase name="RMPhase"/> <!-- user can add his own phases to this area --> <phase name="OperationInFaultPhase"/> <phase name="soapmonitorPhase"/> </phaseOrder> <phaseOrder type="OutFaultFlow"> <!-- user can add his own phases to this area --> <phase name="soapmonitorPhase"/> <phase name="OperationOutFaultPhase"/> <phase name="RMPhase"/> <phase name="PolicyDetermination"/> <phase name="MessageOut"/> <phase name="Security"/> <!-- +++++++Cutome Pahse I have Added+++++++ --> <phase name="TestPhase"/> <!-- +++++++++++++++++++++++++++++++++++++++ --> </phaseOrder>
After doing that you are successfully introduced the phase you have created manually, Now it is time to define the execution type of your module,
To excute it globally, add the <module ref="TestModule"/> entry to to the Global section of the axis2.xml.
<!-- ================================================= --> <!-- Global Modules --> <!-- ================================================= --> <!-- Comment this to disable Addressing --> <module ref="addressing"/> <module ref="TestModule"/> <!--Configuring module , providing parameters for modules whether they refer or not--> <!--<moduleConfig name="addressing">--> <!--<parameter name="addressingPara">N/A</parameter>--> <!--</moduleConfig>-->If you want to add a module specially for a service, add <module ref="TestModule"/> to the service.xml file. Then it will only executed only for that service.
Now your custom module is sucessfully deployed. Now you can start your axis2server again. It will show following log message if your module is successfully loaded.
[INFO] Deploying module: TestModule - file:/home/andunslg/My_Works/Axis2_Code/modules/distribution/target/axis2-1.7.0-SNAPSHOT/repository/modules/TestModule.mar
After that to check it's functionality use the soapUI. Copy your web service's WSDL files link and create a soapUI project using that. If you are successful you will have a project which looks like this,
Double click on add, it will show you are SOAP message. Add parameters to the add function and send it. The web service will reply to your message if you have successfully did all the things. If it is this kind of reply will come,
To see what your module to you have to see in to your terminal where you run the axis2server. In that you can see that following log entries are shown. Those are generated by the module you have created.
[INFO] The web service TestWebService.
[INFO] The operation is org.apache.axis2.description.InOutAxisOperation@2ce99681.
[INFO] This is the SOAP envelop : <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tes="http://testws.wso2.org"><soapenv:Body>
<tes:add>
<tes:args0>3</tes:args0>
<tes:args1>2</tes:args1>
</tes:add>
</soapenv:Body></soapenv:Envelope>
[INFO] The web service TestWebService.
[INFO] The operation is org.apache.axis2.description.InOutAxisOperation@2ce99681.
[INFO] This is the SOAP envelop : <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><ns:addResponse xmlns:ns="http://testws.wso2.org"><ns:return>5</ns:return></ns:addResponse></soapenv:Body></soapenv:Envelope>
Up to now you have added custom module to AXIS2 to extend it. You can define any task in side your handler definition to o in your module. If you have any problem please contact me.
Very informative article mchn...Thumbs up!
ReplyDeleteIn our Wso2 whenever we deploy or undeploy we are getting the handler info...Can we avoid it???
ReplyDeleteCan you explain bit more?
Delete