Das Spring Retry Projekt
Spring Retry ist ein Zusatzprojekt (https://github.com/spring-projects/spring-retry), um Codeblöcke wiederholt auszuführen, wenn sie zu einem Fehler führen.
- Das ist nützlich beim Ansprechen von Remote-Diensten, die temporär nicht verfügbar sein können.
Als erstes müssen zwei Dependencies in unsere POM:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
@Retryable
Schreiben wir eine Bean, die zwei Anläufe braucht, eine Operation durchzuführen.
@Component
class Achiever {
int tries = 1;
@Retryable
public int tryIt() {
System.out.println( "Runde " + tries );
tries++;
if ( tries != 3 )
throw new IllegalStateException( "Runde nicht 3" );
return tries;
}
}
Retryable drückt aus, das eine Operation bei Ausnahmen automatisch neu aufgerufen werden soll. |
|
Die Methoden können eine Rückgabe haben, oder auch keine. |
@EnableRetry
Damit Spring für die annotierten Methoden einen Proxy baut, müssen wir eine @Configuration
mit @EnableRetry
annotieren.
Wir können nun den Achiever
injizieren:
@Autowired Achiever archiever;
Und die Methode ausführen:
System.out.println( "Vor dem Aufruf" );
int i = archiever.tryIt();
System.out.println( "Nach dem Aufruf ist i=" + i );
Auf der Konsole erscheint keine Exception. Nur:
Vor dem Aufruf Runde 1 Runde 2 Nach dem Aufruf
Der Annotationsty Retryable
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Retryable {
String interceptor() default "";
Class<? extends Throwable>[] value() default {};
Class<? extends Throwable>[] include() default {};
Class<? extends Throwable>[] exclude() default {};
String label() default "";
boolean stateful() default false;
int maxAttempts() default 3;
String maxAttemptsExpression() default "";
Backoff backoff() default @Backoff();
String exceptionExpression() default "";
}
Die Anzahl der Wiederholungen ist nicht unendlich, Spring stoppt standardmäßig bei 3. |
Ausblick
Die Dokumentation unter https://github.com/spring-projects/spring-retry zeit weitere Möglichkeiten auf. Ein zusätzliches Beispiel:
@Retryable
public void tryIO() throws IOException {
throw new IOException( LocalTime.now().toString() );
}
@Recover
public void recover( IOException e ) {
System.err.println( "Aarrrrg: " + e );
}
Die mit @Recover annotierte Methode wird am Ende einer nicht erfolgreichen Aufrufkette aufgerufen. |
Erinnert mich an die Failsafe Library
https://github.com/jhalterman/failsafe