Announcement Announcement Module
Collapse
No announcement yet.
Throws advice not working although my before advice is Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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!

  • #2
    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.

    Comment


    • #3
      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, 02:43 AM.

      Comment


      • #4
        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, 09:09 PM.

        Comment


        • #5
          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.

          Comment


          • #6
            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?

            Comment

            Working...
            X