axis-java-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Owens <dow...@synxis.com>
Subject Re: Custom Exceptions
Date Thu, 13 Jun 2002 15:47:45 GMT
Sam/Sylvain

Bob is on vacation, but I worked with him on this stuff, so I
thought I'd post it out there for you so you could take a look
at it....

We got our custom exception to work.  We had to make one hack to
the axis code base to make it possible, and did the rest with a handler.

We have an exception called SrmsException which extends exception.
It has one data variable, and int called "code".  This exception
is thrown from the server.  From that, we code-generate a client
version which extends AxisFault, this is what we catch on the
client.  To get the data (code) into the exception we had to do
the following:

We hacked org.apache.axis.providers.java.JavaProvider.java  to
put the data we need into the messageContext.  The JavaProvider
catches the server exceptions (search for catch block in the file
near processMessage()) and then rethrows it.  We changed it to
catch it, put info in the context, and then throw it.  The code
looks like this:

            try {
                processMessage(msgContext, clsName, allowedMethods,
reqEnv,
                               resEnv, jc, obj);
            } catch (Exception exp) {
                msgContext.setProperty("ThrownException", exp);
                throw exp;
            } finally {


That was the only change we had to make to axis.

Then we added a custome handler which sits in the chain on the request
to the server, in the chain for the response from the server to client.
(We did this by creating and adding the client-config.wsdd which
introduces our handler in the globalConfiguration portion.)

Here is the code for our handler:

package com.synxis.srms.webservices.handlers (Sorry about the
formatting):

import org.apache.axis.AxisFault;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.Constants;
import org.apache.axis.message.SOAPEnvelope;
import org.apache.axis.message.SOAPHeaderElement;
import com.synxis.srms.webservices.client.exception.SrmsException;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class SrmsExceptionDataHandler extends
org.apache.axis.handlers.BasicHandler {

    public void invoke(MessageContext msgContext) throws AxisFault {

        if (msgContext.isClient()) {
           if (msgContext.getPastPivot()) {
               //System.out.println( "INVOKE CALLED" );
               // This is a response.  Check it for the session header.
               Message msg = msgContext.getResponseMessage();
               if (msg == null)
                   return;
               SOAPEnvelope env = null;
               try {
                   env = msg.getSOAPEnvelope();
               }
               catch (Exception e)
               {
                   System.out.println("Caught from getSOAPEnvelope,
trying again");
                   env = msg.getSOAPEnvelope();
               }
               SOAPHeaderElement header =
env.getHeaderByName("http://xml.apache.org/axis/exception",
                                                             
"exceptionCode");
               if (header == null)
                   return;

               env.clearBody();
               Integer code = null;
               // Got one!
               try {
                   code = (Integer)header.
                                getValueAsType(Constants.XSD_INT);
               } catch (Exception e) {
                   throw AxisFault.makeFault(e);
               }

               if(code != null)
               {
                   throw new SrmsException(code.intValue());
               }
           }
        }

    }

    public void onFault(MessageContext msgContext)
    {      
       try
       {
           Exception e = (Exception)
msgContext.getProperty("ThrownException");

           if (e != null && e instanceof
java.lang.reflect.InvocationTargetException)
           {
               Throwable re =
((java.lang.reflect.InvocationTargetException)e).getTargetException();
               if (re instanceof
com.synxis.srms.exception.SrmsException)
               {
                   com.synxis.srms.exception.SrmsException ex =
(com.synxis.srms.exception.SrmsException)re;
                   //System.out.println("Encoding exception code in to
header " + ex.getCode());
                   Message msg = msgContext.getRequestMessage();
                   if (msg == null)
                       return;

                   SOAPEnvelope env = msg.getSOAPEnvelope();
                   SOAPHeaderElement header = new
SOAPHeaderElement("http://xml.apache.org/axis/exception",
                                                                   
"exceptionCode",
                                                                    new
Integer(ex.getCode()));
                   env.addHeader(header);
               }
           }
       }
       catch(Exception e)
       {
           System.out.println("Got exception in OnFault in Handler");
           e.printStackTrace();
       }
    }
};


So, on the request, if there is an fault, onFault() is called.  If
the exception is one of our SrmsExceptions we get the code
(ex.getCode()) and stick it in the header (env.addHeader(header)).

Then, on the response, to the client, we check for an envelope
and a header.  If one exists we look for our header element and
get the data (code) from it.  We then create a new SrmsException
with the code as the value and throw that to be caught by the
client.

The only strange thing we had to do (besides the rest of it. ;])
was to clear the envelope body so that the original fault is
not maintained and sent back to the client.

I hope this isn't too confusing, and I hope it helps.  As you can
tell, we haven't cleaned it all up yet, but it works.  

|)ave

