In this post under Spring Retry, I will show with example how to combine multiple retry policies.
Below is the xml configuration
XML code
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 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
5 <bean id="maxAttemptsRetryPolicy1" class="org.springframework.retry.policy.MaxAttemptsRetryPolicy">
6 <property name="maxAttempts" value="3"/>
7 </bean>
8
9 <bean id="maxAttemptsRetryPolicy2" class="org.springframework.retry.policy.MaxAttemptsRetryPolicy">
10 <property name="maxAttempts" value="6"/>
11 </bean>
12
13 <bean id="retryPolicy" class="org.springframework.retry.policy.CompositeRetryPolicy">
14 <property name="policies">
15 <list value-type="org.springframework.retry.RetryPolicy">
16 <ref bean="maxAttemptsRetryPolicy1"/>
17 <ref bean="maxAttemptsRetryPolicy2"/>
18 </list>
19 </property>
20 </bean>
21
22 <bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate">
23 <property name="retryPolicy" ref="retryPolicy"/>
24 </bean>
25
26 <bean id="service1" class="Service1"/>
27 </beans>
In the above xml code, at line 5, I create bean definition named “maxAttemptsRetryPolicy1” for “MaxAttemptsRetryPolicy” class with “maxAttempts” property value as 3.
At line 9, I create bean definition named “maxAttemptsRetryPolicy2” for “MaxAttemptsRetryPolicy” class with “maxAttempts” property value as 6.
Now i add both the retry policies in a list and set it as value to “policies” property of “CompositeRetryPolicy” class. Please refer to bean definition from line 13 to 20.
Whenever a failed operation is retried, CompositeRetryPolicy loops through the list and calls each retry policies (in the order they are added) to figure out whether to retry or not. If all the retry policies in the list return true, the failed operation is retried. If anyone of the retry policies return false, the failed operation will not be retried. This behaviour can be changed by setting the “optimistic” boolean property of “CompositeRetryPolicy” class to true. By default this property is false.
In our example also “optimistic” property is false.
Below is the output
Output
[INFO] ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5ce81285: startup date [Sat Jan 29 09:40:15 IST 2022]; root of context hierarchy
[INFO] XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [Example11.xml]
Executing method 'executeWithException' : 1
Executing method 'executeWithException' : 2
Executing method 'executeWithException' : 3
java.lang.NullPointerException
at Service1.executeWithException(Service1.java:8)
at Example11.lambda$0(Example11.java:12)
at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:329)
at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:209)
at Example11.main(Example11.java:12)
As you can see from the output the failed operations is retried only 3 times because “optimistic” property is false and “maxAttemptsRetryPolicy1” will return false on 4th attempt. Causing the failed operation to end throwing exception.
In this way we can combine multiple retry policies.
Below is the Service and main class for your reference.
Service class
public class Service1 {
private int i = 0;
private int j = 0;
public void executeWithException() {
i = i + 1;
System.out.println("Executing method 'executeWithException' : " + i);
throw new NullPointerException();
}
public void executeWithoutException() {
j = j + 1;
System.out.println("Executing method 'executeWithoutException' : " + j);
}
public String recovery() {
return "Recovered";
}
}
Main class
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.retry.support.RetryTemplate;
public class Example11 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Example11.xml");
Service1 service1 = (Service1)context.getBean("service1");
RetryTemplate retryTemplate = (RetryTemplate)context.getBean("retryTemplate");
try {
retryTemplate.execute((retryContext) -> { service1.executeWithException(); return null; });
} catch(NullPointerException excep) {
excep.printStackTrace();
}
}
}
Note
Press like button if you like the post. Also share your opinion regarding posts through comments. Also mention what other framework you want me to cover through comments.