6 Replies Latest reply on Jan 24, 2007 12:50 PM by alrubinger

    RuntimeExceptions caught, wrapped in EJBException

    alrubinger

      Hiya.

      So whenever the container encounters a RuntimeException, it's wrapped and rethrown to the client as an EJBException. This behaviour can be overridden by annotating the RuntimeException with @ApplicationException.

      But what about cases where the RuntimeException is not a custom one? Whenever a NullPointer, ArrayIndexOutOfBounds, etc is encountered, the container is rethrowing these as an EJBException to the client alone, silently swallowing the server error. I want to know if the server encounters an unchecked, undeclared exception in any of my service methods. Namely, I've configured Log4J to email me.

      Anyone have experience dealing with this? How do you address it? Can I globally catch these with an interceptor, run "logger.error()", and rethrow?

      Thanks. :)

      S,
      ALR

        • 1. Re: RuntimeExceptions caught, wrapped in EJBException
          jc7442

          I don't know if it is the best solution but for catching exception I have added an interceptor in ejb3-interceptor.xml. This interceptor is set for remote session bean.

          In my case, interceptor catch exception, logg it on server side and throw a new exception without all the chained exception but just the timestamp of the exceptiopn logged in server side (my problem was that sometimes excpetion chained was server side only exception - not in the classpath on the client).

          See http://www.jboss.com/index.html?module=bb&op=viewtopic&t=97105

          • 2. Re: RuntimeExceptions caught, wrapped in EJBException
            alrubinger

            Wow, great. Looks like the interceptor-based solution will be the way to go. Will try this out and repost. Thanks.

            Always wondered why unchecked/undeclared exceptions get wrapped...

            S,
            ALR

            • 3. Re: RuntimeExceptions caught, wrapped in EJBException
              alrubinger

               

              Always wondered why unchecked/undeclared exceptions get wrapped...


              Will correct myself. I understand why they're wrapped. I do not understand why they are not thrown on the server to generate an error.

              S,
              ALR

              • 4. Re: RuntimeExceptions caught, wrapped in EJBException
                alrubinger

                I've made a little Interceptor to do the trick here, but when configuring, I'm unsure how to signal to AOP that I'd like to intercept "all client calls to the service methods", not "all calls to service methods, including internal ones when a service method calls another".

                I've currently configured ejb3-interceptors-aop.xml with the following:

                <interceptor class="my.UncaughtExceptionInterceptor " scope="PER_VM"/>


                and in each domain:

                <interceptor-ref name="my.UncaughtExceptionInterceptor"/>


                under:

                <bind pointcut="execution(public * *->*(..))">


                What should I denote as my pointcut?...I do still need to be able to throw all checked exceptions, and I'd only like to catch UNCHECKED exceptions invoked by the client.

                Perhaps in the "catch" block of my advice I'd be best to do some:

                if(t instanceof EJBException)


                ...nonsense. Anyone with better suggestions?

                package my.interceptor;
                
                import org.apache.commons.logging.Log;
                import org.apache.commons.logging.LogFactory;
                import org.jboss.aop.advice.Interceptor;
                import org.jboss.aop.joinpoint.Invocation;
                
                import my.ServiceException;
                
                /**
                 * Ensures that all unchecked exceptions caught and rethrown as an EJBException
                 * are logged on the server side
                 *
                 * @author ALR
                 *
                 */
                public class UncaughtExceptionInterceptor implements Interceptor {
                
                 // Class Members
                 private static final Log logger = LogFactory
                 .getLog(UncaughtExceptionInterceptor.class);
                
                 public String getName() {
                 return this.getClass().getName();
                 }
                
                 /**
                 * Carries out the invocation as normal, catching any resulting exceptions
                 * thrown from the container and ensuring that they're logged properly
                 * before being rethrown to the client
                 */
                 public Object invoke(Invocation invocation) throws Exception {
                
                 try {
                 logger
                 .trace(this.getClass().getName()
                 + " intercepted invocation.");
                 return invocation.invokeNext();
                 } catch (Throwable t) {
                 String errorMessage = "Uncaught exception found in Services invocation to "
                 + invocation.getTargetObject()
                 + "."
                 + invocation.toString();
                 logger.warn(errorMessage);
                 throw new ServiceException(errorMessage, t);
                 }
                
                 }
                
                }


                • 5. Re: RuntimeExceptions caught, wrapped in EJBException
                  jc7442

                  For me it looks like this:

                  package fr.toto.interceptor;
                  
                  import java.lang.reflect.Method;
                  import java.lang.reflect.UndeclaredThrowableException;
                  import java.util.logging.Level;
                  import java.util.logging.Logger;
                  
                  import org.jboss.aop.advice.Interceptor;
                  import org.jboss.aop.joinpoint.Invocation;
                  import org.jboss.aop.joinpoint.MethodInvocation;
                  
                  /**
                   * Interceptor in charge to log unexpected exception.
                   *
                   * @author jean-cedricwalmetz
                   *
                   */
                  public class ExceptionHanlderInterceptor implements Interceptor {
                   /**
                   * Version number
                   */
                   private final Logger LOGGER = Logger
                   .getLogger(ExceptionHanlderInterceptor.class.getName());
                  
                   /**
                   * Log unexpected exception and thows an UndeclaredThrowableException
                   */
                   public Object invoke(Invocation invocation) throws Throwable {
                   try {
                   return invocation.invokeNext();
                   } catch (Throwable t) {
                   MethodInvocation methodInvocation = (MethodInvocation) invocation;
                   Method m = methodInvocation.getMethod();
                   Class<?>[] exceptions = m.getExceptionTypes();
                   // Exception is an EJBException.
                   Class<?> clazz = (t.getCause() == null ? t.getClass() : t.getCause()
                   .getClass());// /*.getCause()*/.getClass();
                   for (Class<?> c : exceptions) {
                   if (c.isAssignableFrom(clazz)) {
                   throw t;
                   }
                   }
                   long time = System.currentTimeMillis();
                   LOGGER.log(Level.SEVERE, "Unexpected exception " + time + ":", t);
                   // UndeclaredThrowableException is not perfect since I need to
                   // provide null as parameter to the constructor. But excpetion
                   // thrown has to be a runtime and must be in classpath on client
                   // side.
                   Throwable newException = new UndeclaredThrowableException(null,
                   "Chained exception has been logged on server with reference " + time
                   + " !\nMessage was " + t.getMessage());
                   throw newException;
                   }
                   }
                  
                   /**
                   * Return the name of the interceptor
                   */
                   public String getName() {
                   return ExceptionHanlderInterceptor.class.getName();
                   }
                  }
                  


                  • 6. Re: RuntimeExceptions caught, wrapped in EJBException
                    alrubinger

                    Nice. I'm doing something very similar (reading in declared exceptions, logging if not declared). Thanks for the reinforcement. :)

                    S,
                    ALR