[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[aspectj-dev] Narrowing exception conversions

Hi all,
 
A feature that i would like to see in AspectJ would be the ability to perform narrowing conversions on exceptions thrown inside advice.  For example, i have some advice that runs on many method execution joinpoints.  All of these methods, however, throw different kinds of checked exceptions.  In my advice, i would like to have the ability to throw the most generic type of exception that i want to handle (a Throwable) and have it be automatically casted into the c type of exception that the method the advice is executing around declares.  For example, if one method could throw an IOException and another could throw a FileNotFoundException then i would like to be able to throw these exceptions as Throwables from the body of my advice and have them be casted to an IOException and a FileNotFoundException.
 
My primary reason for wanting this bit of functionality is because i am trying to implement a mock object framework based on aspects.  This approach has some very powerful possibilities that include the ability to create mocks based on concrete classes hassle free, mock up static methods and set expectations on objects that are created inside the method being tested.  These are features that a non-aspect based framework would never be able to provide. 
 
Basically, the framework mocks-up objects by having an aspect which wraps around() advice on all public methods that will be involved in a test.  This method intercepting aspect allows us to by-pass the actual implementation of a method so that the user can set up expectations and dummy values to be returned by the method in question.  In addition to allowing the user to set up return values, a good mock framework must also allow the user to make a method throw an exception.
 
This is where narrowing exception conversions come in.  My mock method intercepting aspect needs to be able to throw any kind of exception so that i can simulate the mock methods throwing the kind of exception that they were set up to throw.  Let me illustrate what i want to do with a code snippet:
 
public classToMock
{
    public int getNumber()
    {
        ...
    }

    public void canThrowException() throws IOException
    {
        ...
    }
}
 
aspect MethodInterceptor
{
    pointcut allPublicMethods(): exection(public * *.*(..));

    Object around() throws Throwable: allPublicMethods()
    {
        ...
        if (someCondition)
        {
            // this could return an IOException or any other kind of throwable!
            // it must be casted into
            throw getThrowable();
        }
        ...
    }
 
    private Throwable getThrowable()
    {
        ...
    }
}
 
As we all know, this code will cause all sorts of compile errors because not all of the public methods that i want to test will throw a Throwable (or anything at all!)  However, code such as this is what i want because i do need to be able to throw exceptions and errors of any type.  Indeed, classes dynamically generated by the java.lang.reflect.Proxy class delegate the implementation of their methods to the java.lang.reflect.InvocationHandler.invoke(...) method which does this exact thing.  Invoke(...) throws a Throwable even though the method that delegated to it may only declare an IOException or no exceptions at all.  In the case where the InvocationHandler.invoke(...) method throws a throwable that isn't declared by the delegating method, an UndeclaredThrowableException is thrown.
 
At first glance it would appear that all that is necessary to implement such a feature is to generate a try/catch block around the advice a weave time so that the throwable could caught and then re-thrown as the correct type.  However, i really don't have a good grasp on anything else that would have to change so don't how much work this feature would be to implement.  I would appreciate knowing if it can be done (or if anyone knows of some other way of doing what i need) and when it could be done because without it i will have to scrap my ideas for an aspect-based framework.
 
Thanks for reading this far ;)  Take it easy,
 
Sean Kirby