Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AOP Exception Handling

I see that Guice and Spring use AOP Alliance under the hood for method interceptions, and I've been trying to figure out how to get AOP Alliance to intercept and handle certain exceptions so I don't have to keep writing the same code over and over again inside every catch block.

But after reviewing the play, it doesn't look like AOP Alliance provides any way to intercept thrown Throwables in such a way that the handler/interceptor can do some things (log the exception, etc.) and then determine whether or not to propagate the exception any further or to just recover back to the next line following the line which threw the exception:

HerpDerp hd = null;

if(hd == null)
    throw new RuntimeException("Herpyl derp!");

Manny.pacquiao();

I'm looking for an AOP exception handling mechanism that would intercept the RuntimeException and use business logic to decide whether to keep propagating it or to recover back at the Manny.pacquioa() call.

  • If it is just not possible to do this in Java, please let me know
  • Regardless of whether or not its possible to do this in Java, is there a way to intercept thrown Exception with AOP Alliance or do I have to go somewhere else. And if I have to go somewhere else, where? AspectJ?

Thanks!

like image 994
IAmYourFaja Avatar asked Jun 08 '12 11:06

IAmYourFaja


People also ask

What is AOP used for in Spring?

Aspect-oriented programming (AOP) is one of the major components of the Spring Framework. The Spring AOP helps in breaking down the logic of the program into several distinct parts called as concerns. Cross-cutting concerns is the functions which span multiple points of an application.

How does AOP work in Spring boot?

AOP (Aspect-Oriented Programming) is a programming pattern that increases modularity by allowing the separation of the cross-cutting concern. These cross-cutting concerns are different from the main business logic. We can add additional behavior to existing code without modification of the code itself.

Is Controller advice AOP?

@ControllerAdvice is one of the AOP features Spring offers. The main difference in use case is that @ControllerAdvice is wired up by the Spring MVC infrastructure and uses (and provides) Web-specific features.

What is a Pointcut AOP?

Pointcut is a set of one or more JoinPoint where an advice should be executed. You can specify Pointcuts using expressions or patterns as we will see in our AOP examples. In Spring, Pointcut helps to use specific JoinPoints to apply the advice.


4 Answers

You can catch exceptions with Spring AOP, but I do not know if that matches your requirement for a pure Java framework.

With Spring, you can write a simple AOP interceptor as something like:

@Aspect
public class ErrorInterceptor{
@AfterThrowing(pointcut = "execution(* com.mycompany.package..* (..))", throwing = "ex")
public void errorInterceptor(WidgetException ex) {
    if (logger.isDebugEnabled()) {
        logger.debug("Error Message Interceptor started");
    }

    // DO SOMETHING HERE WITH EX
    logger.debug( ex.getCause().getMessage());


    if (logger.isDebugEnabled()) {
        logger.debug("Error Message Interceptor finished.");
    }
}
}

but there is no way to return to the calling method or continue processing on the subsequent line. However if you handle the exception here, it won't bubble up the chain unless you rethrow it yourself.

like image 66
Eric B. Avatar answered Oct 29 '22 20:10

Eric B.


There's a reason that this doesn't exist. It would require rewriting the block structure of your code as if you'd written the try/catch block in the first place. This, it seems to me, potentially plays havoc with variable scope and other things. You're asking AOP to rewrite the byte code to be something like the following code, and that's quite a rewrite.

HerpDerp hd = null;

try {
    if(hd == null)
        throw new RuntimeException("Herpyl derp!");
} catch(RuntimeException e) {
   if (someConditionIsMet) {
       throw e;
   }
}

Manny.pacquiao();
like image 33
bmargulies Avatar answered Oct 29 '22 19:10

bmargulies


@4herpsand7derpsago If what you're trying to do is to catch the thrown exception using AOP to perform various task to handle it and then comes back to the code where the exception originally thrown, I think you miss understand the concept of AOP.

As you point out in your code

HerpDerp hd = null;

if(hd == null)
throw new RuntimeException("Herpyl derp!");

Manny.pacquiao();

If you want AOP to catch your RuntimeException, perform some stuff to handle it and comes back to Manny.pacquiao();, the answer is you can't. The reason is because when the RuntimeException is thrown and caught by AOP, the stack is already at your AOP code. you can't comes back to execute Many.pacquiao();. The only way if you want to continue executing Many.pacquiao(); is by using try-finally block as follow

HerpDerp hd = null;

try {
    if(hd == null)
        throw new RuntimeException("Herpyl derp!");
} finally {
    Manny.pacquiao();
}

Only then your Many.pacquiao() will get executed, but before your AOP catch the RuntimeException

like image 25
Wins Avatar answered Oct 29 '22 21:10

Wins


To "catch" uncaught exceptions with AspectJ, you can use the following aspect:

pointcut uncaughtExceptionScope() : 
    (execution(* com.mycompany.myrootpackage..Main.main(..)) 
    || execution(* java.util.concurrent.Callable+.call()) 
    || execution(* java.lang.Runnable+.run()) 
    ));

after() throwing(Throwable t) : uncaughtExceptionScope() && !cflow(adviceexecution())    {
    handleException(thisJoinPoint, t);
}   

protected void handleException(JoinPoint jp, Throwable t)
{
    // handle exception here
}

I do not think it is possible to "go back" to the execution point.

like image 30
Wim Deblauwe Avatar answered Oct 29 '22 20:10

Wim Deblauwe