2017-02-14 4 views
0

я найти себе писать много циклов повторных попыток, которые выглядят какJava 8 родовое Retry, если определенное исключение

int triesRemaining = 3; 

    while (triesRemaining > 0) { 
     try { 
      <MY FUNCTION CALL> 
      LOGGER.info("success"); 
      break; 
     } catch (Exception e) { 
      if (e.getCause() instanceof SocketTimeoutException) { 
       triesRemaining--; 
       LOGGER.info(e.getMessage() + " trying again. Tries Remaining: " + triesRemaining); 
      } else { 
       LOGGER.error(e.getMessage(), e); 
       return; 
      } 
     } 
    } 
    if (triesRemaining == 0) { 
     LOGGER.error("Failed over too many times"); 
    } 

Я хочу написать обобщенную функцию, которая принимает Lambda и только повторю на конкретную ошибке (в вышеупомянутый случай - SocketTimeoutException). Я видел некоторые функции, которые принимают Runnable, что хорошо, но они, похоже, не ограничивают определенные исключения.

Любые советы?

ответ

1

Посмотрите на org.springframework.retry

Eсть аннотация @Retryable, соответствующая вашей потребности. Вы можете указать тип исключения для повторной попытки и настроить количество попыток и т. Д.

+1

Уважаемый О.П., для будущего это будет не хуже упоминать в тегах, которые вы используете 'рамки spring' – Andremoniy

1

Ну, это уже сделано. Он также принимает список исключений, на которые вы хотите повторить попытку. Он также обеспечивает линейные/экспоненциальные стратегии повтора. Взгляните https://github.com/rholder/guava-retrying

Простой пример из его ридми, вы можете создавать и использовать retryer как: -

Callable<Boolean> callable = new Callable<Boolean>() { 
public Boolean call() throws Exception { 
    return true; // do something useful here 
}}; 

Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder() 
    .retryIfResult(Predicates.<Boolean>isNull()) 
    .retryIfExceptionOfType(IOException.class) 
    .retryIfRuntimeException() 
    .withStopStrategy(StopStrategies.stopAfterAttempt(3)) 
    .build(); 

try { 
    retryer.call(callable); 
} catch (RetryException e) { 
    e.printStackTrace(); 
} catch (ExecutionException e) { 
    e.printStackTrace(); 
} 
0

В чем проблема, просто заставьте эту функцию принять аргумент Runnable, а затем запустите его в <MY FUNCTION CALL>?

public static void retry(Runnable r) { 
     // ... 
     while (triesRemaining > 0) { 
     try { 
      r.run(); 
      LOGGER.info("success"); 
      break; 
     } 
     // ... 
} 

затем вызвать его (если вы предпочитаете - с лямбда):

retry(() -> { 
     connectToServer(); 
     // todo what-ever-you-want 
    }); 
+0

Я хочу только поймать конкретных исключений – marisbest2

+0

ТВН Я не понимаю как это утверждение относится к моему предложению :) Я просто пропустил часть остального кода, которую я обозначил как «// ...». – Andremoniy

+0

Поскольку я хочу, чтобы функция в целом принимала класс исключения, с которым у меня были проблемы. Но я посмотрел на guava-retrying и увидел «Class ', который был решением моей проблемы – marisbest2

0

Я считаю, что вы ищете для чистого раствора на основе Java. Основываясь на предположении, я бы сказал, что Java 8 использует функциональный интерфейс, интерфейс с единым абстрактным методом. Я бы создал новый класс RetryCommand, который имеет метод , который принимает функцию.

0

Заканчивать Failsafe:

RetryPolicy retryPolicy = new RetryPolicy() 
    .retryOn(SocketTimeoutException.class) 
    .withMaxRetries(3); 

Failsafe.with(retryPolicy) 
    .onRetry((c, f, ctx) -> log.warn("Failure #{}. Retrying.", ctx.getExecutions())) 
    .onFailure(e -> LOGGER.error(e.getMessage(), e)) 
    .run(() -> myFunctionCall()); 
Смежные вопросы