Spring AOP AspectJ @AfterThrowing Example

This Spring AOP tutorial will teach us to use AspectJ @AfterThrowing annotation. The @AfterThrowing annotation is an excellent solution for addressing cross-cutting concerns related to exceptions. It allows to gracefully handle exceptions thrown during the execution of the advised methods.

The Spring AOP @AfterThrowing annotation enables developers to define advice that executes after a method throws an exception. This proves very useful in scenarios where we need to implement specific actions or handle exceptions gracefully.

In this example, we will create a simple Spring application, add a logging aspect, and then invoke aspect methods based on pointcuts information passed in @AfterThrowing annotation.

1. AspectJ @AfterThrowing Annotation Usage

The AspectJ @AfterThrowing advice is executed after a joinpoint does not complete normally and ends up throwing an exception. To create an @AfterThrowing advice use this annotation on the advice method, and use the ‘throwing‘ attribute to capture the thrown exception.

import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

  private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);

  @AfterThrowing(pointcut = "execution(* com.howtodoinjava.core.aop.service.EmployeeService.*(..))", throwing = "ex")
  public void afterThrowingAdvice(Exception ex) {
    // Custom logic after the method throws an exception
    logger.error("After throwing advice: Exception caught - " + ex.getMessage());
    // Additional handling or logging can be implemented here
  }
}

The matching XML configuration is:

<!-- Enable AspectJ auto proxy -->
<aop:aspectj-autoproxy />

<!-- Define the aspect -->
<bean id="loggingAspect" class="com.howtodoinjava.core.aop.aspects.LoggingAspect" />

<!-- Configure the aspect and pointcut -->
<aop:config>
  <aop:aspect id="afterThrowingAspect" ref="loggingAspect">
    <aop:pointcut id="afterThrowingPointcut"
        expression="execution(* com.howtodoinjava.core.aop.service.EmployeeService.*(..))" />
    <aop:after-throwing method="afterThrowingAdvice"
        throwing="ex"
        pointcut-ref="afterThrowingPointcut" />
  </aop:aspect>
</aop:config>

2. Run Advice on Specific Exception Type

Often we want the advice to run only when exceptions of a given type are thrown. We can define the desired exception type as the method argument.

When a method execution exits by throwing a CustomException (or its subtype), the exception will be passed to the advice method as the corresponding argument value. In case the exception type differs, the advice will not be executed.

@AfterThrowing(pointcut = "...", throwing = "ex")
public void afterThrowingAdvice(CustomException ex) {
	 
	//...
}

3. Handling Exceptions

To handle exceptions caught by @AfterThrowing advice, we must define the logic within the advice method.

To handle the exception, generally, we can perform any actions such as logging, notifying, or transforming the exception. Optionally, we can rethrow the exception or suppress it based on the application’s requirements.

In the following example, we are transforming the exception to IllegalArgumentException. You can write your custom logic.

@AfterThrowing(pointcut = "...", throwing = "ex")
public void afterThrowingAdvice(Exception ex) {

  logger.error("After throwing advice: Exception caught - " + ex.getMessage());
  throw new IllegalArgumentException("Exception handled in aspect", ex);
}

Always remember to adapt the exception-handling logic based on the application’s needs, and consider the impact of the chosen approach on the overall error-handling strategy.

4. Demo

When we run any method in the class com.howtodoinjava.core.aop.service.EmployeeService then we can see that the afterThrowingAdvice() is executed after it throws an exception.

In the following EmployeeService class, the save() method throws NullPointerException if the method argument is null.

@Service
public class EmployeeService {

  private static final Logger logger = LoggerFactory.getLogger(EmployeeService.class);

  public Employee save(Employee employee) {
    logger.info("Saving the Employee...");
    if(employee == null){
      throw new NullPointerException("Input is null");
    }
    return employee;
  }
}

Let’s run a method, pass the null argument, and verify the output.

import com.howtodoinjava.core.aop.service.EmployeeService;
import com.howtodoinjava.core.demo.beans.Employee;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {

  public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

    EmployeeService employeeService = context.getBean(EmployeeService.class);
    employeeService.save(null);

    context.close();
  }
}

The program output is:

2023-11-27T14:24:42.001+0530 INFO Saving the Employee...
2023-11-27T14:24:42.002+0530 ERROR After throwing advice: Exception caught - Input is null

5. Maven

To get the @AfterThrowingAdvice annotation working, we need to ensure that Spring AOP is setup correctly. So make sure we have the following dependencies:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>6.1.1</version>
</dependency>

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>6.1.1</version>
</dependency>

<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.20</version>
</dependency>

6. Enabling AOP

Also, we must enable the AOP support to @Aspect annotation to work.

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class AppConfig {
  //...
}

7. Conclusion

The AafterThrowingAdvice annotation in Spring AOP with AspectJ provides a powerful mechanism for handling exceptions in a modular and maintainable way. But we must keep remember that if the target method executes without throwing an exception, the @AfterThrowing advice will not be invoked.

Happy Learning !!

Soure Code on Github

Comments

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.