[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-dev] Can aspects throw checked exceptions which are declared on the join point but not referenced on the point cut?

John,

I definitely agree on the need for something like this. I encountered it quite a few times. In fact, AspectJ in Action has a pattern devoted to this problem -- Exception Introduction Pattern. I always felt that a proper support in AspectJ will be really great.

From the language perspective, some variation of the "rethrow" keyword might be appropriate here. Something along the following lines (and here is another use case)...

Object around() : transactional() {
   try {
      begin();
      Object ret = proceed();
      commit();
      return ret;
   } catch (Exception ex) {
      rollback();
      rethrow ex; // or rethrow(ex);
   }
}

In some ways rethrow acts like proceed() -- only in the opposite direction of the call stack. Also there is a symmetry between return and rethrow--one deals with the return value, other with the thrown exception.

The behavior of rethrow is almost like what you are suggesting, except I think rethrow should just throw a runtime exception (say IncomaptibleRethrownException) if the exception being rethrown is not compatible--since we can assume that correct programming is the common case so we can simplify it. The "re" part of rethrow should give sufficient hint to the programmer that it is his responsibility to match the expected semantics. Of course, the IncomaptibleRethrownException may be caught if the return object style is needed.

-Ramnivas

On Mon, Jun 30, 2008 at 5:10 PM, John Watts <john.watts@xxxxxxxxx> wrote:
A similar question has been asked many times, but this one is a slightly more limited case which I think could and should be supported.

First, what is the use case? Function objects. My function object has a run() method which throws Exception declared on an API I don't control. I want to wrap it in around() advice. By the time any exception thrown from proceed() gets back to my advice, it is typed as a generic Exception. I can determine its type and compare it to the join point but I have no way to let AspectJ know that it is safe to throw.

Of course any checked exception thrown from within an aspect must be compatible with the checked exceptions declared for the current join point. However, AspectJ's limitation is currently more restrictive. It requires that any exception thrown from within an aspect must be compatible with the checked exceptions declared for the point cut.

If I want to know whether an exception is compatible with the throws clause of the join point, I can use the following code in my advice:

boolean isExceptionAllowed(Exception e) {
  CodeSignature cs = (CodeSignature) thisJoinPointStaticPart.getSignature();
  Class[] exceptionTypes = cs.getExceptionTypes();
  for (Class<?> exceptionType : exceptionTypes) {
    if (exceptionType.isInstance(e)) {
      return true;
    }
  }
  return false;
}

After getting true from that method, I know that I should be allowed to throw the exception. However I still can't throw it without casting it to a type which is declared on the point cut. I might not know this type. Or there might be a large number. Or they might be different for different join points (all specified by the same point cut).

On the other hand, I could imagine AspectJ providing a function like the following:

Exception throwIfAllowed(Exception e) {
  if (isExceptionAllowed(e)) {
    throw e;
  }
  else {
    return e;
  }
}

Of course this function would have to be declared to throw Exception (defeating the purpose) if I wrote it. But if both functions were declared by AspectJ (in bytecode where necessary) I could safely call them. I could have fallback handling for any exceptions which are not allowed to be thrown.

Thanks,
John

_______________________________________________
aspectj-dev mailing list
aspectj-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-dev