dowens@synxis.com

On Wed, 2002-06-12 at 13:11, Sam Kapoor wrote:
> Hi Sylvain:
> 
> Yes that's what I thought too.  If I can throw an AxisFault then I 
> should be able to throw a descendant.
> Well actually the exception class that I have defined on my server side 
> is a descendant of Exception.
> EInvalidCustomer = class(Exception)
> 
> And I am throwing that on my server.
> If I catch it on the client it never goes to that catch block.  It will 
> however go to an AxisFault catch block.
> I think that custom exception mappings is not yet supported in Axis.
> 
> Any custom Java exception is converted to an AxisFault by the Axis 
> Engine and on the client you can catch an AxisFault but not an 
> EInvalidCustomer
> 
> If you get this to work please let me know.
> 
> Thanks:
> 
> -Sam
> 
> St-Germain, Sylvain wrote:
> 
> >I may be misunderstanding your question but since I can throw an AxiFault
> >shouldn't I be able to throw a descendent of AxisFault and, assuming it is a
> >known type, expect the serialization to occur?
> >
> >Sylvain.
> >
> >
> >-----Original Message-----
> >From: Bob Cotton [mailto:bcotton@synxis.com]
> >Sent: Tuesday, June 11, 2002 8:41 PM
> >To: axis-user@xml.apache.org
> >Subject: Re: Custom Exceptions
> >
> >
> >>>>>>"Sam" == Sam Kapoor <skapoor@borland.com> writes:
> >>>>>>
> >
> >    Sam> Hi: what I want to do is write a custom exception class and
> >    Sam> propagate it from one of the methods on my Web-Service to the
> >    Sam> client.  So I define a Java exception class:
> >
> >    Sam> public class EInvalidCustomer extends Exception {
> >    Sam>  public EInvalidCustomer(String err){
> >    Sam>   super(err);
> >    Sam>  }
> >
> >    Sam> The method on my web-service throws this EInvalidCustomer
> >    Sam> exception.  Now I run the WSDL2Java and I get public class
> >    Sam> EInvalidCustomer extends org.apache.axis.AxisFault
> >
> >    Sam> Also in my WSDL I have a <wsdl:fault
> >    Sam> message="intf:EInvalidCustomer" name="EInvalidCustomer"/>
> >
> >    Sam> So in my client when I call the method I catch 2 exceptions,
> >    Sam> 1 is the RemoteException and the other is EInvalidCustomer
> >    Sam> excpetion.  However, the catch is always going to the
> >    Sam> RemoteException.  Now if I replace EInvalidCustomer with
> >    Sam> AxisFault then the catch will go to the AxisFault.
> >
> >
> >    Sam> I cannot find any example on Axis doc's that show how to pass
> >    Sam> a custom exception class.
> >    Sam> Do you have any ideas????
> >
> >Working through this same issue now. 
> >
> >Axis can describe the Exception in the WSDL (as you've discovered),
> >but actually SENDING the data is not implemented.
> >
> >Until this happens I'm hacking something in using custom Handlers and
> >SOAP headers to pass the data in my exception.
> >
> >Can the development guys shed some light on this? Possibly by beta3?
> >
> >Thanks
> >- Bob
> >
> 
-- 
And in my spare time, I think I'll write some code.


Mime
View raw message