[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
RE: [aspectj-users] Question about around() advice and exceptionhandling

Hi David,

 

Let me build on Wes’s answer. With respect to thisJoinPointStaticPart, Ramnivas submitted a bugzilla entry a while ago requesting that AspectJ add a user object to join point static part. I’d find this useful as an optimization over creating an identity map (especially in cases where you might want to GC the class and you will need a weak identity hash map, and when concurrent access adds complexity).

 

With respect to exception handling, I wonder if you can avoid the issue by changing from using around advice to before and after advice. The most natural way to observe arbitrary exceptions in AspectJ, without having to rethrow them is to use after throwing advice, rewriting code like this:

 

before() : advised() {

     // set up

}

 

after() throwing(Throwable fault) : advised() {

     handleFailure(fault);

}

 

after() returning(Object ret) : advised() {

    handleSuccess(ret);

}

 

The key here is that you don’t have to take any special action to throw the fault in after throwing advice. The one part of this kind of refactoring that can take some work is holding state that was gathered in the before advice. If you need to do this, you might be able to use a perXXX aspect (often percflow, pertarget) or you might use a ThreadLocal.

 

There are ways to work around the normal checked exception rules in Java as applied by AspectJ. However, in a case like this, I’d try to rewrite the advice to avoid needing to rethrow the exception. However, to be complete, here’s some more info on throwing arbitrary throwables from advice from a message I recently sent to aspectj-dev:

 

In odd cases, e.g., for virtual mock object testing frameworks, you
can use other techniques to throw checked exceptions and rely on dynamic
tests to ensure safety. I believe this should be a last resort, rather like
using Java reflections's setAccessible to access non-public members.

This topic has come up before on the AspectJ users mailing list, so a more
full discussion can be read at:

http://dev.eclipse.org/mhonarc/lists/aspectj-dev/msg01412.html

http://dev.eclipse.org/mhonarc/lists/aspectj-dev/msg01400.html (you can
download a direct bytecode implementation of throwing checked exceptions
from the aTrack open source project too).

 


From: aspectj-users-bounces@xxxxxxxxxxx [mailto:aspectj-users-bounces@xxxxxxxxxxx] On Behalf Of David Budworth
Sent: Saturday, September 09, 2006 1:43 PM
To: aspectj-users@xxxxxxxxxxx
Subject: [aspectj-users] Question about around() advice and exceptionhandling

 

Hello folks,

I was looking in to using AspectJ as a replacement for my current JBossAOP based aspects but I got stumped on a few things.

First was the seeming lack of perJoinPoint type constructs.  Which I resolved by making an IdentityHashMap< JoinPoint.StaticPart,MyState> type cache whenever a new joinpoint was executed.  Works basically the same.

Second, I can't seem to figure out how to genericly wrap methods in an around type construct.
In JBossAOP it was as simple as:
@Bind("blah")
public Object adviceMethod(MethodInvocation mi) throws Throwable){
  Object ret = null;
  Object fault = null;
   ...do random stuff this advice wants to do...
   try{
     ret = mi.invokeNext();
   }
   catch(Throwable th){
       fault = th;
   }
   ...do random stuff this advice wants to do...
   if (fault) throw fault;
   return ret;
}



Problem I have in AspectJ is that it seems I must know the target methods declared checked exceptions.  Which isn't really possible. 
example:
@Tx
public void foo() {
   ... foo stuff...
}
@Tx
public void bar() throws Exception{
   ...bar stuff...
}


There seems to be no construct in AspectJ's language (not the AJ 1.5 annotations, I'm using the traditional aspectj style) to have a catch all / rethrow all type thing.

That or I'm just missing it.

I could make an around() aspect with a:

public around() : execution(@Tx * *(..)) {
   boolean failed = true;
   try{
    proceed();
    failed=false;
  }
  finally{
    if (failed) ...do bad thing (rollback / etc) ...
    else ...do good thing (commit / etc)...
  }
}


but that seems odd, plus I'd lose the ability to see how something fails.

I don't want to use soften since it seems to mask the actual exception thrown which would break virtually all of our code (lots of JDBC / JMS stuff)

It's entirely possible that I'm missing the page with the magic syntax of something like
around() throws *? : execution(@Tx * *(..) throws *?)

Aside from my initial hurdles of syntax/convention converting from JBossAOP to AspectJ, I really like the AspectJ way of doing things.

I look forward to taking our JBossAS restart time from 3min back down to ~2min when this conversion is complete (due to limitations in jbaop's aopc we must use loadtime weaving which adds 1+min to our deploy cycle, which is why I'm trying to switch to AspectJ)