Configuring different retry policy for different exceptions (using xml)

In this post under Spring Retry, I will show with example how to configure different retry policy for different exceptions.

Till now in all my previous posts, I showed how to configure single retry policy regardless of whatever exception the program throws. For all exceptions, the same retry policy will be followed.

But they are situations where we want different retry policy to be executed for different exceptions.

This can be achieved by taking the help of out of the box provided “ExceptionClassifierRetryPolicy” policy.

Below is the xml code showing the 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  
6      <bean id="maxAttemptsRetryPolicy" class="org.springframework.retry.policy.MaxAttemptsRetryPolicy">
7          <property name="maxAttempts" value="5"/>
8      </bean>
9      <bean id="timeoutRetryPolicy" class="org.springframework.retry.policy.TimeoutRetryPolicy">
10         <property name="timeout" value="30"/>
11     </bean>
12     
13     <bean id="retryPolicy" class="org.springframework.retry.policy.ExceptionClassifierRetryPolicy">
14         <property name="policyMap">
15             <map key-type="java.lang.Class" value-type="org.springframework.retry.RetryPolicy">
16                 <entry key="java.lang.NullPointerException" value-ref="maxAttemptsRetryPolicy"/>
17                 <entry key="java.lang.IllegalArgumentException" value-ref="timeoutRetryPolicy"/>
18             </map>
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="service4" class="Service4"/>
27 </beans>

In the above xml code, at line 6 and 9 I create bean definitions for two retry policies one is “MaxAttemptsRetryPolicy” and another is “TimeoutRetryPolicy”.

At line 13, I create a bean definition for “ExceptionClassifierRetryPolicy”. Inside the bean definition, I create a map where key is exception’s class object and value is the reference to previously created retry policies. Next I set this map to “ExceptionClassifierRetryPolicy” property “policyMap”.

As per this bean definition, when the code throws NullPointerException, maxAttemptsRetryPolicy will be used. And when the code throws IllegalArgumentException timeoutRetryPolicy will be used.

At line 23, I set the bean “retryPolicy” as property to “retryTemplate” bean.

In this way we can configure Spring Retry to follow different policies for different exceptions.

Below is the service class and main class code for your reference.

Service class


import java.util.NoSuchElementException;

public class Service4 {
    private int i = 0;
    private int j = 0;
    private int k = 0;

    public void executeWithNullPointerException() {
        i = i + 1;
        System.out.println("Executing 'executeWithNullPointerException' : " + i);
        throw new NullPointerException();
    }

    public void executeWithIllegalArgumentException() throws InterruptedException {
        j = j + 1;
        System.out.println("Executing 'executeWithIllegalArgumentException' : " + j);
        Thread.sleep(1000);
        throw new IllegalArgumentException();
    }

    public void executeWithNoSuchElementException() {
        k = k + 1;
        System.out.println("Executing 'executeWithNoSuchElementException' : " + k);
        throw new NoSuchElementException();
    }
}

Main class


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

public class Example10 {
    public static void main(String[] args) throws InterruptedException {
        ApplicationContext context = new ClassPathXmlApplicationContext("Example10.xml");
        Service4 service4 = (Service4)context.getBean("service4");
        RetryTemplate retryTemplate =  (RetryTemplate)context.getBean("retryTemplate");

        try {
            retryTemplate.execute(retryContext -> { service4.executeWithIllegalArgumentException(); return null; });
        } catch(IllegalArgumentException excep) {
            excep.printStackTrace();
        }

        try {
            retryTemplate.execute(retryContext -> { service4.executeWithNullPointerException(); return null; });
        } catch(NullPointerException excep) {
            excep.printStackTrace();
        }
    }
}

Below is the output

Output


[INFO] ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@6576fe71: startup date [Wed Jan 26 12:08:50 IST 2022]; root of context hierarchy
[INFO] XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [Example10.xml]
Executing 'executeWithIllegalArgumentException' : 1
Executing 'executeWithIllegalArgumentException' : 2
java.lang.IllegalArgumentException
at Service4.executeWithIllegalArgumentException(Service4.java:18)
    at Example10.lambda$0(Example10.java:12)
    at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:329)
    at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:209)
    at Example10.main(Example10.java:12)
Executing 'executeWithNullPointerException' : 1
Executing 'executeWithNullPointerException' : 2
Executing 'executeWithNullPointerException' : 3
Executing 'executeWithNullPointerException' : 4
Executing 'executeWithNullPointerException' : 5
java.lang.NullPointerException
    at Service4.executeWithNullPointerException(Service4.java:11)
    at Example10.lambda$1(Example10.java:18)
    at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:329)
    at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:209)
    at Example10.main(Example10.java:18)

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.

Leave a Reply