@Retryable
(и базовый RetryTemplate
) основаны исключительно на исключениях.
Вы можете создать подкласс RetryTemplate
, переопределяя doExecute()
, чтобы проверить возвращаемое значение.
Вывероятно, придется копировать большую часть кода в методе;на самом деле он не предназначен для переопределения только вызова retryCallback.doWithRetry()
.
Вы можете использовать пользовательский RetryTemplate
в RetryOperationsInterceptor
(указанный в @Retryable
в свойстве interceptor
).
РЕДАКТИРОВАТЬ
Текущий код RetryTemplate
выглядит следующим образом ...
while (canRetry(retryPolicy, context) && !context.isExhaustedOnly()) {
try {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Retry: count=" + context.getRetryCount());
}
// Reset the last exception, so if we are successful
// the close interceptors will not think we failed...
lastException = null;
return retryCallback.doWithRetry(context);
}
catch (Throwable e) {
lastException = e;
try {
registerThrowable(retryPolicy, state, context, e);
}
catch (Exception ex) {
throw new TerminatedRetryException("Could not register throwable",
ex);
}
finally {
doOnErrorInterceptors(retryCallback, context, e);
}
...
}
Вам необходимо изменить его на что-то вроде ...
while (canRetry(retryPolicy, context) && !context.isExhaustedOnly()) {
try {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Retry: count=" + context.getRetryCount());
}
// Reset the last exception, so if we are successful
// the close interceptors will not think we failed...
lastException = null;
T result = retryCallback.doWithRetry(context);
if (((Optional<String>) result).get() == null) {
try {
registerThrowable(retryPolicy, state, context, someDummyException);
}
catch (Exception ex) {
throw new TerminatedRetryException("Could not register throwable",
ex);
}
finally {
doOnErrorInterceptors(retryCallback, context, e);
}
...
}
else {
return result;
}
}
catch (Throwable e) {
...
}
Где someDummyException
- обмануть контекст в увеличении счетчика.Это может быть поле static
, созданное один раз.