In this post under Spring Retry, I will show with example how to configure SimpleRetryPolicy to retry failed operations for specific exceptions and its causes also.
They are situations where exceptions are chained together to indicate Exception1 was caused due to Exception2. So here the cause is Exception2 and the main exception is Exception1. So if we configure Spring Retry as below
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="retryPolicy" class="org.springframework.retry.policy.SimpleRetryPolicy">
6 <constructor-arg name="maxAttempts" value="4"/>
7 <constructor-arg name="retryableExceptions">
8 <map key-type="java.lang.Class" value-type="java.lang.Boolean">
9 <entry key="java.lang.NullPointerException" value="true"/>
10 <entry key="java.lang.IndexOutOfBoundsException" value="true"/>
11 </map>
12 </constructor-arg>
13 </bean>
14
15 <bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate">
16 <property name="retryPolicy" ref="retryPolicy"/>
17 </bean>
18
19 <bean id="service3" class="Service3"/>
20 </beans>
In the above xml code, at line 5 we created a bean named “retryPolicy” for SimpleRetryPolicy class.
In the defination we have set the “maxAttempts” property to 4.
Then we have created a Map where the key is Class object and value is a boolean. Through this map, we are saying Spring Retry that if the exception is thrown when attempting any service operations and the exception is of type NullPointerException or IndexOutOfBoundsException then retry (we indicate this by returning boolean value as map value).
So finally we have configured Spring Retry, to retry failed operations only if the main exception thrown are NullPointerException or IndexOutOfBoundsException.
And the Service class throws an exception like below
public class Service3 {
private int i = 0;
public void executeExceptionWithCause() {
i = i + 1;
System.out.println("Executing 'executeExceptionWithCause' : " + i);
NullPointerException nullPointerException = new NullPointerException();
IllegalArgumentException illegalArgumentException = new IllegalArgumentException(nullPointerException);
throw illegalArgumentException;
}
}
Note NullPointerException is thrown as the cause for IllegalArgumentException and not as the main exception.
So the Spring Retry will not retry the operations because NullPointerException is not the main exception thrown here it is only the cause.
So to configure the Spring Retry to traverse the cause of main exceptions and check whether to retry, we set the property “traverseCauses” to true as shown in the below xml.
Below is the xml configuration
New 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="retryPolicy" class="org.springframework.retry.policy.SimpleRetryPolicy">
6 <constructor-arg name="maxAttempts" value="4"/>
7 <constructor-arg name="retryableExceptions">
8 <map key-type="java.lang.Class" value-type="java.lang.Boolean">
9 <entry key="java.lang.NullPointerException" value="true"/>
10 <entry key="java.lang.IndexOutOfBoundsException" value="true"/>
11 </map>
12 </constructor-arg>
13 <constructor-arg name="traverseCauses" value="true"/>
14 </bean>
15
16 <bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate">
17 <property name="retryPolicy" ref="retryPolicy"/>
18 </bean>
19
20 <bean id="service3" class="Service3"/>
21 </beans>
At line 13 we set the property named “traverseCauses” to true.
So using the above xml code as an example, when the code throws a main exception (which in this case can be NullPointerException or IndexOutOfBoundsException) or throws NullPointerException as the cause for some other exception, the Spring Retry will retry the code.
Remaining everything is same.
This is how we configure Spring Retry to retry failed operations for specific exceptions and also for its causes.
Main class
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.retry.support.RetryTemplate;
public class Example9 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Example9.xml");
Service3 service3 = (Service3)context.getBean("service3");
RetryTemplate retryTemplate = (RetryTemplate)context.getBean("retryTemplate");
try {
retryTemplate.execute(retryContext -> { service3.executeExceptionWithCause(); return null; });
} catch(NullPointerException excep) {
excep.printStackTrace();
}
}
}
Below is the output
Output
[INFO] ClassPathXmlApplicationContext – Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@6576fe71: startup date [Sun Jan 23 13:50:34 IST 2022]; root of context hierarchy
[INFO] XmlBeanDefinitionReader – Loading XML bean definitions from class path resource [Example9.xml]
Executing ‘executeExceptionWithCause’ : 1
Executing ‘executeExceptionWithCause’ : 2
Executing ‘executeExceptionWithCause’ : 3
Executing ‘executeExceptionWithCause’ : 4
Exception in thread “main”
java.lang.IllegalArgumentException: java.lang.NullPointerException
at Service3.executeExceptionWithCause(Service3.java:8)
at Example9.lambda$0(Example9.java:12)
at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:329)
at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:209)
at Example9.main(Example9.java:12)
Caused by: java.lang.NullPointerException
at Service3.executeExceptionWithCause(Service3.java:7)
… 4 more
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.