'RetryTemplate for specific exceptions not triggered

I am implementing a retry logic using the spring retry template that needs to retry 3 times for 2 types of exceptions that are anticipated to occur on API invocation using the rest template. I am not seeing it triggered for some reason.

Here is my RetryTemplate Configruation

    @Bean(name="myRetryTemplate")

    public RetryTemplate retryTemplate() {

        RetryTemplate retryTemplate = new RetryTemplate();
        final SimpleRetryPolicy simpleRetryPolicyCheck1 = new SimpleRetryPolicy();
final SimpleRetryPolicy simpleRetryPolicyCheck2 = new SimpleRetryPolicy();
        simpleRetryPolicyCheck1.setMaxAttempts(3);
simpleRetryPolicyCheck2.setMaxAttempts(3);
        final Map<Class<? extends Throwable>, RetryPolicy> policyMap = new HashMap<>();
        policyMap.put(Exception1.class, simpleRetryPolicyCheck1 );
        policyMap.put(Exception2.class, simpleRetryPolicyCheck2 );
        final ExceptionClassifierRetryPolicy retryPolicy = new ExceptionClassifierRetryPolicy();
        retryPolicy.setPolicyMap(policyMap);
        retryTemplate.setRetryPolicy(retryPolicy);
        return retryTemplate;
    }

Here is my Service call:

public Object getSomething(@PathVariable("id") String id) throws Exception{


        return retryTemplate.execute(new RetryCallback<Object, Exception>() {
            @Override
            public Object doWithRetry(RetryContext arg0) {
                Object o = restTutorialClient.getEmployeesList(id);
                return o;
            }
        });

I can see the simulated Exception type 1 thrown. But there is no retry happening. Please guide to know where is this failing and the corrective measures?



Solution 1:[1]

Since you don't need a custom retry policy or custom back-off policy, you can use the annotation @Retryable :

    @Component
    public class RetryableAction {

        @Autowired
        private RestTutorialClient restTutorialClient;

        @Retryable(value = {
            Exception1.class,
            Exception2.class
        }, maxAttempts = 3, backoff = @Backoff(delay = 5000))
        Object retryAction(String id) throws Exception1, Exception2 {
            return restTutorialClient.getEmployeesList(id);

        }
    }

    @Service
    public class ServiceResource {

        @Autowired
        private RetryableAction retryableAction;

        @GetMapping("/get/{id}")
        public Object getSomething(@PathVariable("id") String id) throws Exception {
            Object object = retryableAction.retryAction(id);
            // Business logic
        }

EDIT : Since you want to perform retries for both exceptions 3 times then, I suggest to have a super exception class which will have two children Exception1 and Exception2 :

    @Component
    public class RetryableAction {

        @Autowired
        private RestTutorialClient restTutorialClient;

        @Retryable(value = SuperException.class, maxAttempts = 3, backoff = @Backoff(delay = 5000))
        Object retryAction(String id) throws SuperException {
            return restTutorialClient.getEmployeesList(id);

        }
    }

    @Service
    public class ServiceResource {

        @Autowired
        private RetryableAction retryableAction;

        @GetMapping("/get/{id}")
        public Object getSomething(@PathVariable("id") String id) throws Exception {
            Object object = retryableAction.retryAction(id);
            // Business logic
        }

Hope that helps.

Solution 2:[2]

You need to call the constructor of the class SimpleRetryPolicy which takes two parameters, the number of attempts and the list of exceptions like this :

Map<Class<? extends Throwable>, Boolean> map= new HashMap<>();
map.put(Exception1.class, Boolean.TRUE);
map.put(Exception1.class, Boolean.TRUE);
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(3 , map);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 RHANAMI yassine