INTRODUCTION

We are covering spring retry framework and how spring retry made to remove boilerplate code and retry mechanism when exception occurred. As part of this article how it helped to reduce the code lines.


Why Spring Retry 

Using Spring Retry we can delete the number of code used for retry mechanism. It provides a set of annotations and interface that you can use for retry mechanism. It also provide declarative way to provide the retry logic. 

Lets start with steps to follow in setting up the spring retry.

step 1 : 

Need to add below maven dependency in pom.xml of your project.

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
    <version>1.3.1</version>
</dependency>

Step 2 : 

Enable spring retry mechanism in spring configuration as @EnableRetry. It will enable the retry functionality in your application.

Example : 


@Configuration

@EnableRetry

public void SpringConfiguration() { 

}

Step 3 : 

1) As we have setup the spring retry lets refactor the code.

Old code : 

public String responseBody() {

int retryCount = 0;
do {

try {  

 HttpClient httpClient = HttpClient.newHttpClient();
 
 HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://getStudent/data"))
                .GET()
                .build();

HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

 String responseBody = response.body();
  
 return responseBody;
 
 }catch(IOException e) {
   logger.error("exception occured while response");
   retryCount++;
 } catch(Exception e) {
  logger.error("exception occured while response return");
   retryCount++;
 }
 }while (retryCount <= 6)

return null;
}

New Code : 

@Retryable(retryFor = {HttpClientException.class,HttpTimeoutException.class},maxAttempts = 6)
public String responseBody() {

 HttpClient httpClient = HttpClient.newHttpClient();
 
 HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://getStudent/data"))
                .GET()
                .build();

HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

 String responseBody = response.body();
  
 return responseBody;
}


In above code you can see @Retryable annotation removed the code into a single line. It contains the exception we need to specify and maxAttempts for how much time you want to retry the process. we can create a property file with name retry.property and add retry.maxAttempts in file.


2) Configurable retry config : 

We can add retry configuration in properties file also. This is useful when you need to change the retry count and no need to deploy the application.

Old Code : 

public String responseBody() {

int retryCount = 0;

do {

Metrics.addMetric("mysql_connection",1)

Class.forName("com.mysql.jdbc.Driver"); 
 
try (Connection connection = DriverManager.getConnection( 
 
"jdbc:mysql://localhost:3306/sonoo","root","")) {
 
Statement statement = connection. createStatement();  

ResultSet  resultset = statement .executeQuery("select * from emp");  
 
while (resultset.next) {
 return resultset.getString("Salary");
}

} catch(SQLException e){
Metrics.addMetric("mysql_connection_error",1);
retryCount ++;
} catch(Exception e) {
 throw e;
}

} while (retryCount <=6)
}

New Code : 

@Retryable(retryFor = {SQLException.class},maxAttempts = "${retry.maxAttempts}")
public String responseBody() {

Class.forName("com.mysql.jdbc.Driver"); 
 
Connection connection = DriverManager.getConnection( 
 
"jdbc:mysql://localhost:3306/sonoo","root",""); 
 
Statement statement = connection. createStatement();  

ResultSet  resultset = statement .executeQuery("select * from emp");  
 
while (resultset.next) {
 return resultset.getString("Salary");
}
}


3) Eliminate the duplicate operations using RetryListenerSupport.

In above example need to emit the metrics,
  • When we are connecting to MYSQL database.
  • When connection failed with MYSQL database.
  • When we are retrying for connection to MYSQL database.
Instead of adding same code in retry block where we are connecting to MYSQL database, we can use RetryListenerSupport to add them in place so code change and redundancy of code is reduced.

How to use RetryListenerSupport ?

Use RetryListenerSupport using registerListener method on RetryTemplate

@Configuration
public void SpringConfig {

@Bean
public retryTemplate getTemplate() {

RetryTemplate retryTemplate = new RetryTemplate();
retryTemplate.resterListener(new DefaultListenerSupport());
return retryTemplate;

}
}

RetryListenerSupport provides three method that we can override and add your own logic.

  • onError : We can use this method when we get error.
  • close : We can use this method when all retryCount is exhausted.
  • open :  We can call this method when retry is started.

CONCLUSION

In above article we can use Spring Retry mechanism and reduce boilerplate code. we can make code easy and readable.

About us

I am Suraj Ladda and I am Software Developer in IT company.

Contact us

surajladda07@gmail.com