Configuring Recovery Callback (using interceptor)

In this post under Spring Retry –> XML Configuration –> Spring AOP, I will show with example how to configure RecoveryCallback using Spring AOP.

For our example we will create a recovery class as shown below

CustomMethodInvocationRecoverer

package defaultPackage;

import org.springframework.retry.interceptor.MethodInvocationRecoverer;

public class CustomMethodInvocationRecoverer implements MethodInvocationRecoverer<Void> {
    @Override
    public Void recover(Object[] args, Throwable cause) {
        System.out.println("Recovered");
        return null;
    }
}

As shown in the above code, the class “CustomMethodInvocationRecoverer” implements “Spring Retry” provided interface “MethodInvocationRecoverer” and provides logic for its “recover” method.

This “recover” method will have the recovery logic. This method receives two parameters
1) The arguments of the method that failed.
2) The cause of the failure

and returns null.

Below is the xml configuration

XML configuration

1  <?xml version="1.0" encoding="UTF-8"?>
2  <beans xmlns="http://www.springframework.org/schema/beans"
3  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4  xmlns:aop = "http://www.springframework.org/schema/aop"
5  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
6  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
7      <aop:config>
8          <aop:pointcut id="transactional" expression="execution(* defaultPackage.Service1.executeWithException(..))"/>
9          <aop:advisor pointcut-ref="transactional" advice-ref="retryAdvice"/>
10     </aop:config>
11     
12     <bean id="recovery" class="defaultPackage.CustomMethodInvocationRecoverer"/>
13     
14     <bean id="retryAdvice" class="org.springframework.retry.interceptor.RetryOperationsInterceptor">
15         <property name="retryOperations" ref="retryTemplate"/>
16         <property name="recoverer" ref="recovery"/>
17     </bean>
18     
19     <bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate">
20         <property name="retryPolicy" ref="retryPolicy"/>
21     </bean>
22     
23     <bean id="retryPolicy" class="org.springframework.retry.policy.MaxAttemptsRetryPolicy">
24         <property name="maxAttempts" value="5"/>
25     </bean>
26     
27     <bean id="service1" class="defaultPackage.Service1"/>
28 </beans>

In the above xml file, at line 12, I have created a bean named “recovery” and is of class “CustomMethodInvocationRecoverer”.

At line 16, I refer that bean and set it to “RetryOperationsInterceptor” bean.

At runtime this “RetryOperationsInterceptor” bean is wrapped around our “service1” bean.

When “Service1” bean “executeWithException” method is called and an exception is thrown from that method, this wrapped around interceptor will retry the operations 5 times and if failed even after 5th
time, the recovery logic stored in “recovery” bean is called.

In this way we can configure “RecoveryCallback” using Spring AOP.

Below is the complete main method for your reference

Main class

package defaultPackage;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Example40 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("resources\\Example29.xml");
        Service1 service1 = (Service1)context.getBean("service1");

        service1.executeWithException();
    }
}

Below is the output

Output

[INFO] ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@27abe2cd: startup date [Thu Nov 16 13:07:06 IST 2023]; root of context hierarchy
[INFO] XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [resources/Example29.xml]
Executing method 'executeWithException' : 1
Executing method 'executeWithException' : 2
Executing method 'executeWithException' : 3
Executing method 'executeWithException' : 4
Executing method 'executeWithException' : 5
Recovered

Leave a Reply