Results 1 to 6 of 6

Thread: Throws advice not working although my before advice is

  1. #1
    Join Date
    Sep 2005
    Location
    Chicago, IL
    Posts
    143

    Default Throws advice not working although my before advice is

    I am trying to write 2 pieces of advice: a "before advice" which logs a Message object during a normal flow and an "after-throwing" advice that logs the message when an exception happens.

    My "before advice" is working but for some reason I cannot get my "after-throws" advice to work.

    Here is my XML definition:
    Code:
    <aop:config>
    
            <aop:pointcut id="exceptionPointcut" expression="execution(* com.test.cwp.integration.exchange.hub..*.*(..))"/>
            <aop:pointcut id="auditLogPointcut" expression="execution(* com.test.cwp.integration.exchange.hub..*.*(..)) and args(message,..)"/>
    
            <aop:aspect ref="integrationSystemAdvice">
                <aop:after-throwing method="handleMessageException" pointcut-ref="exceptionPointcut" throwing="exception"/>
                <aop:before method="logMessage" pointcut-ref="auditLogPointcut" arg-names="message" />
            </aop:aspect>
    
        </aop:config>
    My two methods in my advice are:
    Code:
    public void handleMessageException(Exception exception)
        {
            System.out.println("#######\n\n" + "Exception logged: " + exception + "##\n\n\n");
        }
    
    public void logMessage(Message message)
        {
            TextMessage m = (TextMessage) message;
            try
            {
                System.out.println("#######\n\n" + "message in logMessage: " + m.getText() + "##\n\n\n");
            }
            catch (JMSException e)
            {
                e.printStackTrace();
            }
        }
    I'm running the following method in a test case in the package: com.test.cwp.integration.exchange.hub

    Code:
    public void processMessage(Message message) throws Exception
        {
            TextMessage tMessage = (TextMessage) message;
    
            throw new Exception("testing");
        }
    With this setup, the "before advice" is running properly and my message is printed out in my logMessage method in my advice bean. However, when I throw the new Exception("testing"), it never calls my after-throwing method handleMessageException. What's interesting is the stack trace for the exception I am manually throwing. It is:
    Code:
     java.lang.Exception: testing
         at com.test.cwp.integration.exchange.hub.ExchangeHubMessageListener.processMessage(ExchangeHubMessageListener.java:33)
         at com.test.cwp.integration.exchange.hub.ExchangeHubMessageListener.onMessage(ExchangeHubMessageListener.java:19)
         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:85)
         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:58)
         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java(Compiled Code))
         at java.lang.reflect.Method.invoke(Method.java(Compiled Code))
         at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:301)
         at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
         at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
         at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:50)
         at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:160)
         at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:54)
         at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
         at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
         at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
         at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
         at $Proxy7.onMessage(Unknown Source)
         at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:510)
         at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:445)
         at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:414)
         at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:309)
         at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:254)
         at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:870)
         at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:810)
         at java.lang.Thread.run(Thread.java:570)
    If I remove the pointcut for my after-throws advice, then none of the AOP methods are involved when the exception it thrown. Clearly the pointcut is matching the exception since when I remove the pointcut, the aop method calls are gone.

    I'm really out of ideas. Does anyone have any thoughts? I'm using Spring 2.5.0 on WAS 5.1 with JDK 1.4.2

    Thanks!
    Grant Gochnauer
    Vodori Inc.
    Personal Blog

  2. #2
    Join Date
    Sep 2005
    Location
    Chicago, IL
    Posts
    143

    Default

    As an addendum, the processMessage(Message message) is in a class called ExchangeHubMessageListener which implements javax.jms.MessageListener. The processMessage method is not in an interface so I tried adding proxy-target-class="true" to my <aop:config> but now I get the stack trace:

    Code:
     java.lang.Exception: testing
         at com.test.cwp.integration.exchange.hub.ExchangeHubMessageListener.processMessage(ExchangeHubMessageListener.java:33)
         at com.test.cwp.integration.exchange.hub.ExchangeHubMessageListener.onMessage(ExchangeHubMessageListener.java:19)
         at com.test.cwp.integration.exchange.hub.ExchangeHubMessageListener$$FastClassByCGLIB$$42df09a9.invoke(<generated>)
         at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
         at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:696)
         at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
         at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:50)
         at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:160)
         at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:54)
         at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
         at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
         at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
         at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:631)
         at com.test.cwp.integration.exchange.hub.ExchangeHubMessageListener$$EnhancerByCGLIB$$4b267dd9.onMessage(<generated>)
         at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:510)
         at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:445)
         at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:414)
         at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:309)
         at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:254)
         at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:870)
         at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:810)
         at java.lang.Thread.run(Thread.java:570)
    This is a different stack trace than if I leave out the proxy-target-class="true".

    I'm still unable to figure out why the after-throwing advice isn't calling my advice method while the before one is.
    Grant Gochnauer
    Vodori Inc.
    Personal Blog

  3. #3
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,695

    Default

    With Spring AOP you can only intercept method calls INTO the object. You say that your object is a MessageListener, that interface has 1 method which is externally called, onMessage with a Message as parameter (hence the matching of your before method).

    I expect some exception handling in the onMessage method of the ExchangeHubMessageListener so the after-throws is never triggered (it is an internal method call not an external method call).

    If you want full control you will need to use loadtime or compile time weaving.

    Jörg has written also some nice stuff concerning proxies.
    Last edited by Marten Deinum; Jan 31st, 2008 at 01:43 AM.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  4. #4
    Join Date
    Nov 2005
    Posts
    2

    Default

    I have a similar problem, and would like to know if there is any other solution for generic logging of exceptions that doesn't require AspectJ.

    The reason I ask is that I have used both compile time and load time weaving. Compile time weaving works great, but slows down our automated builds so much that it is taking several hours to complete, a significant amount of that time in the AspectJ compiler. This is becoming a real problem for us, particularly as we may be working on one of several branches and may never see a build of our code changes finish in a day.

    We tried load time weaving, but our application jumped to twice its memory usage. As the build time suggests, this is a very large application and requiring twice the memory to be installed wasn't an option, particularly as we are running up against the 32bit limits at some sites.

    So my question is, is there some way we can replace "exception logging by catching the exception in a pointcut" with something else that Spring AOP could support? Something that wouldn't require us to manually add log messages to each catch block.

    FYI, here is the advice we use:

    Code:
    public aspect ExceptionLogging
    {
        private Logger exceptionLogger = Logger.getLogger(ExceptionLogging.class);
    
        pointcut exceptionHandlers(Throwable t) : handler(Throwable+) && (args(t));
    
        before(Throwable t) : exceptionHandlers(t)
        {
            // exclude handlers in methods annotated by @SuppressExceptionLogging
            Method enclosingMethod = ((MethodSignature)thisEnclosingJoinPointStaticPart.getSignature()).getMethod();
            if(enclosingMethod.isAnnotationPresent(SuppressExceptionLogging.class))
                return;
            exceptionLogger.error(t.toString(), t);
        }
    }
    Last edited by pedxing; Jan 30th, 2008 at 08:09 PM.

  5. #5
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,695

    Default

    Loadtime and compile time weaving are much more powerfull then proxy based AOP. You could try to use the proxy based approach but that would only allow you to intercept calls INTO objects, internal method calls wouldn't be intercepted.

    Chapter 6 of the reference guide explains the AOP possibilities for Spring.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  6. #6
    Join Date
    Nov 2005
    Posts
    2

    Default

    Yes, I have read the reference manual a few times (on each major release). And I have tried to think of a method to do exception logging that would use the features of Spring AOP rather than requiring the full power of AspectJ, but have so far been unsuccessful.

    My question is whether anyone else has had a flash of insight and discovered a way to do this that I haven't thought of?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •