Spring AOP AfterThrowing Advice Annotation Example

0

In this article, we will see an example of Spring AOP @AfterThrowing advice annotation.

An after throwing advice is executed only when an exception is thrown by a method and you want to handle the exception separately.

Think of a scenario where a system gets off the network due to some network issue, other systems connected to it, may want to keep trying to reconnect till they are successful. The strategy may differ system to system and you want to let them configure it.

Thus you may want to treat the re-connection strategy as a separate concern and deal it as a cross-cutting concern.

Simple test bean

To demonstrate the example of @AfterThrowing advice, we will make use of a simple test bean that contains method greet(String). If the greeting message is null, the method will throw a NullPointerException. If the greeting message is other than ‘Hello’, method will throw NotAGreetingException. Ok, that sounds simple.

TestBean:

package com.javarticles;

public class TestBean {
    
    public String greet(String a) {
        System.out.println("methodA(" + a + ") called");
        if (a == null) {
            throw new NullPointerException();
        }
        if (!"HELLO".equals(a.toUpperCase())) {
            System.out.println("Throw NotAGreetingException");
            throw new NotAGreetingException();
        }
        return a;
    }    
}

 

NotAGreetingException:

package com.javarticles;

public class NotAGreetingException extends RuntimeException {

}

AfterThrowing Annotation

We will declare an aspect using @Aspect type annotation. Next, we will define the After Throwing advice using @AfterThrowing. The pointcut expression is generic, applies on all methods.

@AfterThrowing(value = "execution(* *.*(..))")

AopBean:

package com.javarticles;

import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AopBean {

    @AfterThrowing(value = "execution(* *.*(..))")
    public void afterAnyMethod() {
        System.out
                .println("@After AOP afterAnyMethod(), execution point: '* *.*(..)'");
    }  
}

Include <aop:aspectj-autoproxy/> for spring to parse the annotations and create proxies. Declare TestBean and AopBean.

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

	<bean id="testBean" class="com.javarticles.TestBean"/>
    <aop:aspectj-autoproxy/>
	<bean id="aopBean" class="com.javarticles.AopBean"/>
	
</beans>

Let’s run the example. Load spring context and get TestBean.

Our main class, makes call to method greet(). It first passes ‘Hello’ as argument so that the method runs through. Next, it passes null, so that the method throws NullPointerException. Our AfterThrowing should handle this exception.

Finally, it passes something other than ‘hello’.

It should throw NotAGreetingException.

SpringAopAfterThrowingExample:

package com.javarticles;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringAopAfterThrowingExample {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                "applicationContext.xml");
        TestBean testBean = (TestBean) context.getBean("testBean");
        System.out.println("Call testBean.methodA(Hello)");
        testBean.greet("Hello");        
        try {
            System.out.println("********************************");
            System.out.println("Call testBean.methodA(null)");
            testBean.greet(null);
        } catch (Exception e) {
            System.out.println("Exception: " + e.toString());
        }
        try {
            System.out.println("********************************");
            System.out.println("Call testBean.methodA('Are u there?')");
            testBean.greet("Are u there?");
        } catch (Exception e) {
            System.out.println("Exception: " + e.toString());
        } finally {
            context.close();
        }
    }
}

As yo can see AfterThrowing advice manages to handle both NullPointerException and NotAGreetingException.

Output:

Call testBean.methodA(Hello)
methodA(Hello) called
********************************
Call testBean.methodA(null)
methodA(null) called
@After AOP afterAnyMethod(), execution point: '* *.*(..)'
Exception: java.lang.NullPointerException
********************************
Call testBean.methodA('Are u there?')
methodA(Are u there?) called
Throw NotAGreetingException
@After AOP afterAnyMethod(), execution point: '* *.*(..)'
Exception: com.javarticles.NotAGreetingException

Declare Exception as Argument Type

Suppose, we are only interested in handling a specific exception.In such cases, we need to include a throwing attribute to the @AfterThrowing annotation. It is this parameter that tells Spring which exceptions should be handled by the advice. Next, you need to declare it as the argument type of the exception.

If the argument type is Throwable then the AfterThrowing advice will handle all errors and exceptions. In our case, we are interested only in NotAGreetingException so the argument type is of type NotAGreetingException

AopBean:

package com.javarticles;

import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AopBean {

    @AfterThrowing(value = "execution(* *.*(..))")
    public void afterAnyMethod() {
        System.out
                .println("@After AOP afterAnyMethod(), execution point: '* *.*(..)'");
    }  
 
    @AfterThrowing(value = "execution(* *.*(..))", throwing="e")
    public void afterGreeting(NotAGreetingException e) {
        System.out
                .println("@After AOP afterGreeting(), execution point: '* *.*(..)' e<" + e + ">");
    } 
}

Output:

Call testBean.methodA(Hello)
methodA(Hello) called
********************************
Call testBean.methodA(null)
methodA(null) called
@After AOP afterAnyMethod(), execution point: '* *.*(..)'
Exception: java.lang.NullPointerException
********************************
Call testBean.methodA('Are u there?')
methodA(Are u there?) called
Throw NotAGreetingException
@After AOP afterAnyMethod(), execution point: '* *.*(..)'
@After AOP afterGreeting(), execution point: '* *.*(..)' e
Exception: com.javarticles.NotAGreetingException

Download the source code

This was an example about Spring AOP @AfterThrowing annotation.

You can download the source code here: springAopAfterExceptionAdviceAnnotationExample.zip
Share.

Comments are closed.