Возможно, вам стоит взглянуть на поддержку Spring Aspect. То, что вы описываете, это повторная попытка с (постоянным) откатом, и есть вероятность, что он вам в конечном итоге понадобится где-то еще, будь то общение с веб-службой, сервером электронной почты или любой другой сложной системой, подверженной временным сбоям.
Например, этот простой метод вызывает базовый метод до maxAttempts раз всякий раз, когда генерируется исключение, если только он не является подклассом Throwable, перечисленным в noRetryFor.
private Object doRetryWithExponentialBackoff(ProceedingJoinPoint pjp, int maxAttempts,
Class<? extends Throwable>[] noRetryFor) throws Throwable {
Throwable lastThrowable = null;
for (int attempts = 0; attempts < maxAttempts; attempts++) {
try {
pauseExponentially(attempts, lastThrowable);
return pjp.proceed();
} catch (Throwable t) {
lastThrowable = t;
for (Class<? extends Throwable> noRetryThrowable : noRetryFor) {
if (noRetryThrowable.isAssignableFrom(t.getClass())) {
throw t;
}
}
}
}
throw lastThrowable;
}
private void pauseExponentially(int attempts, Throwable lastThrowable) {
if (attempts == 0)
return;
long delay = (long) (Math.random() * (Math.pow(4, attempts) * 100L));
log.warn("Retriable error detected, will retry in " + delay + "ms, attempts thus far: "
+ attempts, lastThrowable);
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
// Nothing we need to do here
}
}
Этот совет может быть применен к любому бобу, который вы пожелаете, с помощью поддержки Aspect Spring. Подробнее см. http://static.springsource.org/spring/docs/2.5.x/reference/aop.html.