-
Notifications
You must be signed in to change notification settings - Fork 95
Spring Retry Extensions Example
In order to build fault tolerant code, it is often necessary to allow operations to be retried under certain conditions. The Spring-Retry library allows this, but has some limitations:
- It accepts callbacks only on it's own RetryCallback interface, and not Callable or Runnable
- The built in RetryPolicy implementations tend to deal with Throwable instances in terms of their class hierarchy, and not their actual content.
You will need JRugged 3.1.2-SNAPSHOT - If you are using Maven, adding the following dependencies to your project's pom.xml should be sufficient:
<dependency>
<groupId>org.fishwife</groupId>
<artifactId>jrugged-core</artifactId>
<version>3.1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.fishwife</groupId>
<artifactId>jrugged-spring</artifactId>
<version>3.1.2-SNAPSHOT</version>
</dependency>
Since 'ExtendedRetryTemplate' extends the existing 'RetryTemplate' class, the steps to construct it are the same. Here is a simple example:
<bean name="retryTemplate" class="org.fishwife.jrugged.spring.retry.ExtendedRetryTemplate">
<property name="retryPolicy">
<bean id="retryPolicy" class="org.springframework.retry.policy.SimpleRetryPolicy">
<property name="maxAttempts" value="3" />
</bean>
</property>
</bean>
Then in your code:
public class MyService {
@Inject
private ExtendedRetryTemplate retryTemplate;
public void doSomethingCallable() {
String s = retryTemplate.execute(new Callable<String>() { ... });
}
public void doSomethingRunnable() {
String s = retryTemplate.execute(new Runnable() { ... });
}
}
There are also times, when you might want to submit a Callable or RetryCallback to an ExecutorService, and apply the retry logic. For this you can use the 'asCallable' method, which wraps up the given Callable or RetryCallback into another Callable which uses the ExtendedRetryTemplate internally.
public void doSomething() {
Future<String> future =
executorService.submit(retryTemplate.asCallable(new Callable<String>() { ... }));
}
The built in SimpleRetryPolicy is geared around classifying exceptions based on class hierarchy. There may be times where this is not enough for you. To solve this problem, you can use a 'ClassifierSimpleRetryPolicy' which takes a generic Classifier<Throwable, Boolean> as an argument, and applies that classifier.
<bean id="retryPolicy" class="org.fishwife.jrugged.spring.retry.ClassifierSimpleRetryPolicy">
<constructor-arg value="3" />
<constructor-arg ref="exceptionClassifier" />
</bean>
We also provide a Classifier instance which is based on a Google Guava predicate, allowing you to plug in any classification logic you want via an instance of Predicate<Throwable,Boolean>. You can then check the error messages, sql error codes, or any other field on the exception you'd like. This allows you to determine if the operation is retry-able.
<bean id="exceptionClassifier" class="org.fishwife.jrugged.spring.retry.PredicateBinaryExceptionClassifier">
<constructor-arg ref="exceptionPredicate" />
</bean>