Writing the module.xml file
So far, we have written two handlers and module implementation classes. Now,
the only remaining thing to do is to write the module descriptor file. When writing
module.xml, we have to use phase rules to specify the location of handlers and we
have discussed phase rules before (it is time to refresh our mind about the phase
rule). The most simple module.xml file for our module is shown here:
<code> <module name="counterModule" class="org.apache.axis2.sample.module. request.CounterModule"> <Description> Counts the incoming and outgoing messages </Description> <InFlow> <handler name="IncomingMessageCountHandler" class="org.apache.axis2.sample.module.request. IncomingCounterHandler"> <order phase="Transport" after="RequestURIBasedDispatcher" before="SOAPActionBasedDispatcher"/> </handler> </InFlow> <OutFlow> <handler name="OutgoingMessageCountHandler" class="org.apache.axis2.sample.module.request. OutgoingCounterHandler"> <order phase="MessageOut"/> </handler> </OutFlow> </module> </code>
In the file module.xml, we have specified the description of the module as “Counts the incoming and outgoing messages”; in the meantime, it has specified the two handlers we implemented earlier with phase rules.
As you can see, we try to put our incoming message counter into the transport phase and the exact location is after RequestURIBasedDispatcher and before SOAPActionBasedDispatcher. If you look at the default axis2.xml file, you can see the two handlers in the inFlow. Meanwhile, in the outgoing message, a counter is added to the message-out phase and this does not specify the exact location.
If you look carefully, you can see in the root element that there is an attribute called
“class”, which specifies the module interface class. We need to remember that this attribute is an optional one and some modules may or may not have this attribute.
<code> There are instances where the module author needs to use a new phase for the module. In such a situation, one can edit the axis2.xml and specify the new phase(s) one wants. Once specified, phases can be used inside the module.xml. </code>
In the module.xml file, we have not discussed how to add the fault handlers, as we already know, there are two fl ows for fault processing: InFaultFlow and OutFaultFlow. The InFaultFlow is executed when there is an incoming fault. Similarly, OutFaultFlow is executed when there is an outgoing message. If you want to add handler(s) to any of those phases, you can do that just like you did with the other two fl ows.
Deploying and engaging the module
Now we have written everything you need for a valid module, the only remaining thing is to create the module archive file and deploy it to the repository. First we compile our source code and then, as we know, it creates .class files.
Assuming org.apache.axis2.sample.module.request is the package name of
our source file, we can find all the .class files under classes/org/apache/axis2/
Now create a directory called META-INF under the classes directory and copy the
module.xml file into it. Then our classes directory should look like the following
Now create a ZIP file from the classes directory and rename the ZIP file into the
Deploying the module is as simple as dropping the file into the TOMCAT_HOME/webapps/axis2/WEB-INF/modules or repository/modules directory. In this case, let’s focus on deploying the module in Tomcat or your favorite web application server. As we know, Axis2 does not support module hot deployment, so just dropping the module will not make any changes to the runtime system. To deploy our module and apply the necessary changes to runtime, we need to restart Axis2; in other words, we need to restart the application server.
It should be noted that just deploying a module does not add its handlers into the handler chain; to add handlers into the system, it is necessary to engage the module. Now, let’s see how we engage a module in Axis2. For this purpose, we can use the Axis2 web administration console. Moreover, to make the story simple, let’s try to engage the module to all the services in the system using the web administration console (we can engage to a single service also using the administration console).
We can engage the module to the system by carrying out the following steps:
- Go to http://localhost:8080/axis2/.
- Click on the Administration tab. This will open up a new page and ask for
the username and password.
- Enter admin as the username and axis2 as the password. This will open up
the administration console.
- After that, click on the Available Modules in the side navigation menu on
the left-hand side. There we will find our Counter module as
counterModule: Counts the incoming and outgoing messages.
- Now go to Engage Module\For all Services and this will open up a new
page with a drop-down menu.
- Select counterModule from that and click engage.
- Now we should see the message counterModule module engaged globally
- Go to Global Chains and you will be able to see the
IncomingMessageCountHandler handler in the transport phase between
RequestURIBasedDispatcher and SOAPActionBasedDispatcher.
Now, this simply tells us that we have engaged the module successfully and we have added the handler into the correct phases to invoke the version server, enter the following into your browser:
Then, in the console, you will see the following:
and the response has gone though the outgoing counter handler. Now, let’s invoke the service one more time and see what we get in the console. We will see the following:
<code> There are other ways of engaging a module, for example, to engage a module globally, a user can edit axis2.xml and add the <module ref="modulename"/> element. Moreover, if a user wants to engage it to particular services, he/she can do that by editing the services.xml and adding the same tag mentioned earlier. </code>
Here, we looked at a very simple module.xml, but when it comes to very complex applications, we need to have many more configurations in a module.xml file. We might need to have parameters, WS-Policy, and endpoints. Now let’s look at them one at a time in brief.
Adding a parameter here is the same as adding a parameter in services.xml or axis2.xml. We just need to add the following tag into module.xml and Axis2 will do the right thing for us:
We can have any number of parameters in a module.xml, and when we want to access the parameter, we can do that by carrying out the following steps:
- First we need to get the AxisModule. We can do that either by using the init method (Axis2 passes the AxisModule ) or we need to get the corresponding AxisModule from the ConfigurationContext (inside the Module implementation class) or from messageContext (inside a handler).
- After this, we can ask for the parameter from the AxisModule.
Specifying a WS-Policy element in module.xml is one way of configuring a module. We can add WS-Policy element inside a module.xml. If we consider the Sandesha2 (reliable message implementation) module, we can find the following policy element:
<code> <wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/ oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:sandesha2="http://ws.apache.org/sandesha2/ policy" wsu:Id="RMPolicy"> <sandesha2:RMAssertion> [REST OF THE FILE] </sandesha2:RMAssertion> </wsp:Policy> </code>
In Axis2, an endpoint is an operation of a web service. So, adding an endpoint is the same as adding an operation. The key question is—why do we need to add an endpoint to a module? To understand this, let’s assume that we have a module and this module has a set of control operations. The most suitable example is reliable messaging, as it has a number of control messages (for example, create sequence, last message, terminate sequence). Say, we need to invoke a service in a reliable manner. It first needs to set up a sequence with the service. For this, it will send the control message called createSequence to the service we need to access. But that service does not have that method, so if we try to send the createSequence message without adding the method, Axis2 will throw an exception saying Unable to dispatch. Therefore, adding an endpoint will solve that issue. Hence, when we engage Sandesha, it adds a method called createSequence to the service at the time we engage the module (or all the services, if we engage that to the whole system). When a request comes, Axis2 will dispatch without having any problem. This operation or the endpoint has its own message receiver to do the right thing.
So, it is obvious that when a module needs control operations exchange, it is required to add endpoint to represent those operations. Adding an endpoint is very simple.
What we need to do is add an operation element(s) along with a message receiver and a set of action mapping. To get an idea about that, let’s take the Sandesha module as a reference. Its module.xml has the following operation tag to add the control operations. Remember, when we have the operation tag in module.xml, Axis2 will do all the processing, including creating AxisOperation and adding that. As a module author, all we need to do is specify them in the module.xml file:
<code> <operation name="Sandesha2OperationInOut" mep="http://www. w3.org/2006/01/wsdl/in-out"> <messageReceiver class="org.apache.sandesha2.msgreceivers. RMMessageReceiver"/> <!-- namespaces for the 2005-02 spec --> <actionMapping>http://schemas.xmlsoap.org/ws/2005/02/rm/ CreateSequence</actionMapping> <actionMapping>http://schemas.xmlsoap.org/ws/2005/02/rm/ AckRequested</actionMapping> .................... </operation> </code>
If we look at the Sandesha module.xml, we will be able to learn and find out more
about writing a module.xml file.
In this chapter, you learned about the importance of the Axis2 module. We also learned that the Axis2 module provides a very fl exible way to extend the Axis2 core functionality and provides quality service. Moreover, we discussed the module and related concepts by writing a sample module and demonstrating most of the commonly used configuration settings. In our sample application, we discussed how to write handlers, how to write module implementation classes, and finally, how to put everything together and deploy the module. At the end of the chapter, we learned how to engage a module to Axis2.
In this chapter, we discussed how to write and deploy services and how to write and
deploy modules. In the next chapter, we are going to discuss how to invoke a remote
service. There, we will discuss how to use Axis2 as a client and invoke services in a
number of ways.