Hi All,

There are instance when RESTful service don’t respond back. The issues can be several. However, we still want to get the response from that service. In those scenarios we put a retry mechanism.

The most common issue that we face is Read Timeout and Connection Timeout. The below code handle that scenario and retries to get the response.

The idea is to call the RESTful service again for a fixed number of times.

So, let’s jump into the code. We are going to keep the REST client singleton as it is the best practice.

RESTClientWithRetry

package com.rest.client;

import java.net.SocketTimeoutException;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.glassfish.jersey.client.ClientProperties;


/**
 * The Class RESTClientWithRetry.
 */
public class RESTClientWithRetry {

  /** The instance. */
  private static RESTClientWithRetry instance;

  /** The client. */
  private Client client;

  /**
   * Instantiates a new jersey rest client.
   */
  private RESTClientWithRetry() {	
    if(client == null) {
      createClient();
    }
  }
  
  /**
   * Creates the client.
   */
  public void createClient() {
    client = ClientBuilder.newClient();
    client.property(ClientProperties.CONNECT_TIMEOUT, 3000);
    client.property(ClientProperties.READ_TIMEOUT,    3000);
  }

  /**
   * Gets the single instance of RESTClientWithRetry.
   *
   * @return single instance of RESTClientWithRetry
   */
  public static synchronized RESTClientWithRetry getInstance() {
    return instance == null ? new RESTClientWithRetry() : instance;
  }

  /**
   * Gets the response as string.
   *
   * @param resourceLocation the resource location
   * @return the response as string
   */
  public String getResponseAsString(String resourceLocation)  {
    String output = null;

    try {
      WebTarget target = client.target(resourceLocation);
      
      int i = 0;
      int retryNumber = 2;
      
      Response res = null;
      
      while (true) {
          try {
          	res = target.request().accept(MediaType.APPLICATION_JSON).get();
              break;
          } catch (ProcessingException e){ // retry in case of exception
              if (e.getCause() instanceof SocketTimeoutException && i < retryNumber) {
                  i++;
              } else {
                  break;
              }
          }
      }

      if(res.getStatus() == 200) {
        output = res.readEntity(String.class);
      }
      res.close();

    } catch (Exception e) {
      e.printStackTrace();
    }
    return output;
  }
}

The main logic is here:

while (true) {
          try {
          	res = target.request().accept(MediaType.APPLICATION_JSON).get();
              break;
          } catch (ProcessingException e){ // retry in case of exception
              if (e.getCause() instanceof SocketTimeoutException && i < retryNumber) {
                  i++;
              } else {
                  break;
              }
          }
      }

If response is received straight away, then it will come out from the while loop. But if there is a SocketTimeoutException for Read Timeout and Connection Timeout, and retry count is less than 2 (which is number of retries in our case), then it will call service again. Same process will be repeated in the case of failure. Once retries are exhausted, it will come out of the while loop.

So, that’s it guys.

You can browse the complete code from GitHub: https://github.com/niteshapte/singleton-rest-client-with-retry-mechanism-java

and download directly: https://github.com/niteshapte/singleton-rest-client-with-retry-mechanism-java/archive/master.zip

 

Feedback / comments are welcome.

Have a nice day ahead.

 

Loading