Hey Joshua... here's what I've done:

 

First, some context for the example:  I'm using session management (soap
sessions) and by default (ie. without a fault handler) axis2 returns an
axis fault when an invalid soap session id is sent from a client
request.  Basically I needed to return a formatted error response with
an error code and other information the conforms to the service
agreements we have with our clients.  In other words it was unacceptable
that I return a raw axis fault.

 

My solution was based on this:

Axis2 has a pretty cool execution cycle, which breaks down into four
execution 'flows' - in INFLOW, the INFAULTFLOW, the OUTFLOW, and the
OUTFAULTFLOW.   When a SOAP message is received, the axis2 engine starts
processing in the INFLOW... but if a fault occurs during processing then
execution passes to the INFAULTFLOW.  Similarly the OUTFLOW and
OUTFAULTFLOW handle the processing of the outbound SOAP response.  Each
flow in itself is comprised of one or more 'phases' of execution.  A
phase then defines handler classes that are invoked during execution of
the phase.  Phase handlers conform to a contract (ie. they extend an
axis2 AbstractHandler and implement and Axis2 handler).  Essentially a
phase handler needs to implement the method:

 

     public InvocationResponse invoke(MessageContext context) throws
AxisFault { ... }

 

The Axis2 engine then basically reads the flow information from the
axis2.xml configuration file and invokes the specified phases/handlers
at runtime by iterating through the handlers and calling the 'invoke'
method.  Notice that you'll have access to the MessageContext within the
handler. 

 

What this all means is that you can add your own custom phases and
handlers to these flows.  Your handler just needs to implement the
invoke method described above.  In my case I added a phase to the
OUTFAULTFLOW.  By the time the engine invokes my handler the message
context it passes contains an axis fault.  I simply create a new SOAP
envelope with the response I want to send and set it to the message
context (and by doing so overwrite the SOAP envelope with the axis
fault).     

 

Here's my handler implementation (note I haven't included all the
methods for the jibx conversion of my response type to xml - basically
the point is that you just need to create your own SOAP envelope).

 

 

    package com.ws.axis2.faults;

    import org.apache.axiom.om.OMAbstractFactory;

    import org.apache.axiom.soap.SOAP11Constants;

    import org.apache.axiom.soap.SOAP12Constants;

    import org.apache.axiom.soap.SOAPFactory;

    import org.apache.axis2.AxisFault;

    import org.apache.axis2.context.MessageContext;

    import org.apache.axis2.context.OperationContext;

    import org.apache.axis2.engine.Handler;

    import org.apache.axis2.handlers.AbstractHandler;

    import org.apache.axis2.i18n.Messages;

    import org.apache.log4j.Level;

    import org.apache.log4j.Logger;

 

    public class MyFaultHandler extends AbstractHandler implements
Handler {

    private String name; 

    static Logger logger;                

    static {

                        logger = Logger.getLogger(MyFaultHandler.class);

            }

    

    /* (non-Javadoc)

     * @see
org.apache.axis2.engine.Handler#invoke(org.apache.axis2.context.MessageC
ontext)

     */

    public InvocationResponse invoke(MessageContext msgContext) throws
AxisFault {

        // TODO Auto-generated method stub

        

        try {

            // find the error that caused this axis fault by extracting
it from the existing msgContext SOAP envelope

            String err =
msgContext.getEnvelope().getBody().getFault().getText();

 

            // log the error

            logger.error(err);

 

            // create a new SOAP envelope and create it's contents

            org.apache.axiom.soap.SOAPEnvelope envelope = null;

 

            // I'm using jibx data binding to create my own response
type and format as XML

            MyResponseType response = null;

                            response = new MyResponseType ();

                                    response.setMajorCode(3);

                                    MyErrorType error = new
MyErrorType();

                                    error.setCode(303);

                                    error.set_value("My error
message.");

                                    response.addError(error);

                                    

                                    // add my custom error response to
the SOAP envelope 

                                    envelope =
toEnvelope(OMAbstractFactory.getSOAP11Factory(),

                                                            response,
false);

 

                                    // set the msgContext's envelope to
the one I just created

                                    msgContext.setEnvelope(envelope);

                                    

                        } catch (Exception e) {

                                    throw
org.apache.axis2.AxisFault.makeFault(e);

                        }

   

        // continue processing     

        return InvocationResponse.CONTINUE;

    }

 

  public void setName(String name) {

        this.name = name;

    }

 

}

 

 

 

Ok, so that covers the handler.  For the packaging and deployment of the
fault module I'll refer you to this article:
http://ws.apache.org/axis2/1_1/modules.html

 

It describes the modifications you need to make to the axis2.xml as well
as how to create a module that contains your custom phase and handler.
After you read the article,  here's some additional notes I have from
having done this myself

 

1.      Your module.xml deployment descriptor will look something like
this:

 

<module name="myfaultmodule" class="com.ws.axis2.faults.MyFaultModule">

  <OutFaultFlow>

      <handler name="MyFaultFlowHandler"
class="com.ws.axis2.faults.MyFaultHandler">

            <order phase="MyFaultPhase"/>

      </handler>

  </OutFaultFlow>

</module>

 

2.      Name your .mar deployment module exactly the same as how you
refer to it from your services.xml descriptor. 

 

    Ie.  your services.xml will have a module reference tag:   

  

    <module ref="myfaultmodule">  

 

    And you will deploy your module as:

 

   <<appserver>>/webapps/axis2/WEB-INF/modules/myfaultmodule.mar

 

 

 

     3.  Add your custom phase to the OUTFAULTFLOW like this (from
axis2.xml):

 

<phaseOrder type="OutFaultFlow">

        <!--      user can add his own phases to this area  -->

        <phase name="soapmonitorPhase"/>

        <phase name="OperationOutFaultPhase"/>

        <phase name="PolicyDetermination"/>

        <phase name="MessageOut"/>

        <phase name="MyFaultPhase"/>

 </phaseOrder>

 

 

 

 

 

 

 

 

 

 

________________________________

From: Joshua White [mailto:[EMAIL PROTECTED] 
Sent: Tuesday, March 06, 2007 7:25 AM
To: [email protected]
Subject: Re: [Axis 1.4.x] Strategies for handling exceptions

 

Rob,

 

That sounds pretty cool.  Would you mind posting a small example?

 

Thanks,

 

Joshua

 

On 3/5/07, Rasile, Rob <[EMAIL PROTECTED]> wrote: 

One way is to create your own custom fault module (with a fault handler)
and add it to the in-fault/out-fault flow execution chain (which are
comprised of phases).  Within your custom fault handler you can
intercept the axis fault (which by that time is in the message context)
and replace it with something more to your liking (which is what I do).
If you look at the axis2.xml you'll see these flows and the
corresponding phases defined - as well as where you can add your own
phases/handlers.  If you'd like an example on how to do this let me know
and I'll post something tomorrow.    

 

________________________________

From: Joshua White [mailto: [EMAIL PROTECTED] 
Sent: Monday, March 05, 2007 9:26 PM
To: [email protected]
Subject: [Axis 1.4.x] Strategies for handling exceptions

 

Hello,

 

I am looking for some examples on how to best handle checked and
unchecked exceptions.  Is there a "best" way to map to soap faults to
return an intelligent message to your client?  I have not seen many much
documentation or examples about this.  Any help you would be
appreciated. 

 

Regards,

 

Joshua

 

Reply via email to