Writing Axis2 Handlers

Published by: 0

Interfering the message flow

Axis2 handler is the smallest invocation unit of the axis2 engine, which has ability to intercept into the message flow during the runtime and operate read/write operations on an incoming or outgoing message. i.e: if you need to route messages coming with specific attributes to a different end point or count the number of messages with that attribute you can simply make use of axis2 handlers. Since, handlers has that ability of intercepting to message flow and read/write to message context, inherently they are capable of suspending the message flow.

Axis2 handlers give you full authority over SOAP messages travel through. As a result of that super control, handlers can add additional headers to SOAP message, add body content and read the message header or the body.

Specially, when implementing ws-reliableMessaging handlers can be used to control the flow of the message. if the message supposed to be delivered second, arrives first it can be hold till the first message arrives and then it can be send to execution.

Inbuilt axis2 handlers

Axis2 comes with a list of inbuilt handlers to implement ws-* and other functionalities like parsing headers.

Writing an axis2 Handler

To write a handler, you either have to extend the AbstractHandler class or implement the Handler interface.

[java]/**
* Created by malintha on 9/25/14.
*/
public class MyHandler extends AbstractHandler {

    private static Log audit = LogFactory.getLog(MyHandler.class);
    @Override
    public InvocationResponse invoke(MessageContext messageContext) throws AxisFault {
        SOAPEnvelope mes = messageContext.getEnvelope();
        SOAPHeader mesh = mes.getHeader();
        SOAPBody mesb = mes.getBody();
        OMElement bodyChild = mesb.getFirstElement();
        //TODO statements
            }
//This return statement defines what to be done with the message flow after this handler
//execution is finished.
        return InvocationResponse.CONTINUE;

}[/java]

The return statement of the

[code]invoke()[/code]

method defines what has to be done with the message flow after the execution of current handler is finished.

 

  • Continue: The handler thinks that the message is ready to go forward.
  • Suspend: The handler thinks that the message cannot be sent forward since some conditions are not satisfied; so the execution is suspended.
  • Abort: The handler thinks that there is something wrong with the message, and cannot therefore allow the message to go forward.

In most cases, handlers will return

[code]InvocationResponse.CONTINUE[/code]

as the return value.

 

An axis2 phase consists of several handlers and after each handler calls InvocationResponse.CONTINUE after the execution, the message is immediately passed to the next handler

Packaging the handler

Easiest way of packaging a handler is shipping it with an axis2 module. By that way, each handler can act independently and number of handlers can be shipped.

A module is a collection of handlers along with its configurations. We can define more than one handlers within a module.

Create the following directory structure in your project.

[code]LoggingModule

-Resources
    -META-INF
      -module.xml
-src
   -LoggingModule.java
   -LoggingHandler.java

[/code]

LoggingModule.java No implementation in this class at the moment.

[java]/**
* Created by malintha on 9/25/14.
*/
public class LoggingModule implements Module {

public void init(ConfigurationContext configurationContext, AxisModule axisModule) throws AxisFault {}

public void engageNotify(AxisDescription axisDescription) throws AxisFault {}

public void shutdown(ConfigurationContext configurationContext) throws AxisFault {}

public void applyPolicy(org.apache.neethi.Policy policy, AxisDescription axisDescription) throws AxisFault {}

public boolean canSupportAssertion(org.apache.neethi.Assertion assertion) {
return false;
}
}[/java]

LoggingHandler.java

[java]public class LoggingHandler 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;
}
}[/java]

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

[xml]<module name="logging" class="LoggingModule">
<InFlow>
<handler name="InFlowLogHandler" class="LogHandler">
<order phase="loggingPhase" />
</handler>
</InFlow>

<OutFlow>
<handler name="OutFlowLogHandler" class="LogHandler">
<order phase="loggingPhase"/>
</handler>
</OutFlow>

<OutFaultFlow>
<handler name="FaultOutFlowLogHandler" class="LogHandler">
<order phase="loggingPhase"/>
</handler>
</OutFaultFlow>

<InFaultFlow>
<handler name="FaultInFlowLogHandler" class="LogHandler">
<order phase="loggingPhase"/>
</handler>
</InFaultFlow>
</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.

 

Then you can modify the axis2.xml in order to introduce LoggingModule to the axis2 engine. Here we have defined a custome phase named LoggingPhase here.

[xml] <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>[/xml]

services.xml

[xml]<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>[/xml]

After the module is built, you may place the .jar or .mar (rename the jar file) and keep in your library dir WSO2, (repository/components/lib).