Skip to main content

[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


Back to the top