[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[aspectj-dev] around advice & exceptions
|
Hello,
I've started a toy project for myself to explore AOP a bit. While
working on it I came across something that I believe is a limitation of
AspectJ language.
I am trying to write a generic aspect for proxy pattern:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
public abstract aspect TransparentProxy perthis(association(Object)) {
public abstract pointcut association(Object o);
public abstract pointcut proxyOperations(Object o);
private Object delegate;
public void setDelegate(Object delegateArg) {
delegate = delegateArg;
}
Object around(Object o) : proxyOperations(o)
{
if (delegate == null)
return proceed(o);
else
return proxyProceed(o, thisJoinPoint);
}
private Object proxyProceed(Object target, JoinPoint tjp) {
MethodSignature sig = ((MethodSignature) tjp.getSignature());
sig.getDeclaringType(); // <<< workaorund for AJ bug >>>
try {
return sig.getMethod().invoke(target, tjp.getArgs());
} catch (IllegalAccessException e) {
throw new RuntimeException("reflection problem", e);
} catch (InvocationTargetException e) {
throw new RuntimeException("business exception",
e.getTargetException()); // <<< limitation here >>>
}
}
}
The problem that I am seeing is that a generic around proxyOperations
clause is not able to declare what checked exceptions will be thrown
inside it, because it is expected to capture joint points with
signatures varying in this regard. This makes it impossible to properly
unwrap and rethrow the exception reported in InvocationTargetException
by the method invoked reflectively in the aspect above.
I've read about exception (re)introduction pattern in AspectJ in Action
book, and I have the impression that a generic solution to this problem
is not possible as of today.
I think I see a possibility of enhancing AspectJ to handle this.
Assumption: The weaver can statically determine the types of exceptions
that can be thrown in the context where the advice is being woven in.
1) create new exception type org.aspectj.lang.UnwrappableException that
would carry an inner Throwable object.
2) when an advice declares it can throw the above exception, weave it in
within a try/catch block, and perform the following logic in the catch
block per each exception type that can be thrown at the join point being
processed: check if the caught WrappableException carries the exception
type, if yes throw it, if not continue. If none of the checks results in
a throw, the WrappableException contained invalid exception - this also
needs to be signalled, with an RuntimeException or Error.
Excuse me if I am not making sense: I have no idea about weaver internals.
A note about <<< workaround for AJ bug >>> line in my example above:
I am getting NPE when calling sig.getMethod() directly. A quick
investigation revealed that declaringType field was null. A naive fix
would be:
public Method getMethod() {
if (method == null) {
if(getDeclaringType() != null) {
try {
method =
declaringType.getDeclaredMethod(getName(),getParameterTypes());
} catch (NoSuchMethodException nsmEx) {
; // nothing we can do, user will see null return
}
}
}
return method;
}
but 1) there are more methods like that getField(), getConstructor() and
so on, and if the fix is valid it should be applied to all of them, 2)
instead of doint that it may be more important to investigate why the
constructor was called with null declaringType arg in the first place.
Rafal