Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring AOP AfterThrowing vs. Around Advice

Tags:

when trying to implement an Aspect, that is responsible for catching and logging a certain type of error, I initially thought this would be possible using the AfterThrowing advice. However it seems that his advice doesn't catch the exception, but just provides an additional entry point to do something with the exception.

The only advice which would also catch the exception in question would then be an AroundAdvice - either that or I did something wrong.

Can anyone assert that indeed if I want to catch the exception I have to use an AroundAdvice? The configuration I used follows:

@Pointcut("execution(* test.simple.OtherService.print*(..))") public void printOperation() {}  @AfterThrowing(pointcut="printOperation()", throwing="exception") public void logException(Throwable exception) {   System.out.println(exception.getMessage()); }  @Around("printOperation()") public void swallowException(ProceedingJoinPoint pjp) throws Throwable {   try {     pjp.proceed();   } catch (Throwable exception) {     System.out.println(exception.getMessage());   } } 

Note that in this example I caught all Exceptions, because it just is an example. I know its bad practice to just swallow all exceptions, but for my current use case I want one special type of exception to be just logged while avoiding duplicate logging logic.

like image 405
whiskerz Avatar asked Mar 23 '10 17:03

whiskerz


People also ask

What are the different types of advice in Spring AOP?

In Spring AOP, 4 type of advices are supported : Before advice – Run before the method execution. After returning advice – Run after the method returns a result. After throwing advice – Run after the method throws an exception.

How does AfterThrowing advice work?

After throwing advice: Advice to be executed if a method exits by throwing an exception. After (finally) advice: Advice to be executed regardless of the means by which a join point exits (normal or exceptional return). Around advice: Advice that surrounds a join point such as a method invocation.

What will after advice do in Spring AOP?

After advice is used in Aspect-Oriented Programming to achieve the cross-cutting. It is an advice type which ensures that an advice runs after the method execution. We use @After annotation to implement the after advice.


2 Answers

The Spring reference doc says:

"After throwing advice runs when a matched method execution exits by throwing an exception"

By then it's too late to catch the exception as it has already been thrown and the method has exited. The approach you've taken with the @Around advice is the only way to actually catch the exception and deal with it before the method exits.

like image 119
Shane Bell Avatar answered Sep 22 '22 18:09

Shane Bell


Actually, it is possible to catch exception within AfterThrowing advice as well. I know it is a convoluted example, but it works.

@Aspect @Component class MyAspect {      @Autowired     public Worker worker;      @Pointcut(value = "execution(public * com.ex*..*.*(..))")     public void matchingAll(){}      @AfterThrowing(pointcut = "matchingAll()", throwing = "e")     public void myAdvice(RuntimeException e){         Thread.setDefaultUncaughtExceptionHandler((t, e1) ->                  System.out.println("Caught " + e1.getMessage()));         System.out.println("Worker returned " + worker.print());     } }  @Component class Worker {      public static int value = 0;      public int print() {         if (value++ == 0) {             System.out.println("Throwing exception");             throw new RuntimeException("Hello world");         } else {             return value;         }     } }  @SpringBootApplication @EnableAspectJAutoProxy public class AdvicesDemo {      public static void main(String[] args) {         final ConfigurableApplicationContext applicationContext = SpringApplication.run(AdvicesDemo.class);         final Worker worker = applicationContext.getBean(Worker.class);         System.out.println("Worker returned " + worker.print());         System.out.println("All done");     } } 

As you can see it is more about how to catch originally thrown exception and thus prevent its propagation back to the caller.

Working example on GitHub (check com.example.advices package)

like image 45
fg78nc Avatar answered Sep 21 '22 18:09

fg78nc