I have made this abstract class to automatically retry network calls if some exception is thrown.
InterruptedException &
UnknownHostException. public abstract class AutoRetry {
  private Object dataToReturn = null;
  public Object getDataToReturn() {
    return this.dataToReturn;
  }
  public AutoRetry() {
    short retry = -1;
    while (retry++ < StaticData.NETWORK_RETRY) {
      try {
        Thread.sleep(retry * StaticData.NETWORK_CALL_WAIT);
        this.dataToReturn = doWork();
        break;
      } catch (InterruptedException | UnknownHostException e) {
        e.printStackTrace();
        this.dataToReturn = null;
        return;
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
  protected abstract Object doWork() throws IOException;
}
I use it as follows :
final Object dataAfterWork = new AutoRetry() {     
  @Override
  protected Object doWork() throws IOException {
    return; //a network call which returns something
  }
}.getDataToReturn();
So is this implementation good/correct ?
moved to https://codereview.stackexchange.com/questions/87686
Have a look at Failsafe. It supports retry policies, synchronous and async retries, event listeners, integration with Java 8's CompletableFuture, etc. Ex:
RetryPolicy retryPolicy = new RetryPolicy()
  .retryOn(ConnectException.class)
  .withDelay(1, TimeUnit.SECONDS)
  .withMaxRetries(100);
// Synchronous get with retries
Connection connection = Failsafe.with(retryPolicy).get(() -> connect());
// Asynchronous get with retries
Failsafe.with(retryPolicy, executor)
  .get(() -> connect())
  .onSuccess(connection -> log.info("Connected to {}", connection))
  .onFailure(failure -> log.error("Connection attempts failed", failure));
                        This looks pretty good, but I would split the running task from the retry. Also use generics, don't just throw Object about.
Use a Java 8 lambda and the return of the method:
public static <T> Optional<T> doWithRetry(final Supplier<T> t) {
    for (int retry = 0; retry <= StaticData.NETWORK_RETRY; ++retry) {
        try {
            Thread.sleep(retry * StaticData.NETWORK_CALL_WAIT);
            return Optional.of(t.get());
        } catch (InterruptedException | UnknownHostException e) {
            LOGGER.log(Level.SEVERE, "Call failed.", e);
            return Optional.empty();
        } catch (IOException e) {
            LOGGER.log(Level.WARNING, "Call failed. Retry.", e);
        }
    }
    LOGGER.log(Level.SEVERE, "Call failed. Retries exceeded.");
    return Optional.empty();
}
Also, use a real logger, not printStackTrace...
Usage:
final String data = doWithRetry(() -> {
   //do stuff 
});
If your lambda needs to throw an exception, you'll need to define your own @FunctionalInterface:
@FunctionalInterface
interface StuffDoer<T> {
    T doStuff() throws Exception;
}
And use that in the method signature, you'll need to handle generic Exception.
Pre-Java 8 usage:
final String data = doWithRetry(new StuffDoer<T>() {
    @Override
    public T get() throws Exception {
        return null;
    }
});
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With