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.