||
Skip to end of metadata
Go to start of metadata

Axis2 provides extended support for modules. For details on modules in Axis2, refer to the Architecture Guide. Shown below is how a simple logging module is developed. 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. 

The following steps explain the process of creating and packaging an axis2 module: 

Step1: Creating the Module Implementation

LoggingModule is the implementation class of the Axis2 module. Axis2 modules should implement the org.apache.axis2.modules.Module interface with the following methods:

public void init(ConfigurationContext configContext, AxisModule module) throws AxisFault;//Initialize the module
public void shutdown(ConfigurationContext configurationContext) throws AxisFault;//End of module processing
public void engageNotify(AxisDescription axisDescription) throws AxisFault;
public void applyPolicy(Policy policy, AxisDescription axisDescription) throws AxisFault ;
public boolean canSupportAssertion(Assertion assertion) ;
  • init(), shutdown(), engageNotify() - The methods that can be used to control the module initialization and the termination,
  • applyPolicy(), canSupportAssertion() - The methods that are used to perform policy related operations.

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 a simple logging service (as in the example), it is possible to keep these methods blank in the implementation class.

Step 2: Creating the Handlers

In the example below, a LogHandler is created.

A module in "Axis2" can contain one or more handlers that perform various SOAP header processing at different phases. To write a handler one should implement org.apache.axis2.engine.Handler. But for convenience org.apache.axis2.handlers.AbstractHandler provides an abstract implementation of the Handler interface.

For the logging module, a handler is written with the following methods:

  • public void invoke(MessageContext ctx); - Is the method that is called by the "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.
public class LogHandler extends AbstractHandler implements Handler {
    private static final Log log = LogFactory.getLog(LogHandler.class);
    private String name;

    public String getName() {
        return name;
    }

    public InvocationResponse invoke(MessageContext msgContext) throws AxisFault {
        log.info(msgContext.getEnvelope().toString());
        return InvocationResponse.CONTINUE;
    }

    public void revoke(MessageContext msgContext) {
        log.info(msgContext.getEnvelope().toString());
    }

    public void setName(String name) {
        this.name = name;
    }
}

Step 3: Creating the module.xml 

module.xml contains the deployment configurations for a particular module. It contains details such as the implementation class of the module (in this example it is the LoggingModule class and various handlers that will run in different phases). The module.xml for the logging module will be as follows:

<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>

There are four flows defined in the module.xml:

  • InFlow - Represents the handler chain that will run when a message is coming in.
  • OutFlow - Represents the handler chain that will run when the message is going out.
  • OutFaultFlow - Represents the handler chain that will run when there is a fault, and the fault is going out.
  • InFaultFlow - Represents the handler chain that will run when there is a fault, and the fault is coming in.

The following set of tags describes the name of the handler, handler class, and the phase in which this handler is going to run.

  • handler
    • name - Is the name given for the particular instance of this handler class.
    • class - Is the actual implementation class for this handler. Since we are writing a 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 - Describes the phase in which this handler runs.
<handler name="InFlowLogHandler" class="userguide.loggingmodule.LogHandler">
<order phase="loggingPhase" />
</handler>

To learn more about Phase rules, refer to the article Axis2 Execution Framework: http://www.developer.com/java/web/article.php/3529321

Step 4: Updating the axis2.xml 

In this handler the loggingPhase is defined by the module writer. It is not a predefined 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 (inFlowoutFlow, etc.).

The following XML lines show the respective changes made to the axis2.xml in order to deploy the logging module in the "Axis2" engine. This is an extract of the phase section of axis2.xml.

<!-- ================================================= -->
<!-- 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.dispatchers.AddressingBasedDispatcher">
                <order phase="Dispatch"/>
            </handler>

            <handler name="RequestURIBasedDispatcher"
                     class="org.apache.axis2.dispatchers.RequestURIBasedDispatcher">
                <order phase="Dispatch"/>
            </handler>

            <handler name="SOAPActionBasedDispatcher"
                     class="org.apache.axis2.dispatchers.SOAPActionBasedDispatcher">
                <order phase="Dispatch"/>
            </handler>

            <handler name="SOAPMessageBodyBasedDispatcher"
                     class="org.apache.axis2.dispatchers.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="loggingPhase"/>
    </phaseOrder>

    <phaseOrder type="outflow">
        <!--      user can add his own phases to this area  -->
        <phase name="OperationOutPhase"/>
        <phase name="loggingPhase"/>
        <!--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="loggingPhase"/>
    </phaseOrder>

    <phaseOrder type="Outfaultflow">
        <!--      user can add his own phases to this area  -->
        <phase name="OperationOutFaultPhase"/>
        <phase name="loggingPhase"/>
        <phase name="PolicyDetermination"/>
        <phase name="MessageOut"/>
    </phaseOrder>

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 the module is associated with this phase, the LogHandler inside the module will now be executed in this phase.

Step 5: Engaging the module

Up to this point, we have created the required classes and configuration descriptions for the logging module and the required phases. Next step is to "engage" (use) this module. You can engage the module at three levels: 

Engaging the module at service level 

The following example shows how the module is engaged for the example MyService. It is necessary to modify the services.xml of MyService in order to engage this module. The code for the service can be found in the Axis2_HOME/samples/userguide/src/userguide/example2 directory.

<service name="MyServiceWithModule">

    <description>
    This is a sample Web service with a logging module engaged.
    </description>

    <module ref="logging"/>

    <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>

In this example, the service name was changed. In addition, the line <module ref="logging"/> was added 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.

Engaging the module at operation level

Modules can be engaged for selected operations in a service by updating the services.xml of the service. The following example shows how the "logging" module is engaged for the operation named "listModulesForOperation" in a service.

<operation name="listModulesForOperation">
    <parameter name="AuthorizationAction" locked="false">/permission/admin/manage/modify/service</parameter>
    <module ref="logging"/>
</operation>

Engaging the module globally

In order to globally engage modules in WSO2 products that are based on Carbon 4.4.1 or a later version, you need to update the <AS_HOME>/repository/conf/axis2/axis2.xml file with the following:

<module ref="logging"/>

Note that the "Addressing" module is engaged by default in the axis2.xml as shown below.

<module ref="addressing"/>

Step 6: Packaging in a MAR (Module Archive) 

Before deploying the module, it is necessary to create the MAR file for this module. This can be done using the JAR command and then renaming the created JAR file. Else you can find the logging.mar that has already been created in the Axis2_HOME/samples/userguide directory.

  • No labels