Automatic Retry with Spring boot application

Automatic Retry with Spring boot application

In this article, we'll learn about the automatic retry of any failure call in the spring boot application. This call can be anything external or internal, like a database call, any microservice call, or any third-party component call. Failure can occur for lots of reasons like database glitch, network glitch, dependent microservice overloaded, dependent microservice goes down, etc.

As part of this demo, we'll use two spring boot-microservices frontend and backend. The frontend depends on the backend to get actual data. When backend service goes down or overloaded, then frontend service also fails. To overcome this we may try to retry the backend service call manually when we get any specific error but this solution will be error-prone and requires a bit of effort as well. To solve this problem, we have a spring boot retry feature and in this demo, we'll learn how to configure and use the same.

Here I have attached a core code snippet for full code reference refer front-end and backend

Prerequisites

  • JDK
  • Maven
  • Basic knowledge of Java, Spring boot

Backend service

  • This is a spring boot application. The primary goal of this application is to interact with data or any sensitive information. So it will be accessible within the network or another service that is running in the same network.
  • As part of the demo we will just create sample rest controller which return simple message

      @RestController
      public class BackendController {
          @RequestMapping(value = "backend", method= RequestMethod.GET)
          public String backend() {
              return "Data from the backend application";
           }
      }
    

Frontend service

  • This is again another spring boot application deployed within the same network(where backend service is deployed) or host so it can access backend service.
  • Here we will use the spring boot retry feature so that when we get a specific error from the backend service, then the application automatically retries after a specified duration.
  • Add spring retry maven library

          <dependency>
              <groupId>org.springframework.retry</groupId>
              <artifactId>spring-retry</artifactId>
          </dependency>
    
  • Add @EnableRetry annotation on the main class to enable spring retry
  • Add below RetryService. @Retryable contains exceptions when the application will retry, number of attempts, and back-off time. The service method will be called the number of times specified in max attempts if any ResourceAccessException from the backend service call and the recover method will call only once after this.

    @Service
    public class RetryService {
      @Autowired
      private RestTemplate restTemplate;
      @Retryable(value = {ResourceAccessException.class},
              maxAttempts = 4, backoff = @Backoff(1000))
      public String service() {
          System.out.println("Inside service method");
          String url = "http://localhost:8081/backend";
          ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
          return response.getBody();
      }
    
      @Recover
      public String recover(ResourceAccessException e) {
          System.out.println("Inside recover method");
          return "Error occurred while fetching data from backend service";
      }
    }
    
  • Add below the controller. This is a normal spring boot controller that is the calling a service method of RetryService call.

    @RestController
    public class FrontEndController {
      @Autowired
      private RetryService retryService;
    
      @RequestMapping(value = "frontend-retry", method = RequestMethod.GET)
      public String frontendRetry() {
          System.out.println("Front end controller start");
          String message = retryService.service();
          System.out.println("Front end controller end");
          return message;
      }
    }
    
  • First start frontend service only and try to access /frontend-retry REST endpoint, as backend service is not started yet so we will get ResourceAccessException and application will retry 4 times after 1 second pause automatically. If it failed all the 4 times it will call recover method defined in RetryService class.
  • 1.png
  • Now start backend application as well and try to access /frontend-retry REST endpoint, as backend applications running we will get output on the first attempt.
  • 2.png