Monday, January 3, 2011

Develop Web Service With Axis2 #4 - Axis2 Style Interceptor

Prev >>> Develop Web Service With Axis2 #3 - Custom Fault Message

If you are familiar with struts2, you would know there are a few of interceptors work together in strut2 framework. Similarly, Axis2 provides 4 flows or execution chains, InFlow, OutFlow, InFaultFlow and OutFaultFlow, which define a series of modules inside, or you can call them interceptors.

This article is strictly to follow the instruction provided by axis2 to implement a handler to print incoming/outgoing soap messages for each web service transactions.
http://axis.apache.org/axis2/java/core/docs/modules.html

1.  module class

package mypackage;

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 AuditLogModule implements Module {

    // initialize the module
    public void init(ConfigurationContext configContext, AxisModule module)
            throws AxisFault {
        System.out.println("init");
    }

    public void engageNotify(AxisDescription axisDescription) throws AxisFault {
    }

    // shutdown the module
    public void shutdown(ConfigurationContext configurationContext)
            throws AxisFault {
        System.out.println("shutdown");
    }

    public String[] getPolicyNamespaces() {
        return null;
    }

    public void applyPolicy(Policy policy, AxisDescription axisDescription)
            throws AxisFault {
    }

    public boolean canSupportAssertion(Assertion assertion) {
        return true;
    }
}

2.  handler class to print soap messages

------- class to print incoming soap message
package mypackage;

import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.engine.Handler;
import org.apache.axis2.handlers.AbstractHandler;

public class AuditInHandler extends AbstractHandler implements Handler {

    public InvocationResponse invoke(MessageContext msgContext)
            throws AxisFault {
        System.out.println("Request Message :"
                + msgContext.getEnvelope().toString());
        return InvocationResponse.CONTINUE;
    }
}

------- class to print outgoing soap message

package mypackage;

import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.engine.Handler;
import org.apache.axis2.handlers.AbstractHandler;

public class AuditOutHandler extends AbstractHandler implements Handler {

    @Override
    public InvocationResponse invoke(MessageContext msgContext)
            throws AxisFault {
        System.out.println("Response Message :"
                + msgContext.getEnvelope().toString());
        return InvocationResponse.CONTINUE;
    }

}

3. prepare a module configuration file module.xml

<module name="auditLogger" class="mypackage.AuditLogModule">
    <InFlow>
        <handler name="InFlowAuditLogHandler" class="mypackage.AuditInHandler">
            <order phase="auditLogPhase" />
        </handler>
    </InFlow>
    <OutFlow>
        <handler name="OutFlowAuditLogHandler" class="mypackage.AuditOutHandler">
            <order phase="auditLogPhase" />
        </handler>
    </OutFlow>

</module>

4. add the element in red to service.xml which the web service you are going to apply to with the interceptor.

<?xml version="1.0" encoding="UTF-8"?>
<!-- This file was auto-generated from WSDL -->
<!-- by the Apache Axis2 version: 1.5.3  Built on : Nov 12, 2010 (02:24:07 CET) -->
<serviceGroup>
    <service name="UserServices">
        <messageReceivers>
            <messageReceiver mep="http://www.w3.org/ns/wsdl/in-out" class="com.test.axis.ws.skeleton.UserServicesMessageReceiverInOut"/>
        </messageReceivers>
        <module ref="auditLogger"/>
        <parameter name="ServiceClass">com.test.axis.ws.skeleton.UserServicesSkeleton</parameter>
        <parameter name="useOriginalwsdl">true</parameter>
        <parameter name="modifyUserWSDLPortAddress">true</parameter>
        <operation name="authUser" mep="http://www.w3.org/ns/wsdl/in-out" namespace="http://axis.test.com/ws/service">
            <actionMapping>urn:authUser</actionMapping>
            <outputActionMapping>urn:authUserResp</outputActionMapping>
            <faultActionMapping faultName="WebServiceFault">urn:authUserWebServiceFault</faultActionMapping>
        </operation>
        <operation name="getUserInfo" mep="http://www.w3.org/ns/wsdl/in-out" namespace="http://axis.test.com/ws/service">
            <actionMapping>urn:getUserInfo</actionMapping>
            <outputActionMapping>urn:getUserInfoResp</outputActionMapping>
            <faultActionMapping faultName="WebServiceFault">urn:getUserInfoWebServiceFault</faultActionMapping>
        </operation>
    </service>
</serviceGroup>

5. deploy module to server.

copy the auditLog.mar file to %tomcat%\webapps\axis2\WEB-INF\modules
or create a folder %tomcat%\webapps\axis2\WEB-INF\modules\auditLog and put all necessary files inside.

<folder auditLog>
          |-  META-INF
                     MANIFEST.MF
                     module.xml
          |-  com\......\xx.class


6. modify axis2.xml

I am using axis2 v1.5.3. The configuration file axis2.xml of different axis2 version might be a bit different.

add the elements shown in red to axis2.xml

<!-- ================================================= -->
    <!-- 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"/>
        <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="auditLogPhase"/>
        <phase name="soapmonitorPhase"/>
    </phaseOrder>
    <phaseOrder type="OutFlow">
        <!--      user can add his own phases to this area  -->
        <phase name="soapmonitorPhase"/>
        <phase name="OperationOutPhase"/>
        <phase name="auditLogPhase"/>
        <!--system predefined phase-->
        <!--these phase will run irrespective of the service-->
        <phase name="RMPhase"/>
        <phase name="PolicyDetermination"/>
        <phase name="MessageOut"/>
        <phase name="Security"/>
    </phaseOrder>
    <phaseOrder type="InFaultFlow">
        <phase name="Addressing">
            <handler name="AddressingBasedDispatcher"
                     class="org.apache.axis2.dispatchers.AddressingBasedDispatcher">
                <order phase="Addressing"/>
            </handler>
        </phase>
        <phase name="Security"/>
        <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"/>
    </phaseOrder>

7.test it. try to call one web service method mentioned in previous article. we can see soap message printed on tomcat console.

Request Message :<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:q0="http://axis.test.com/ws" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body>
    <q0:getUserInfo>
      <q0:userId>aaaa</q0:userId>
    </q0:getUserInfo>
  </soapenv:Body></soapenv:Envelope>


Response Message :<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><ns2:getUserInfoResp xmlns:ns2="http://axis.test.com/ws"><ns2:return><ns1:age xmlns:ns1="http://bean.axis.test.com/xsd">22</ns1:age><ns1:userName xmlns:ns1="http://bean.axis.test.com/xsd">test name1</ns1:userName></ns2:return></ns2:getUserInfoResp></soapenv:Body></soapenv:Envelope>

No comments:

Post a Comment