Anleitung zur Federwiederholung

1. Übersicht

Spring Retry bietet die Möglichkeit, einen fehlgeschlagenen Vorgang automatisch erneut aufzurufen. Dies ist hilfreich, wenn die Fehler vorübergehend sein können (z. B. ein vorübergehender Netzwerkfehler).

In diesem Tutorial werden die verschiedenen Möglichkeiten zur Verwendung von Spring Retry beschrieben: Anmerkungen, RetryTemplate und Rückrufe.

2. Maven-Abhängigkeiten

Beginnen wir mit dem Hinzufügen der Spring-Retry- Abhängigkeit in unsere Datei pom.xml :

 org.springframework.retry spring-retry 1.2.5.RELEASE 

Wir müssen auch Spring AOP in unser Projekt aufnehmen:

 org.springframework spring-aspects 5.2.8.RELEASE 

In Maven Central finden Sie die neuesten Versionen der Abhängigkeiten von Spring-Retry und Spring-Aspekten.

3. Aktivieren von Spring Retry

Frühling Retry in einer Anwendung zu aktivieren, müssen wir die hinzuzufügen @EnableRetry Anmerkung zu unserer @Configuration Klasse:

@Configuration @EnableRetry public class AppConfig { ... }

4. Verwenden von Spring Retry

4.1. @Retryable ohne Wiederherstellung

Um den Methoden Wiederholungsfunktionen hinzuzufügen, können Sie die Annotation @Retryable verwenden :

@Service public interface MyService { @Retryable(value = RuntimeException.class) void retryService(String sql); }

In diesem Beispiel wird versucht, es erneut zu versuchen, wenn eine RuntimeException ausgelöst wird .

Per @Retryable ‚s Standardverhalten, kann die Wiederholung bis dreimal geschehen auf, mit einer Verzögerung von einer Sekunde zwischen den Wiederholungen .

4.2. @Retryable und @Recover

Fügen wir nun eine Wiederherstellungsmethode mit der Annotation @Recover hinzu :

@Service public interface MyService { @Retryable(value = SQLException.class) void retryServiceWithRecovery(String sql) throws SQLException; @Recover void recover(SQLException e, String sql); }

In diesem Beispiel wird der Wiederholungsversuch versucht, wenn eine SQLException ausgelöst wird . Die Annotation @Recover definiert eine separate Wiederherstellungsmethode, wenn eine Methode @Retryable mit einer angegebenen Ausnahme fehlschlägt.

Wenn die Methode retryServiceWithRecovery nach drei Versuchen weiterhin eine SqlException auslöst , wird die Methode recovery () aufgerufen.

Der Wiederherstellungshandler sollte den ersten Parameter vom Typ Throwable (optional) und denselben Rückgabetyp haben.Die folgenden Argumente werden in derselben Reihenfolge aus der Argumentliste der fehlgeschlagenen Methode ausgefüllt.

4.3. Anpassen des Verhaltens von @ Retryable

Um eine Wiederholung Verhalten anpassen, können wir die Parameter verwenden maxAttempts und Backoff :

@Service public interface MyService { @Retryable( value = SQLException.class, maxAttempts = 2, backoff = @Backoff(delay = 100)) void retryServiceWithCustomization(String sql) throws SQLException; }

Im obigen Beispiel gibt es bis zu 2 Versuche und eine Verzögerung von 100 Millisekunden.

4.4. Federeigenschaften verwenden

Wir können auch Eigenschaften in der Annotation @Retryable verwenden .

Um dies zu demonstrieren, werden wir sehen, wie die Werte von delay und maxAttempts in eine Eigenschaftendatei ausgelagert werden .

Definieren wir zunächst die Eigenschaften in einer Datei namens retryConfig. Eigenschaften :

retry.maxAttempts=2 retry.maxDelay=100

Anschließend weisen wir unsere @ Configuration- Klasse an, diese Datei zu laden:

// ... @PropertySource("classpath:retryConfig.properties") public class AppConfig { ... }

Schließlich können wir die Werte von retry.maxAttempts und retry.maxDelay in unsere @ Retableable- Definition einfügen :

@Service public interface MyService { @Retryable( value = SQLException.class, maxAttemptsExpression = "${retry.maxAttempts}", backoff = @Backoff(delayExpression = "${retry.maxDelay}")) void retryServiceWithExternalizedConfiguration(String sql) throws SQLException; }

Bitte beachten Sie, dass wir jetzt maxAttemptExpression und delayExpression anstelle von maxAttempts und delay verwenden .

5. RetryTemplate

5.1 Wiederholungsoperationen

Spring Retry bietet eine RetryOperations- Schnittstelle, die eine Reihe von execute () -Methoden bereitstellt :

public interface RetryOperations {  T execute(RetryCallback retryCallback) throws Exception; ... }

Der RetryCallback, der ein Parameter von execute () ist, ist eine Schnittstelle, die das Einfügen von Geschäftslogik ermöglicht, die bei einem Fehler wiederholt werden muss:

public interface RetryCallback { T doWithRetry(RetryContext context) throws Throwable; }

5.2. RetryTemplate- Konfiguration

Das RetryTemplate ist eine Implementierung der RetryOperations . Konfigurieren wir eine RetryTemplate- Bean in unserer @ Configuration- Klasse:

@Configuration public class AppConfig { //... @Bean public RetryTemplate retryTemplate() { RetryTemplate retryTemplate = new RetryTemplate(); FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy(); fixedBackOffPolicy.setBackOffPeriod(2000l); retryTemplate.setBackOffPolicy(fixedBackOffPolicy); SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(); retryPolicy.setMaxAttempts(2); retryTemplate.setRetryPolicy(retryPolicy); return retryTemplate; } } 

Die RetryPolicy legt fest, wann ein Vorgang wiederholt werden soll.

Eine SimpleRetryPolicy wird verwendet, um eine feste Anzahl von Malen erneut zu versuchen . Andererseits wird die BackOffPolicy verwendet, um das Backoff zwischen Wiederholungsversuchen zu steuern.

Schließlich wird eine FixedBackOffPolicy für einen festgelegten Zeitraum angehalten, bevor Sie fortfahren.

5.3. Verwenden der RetryTemplate

Um Code mit Wiederholungsbehandlung auszuführen, können wir die Methode r etryTemplate.execute () aufrufen :

retryTemplate.execute(new RetryCallback() { @Override public Void doWithRetry(RetryContext arg0) { myService.templateRetryService(); ... } });

Anstelle einer anonymen Klasse können wir einen Lambda-Ausdruck wie folgt verwenden:

retryTemplate.execute(arg0 -> { myService.templateRetryService(); return null; }); 

6. Zuhörer

Listener bieten zusätzliche Rückrufe bei erneuten Versuchen. Wir können diese für verschiedene Querschnittsthemen in verschiedenen Wiederholungsversuchen verwenden.

6.1. Rückrufe hinzufügen

Die Rückrufe werden in einer RetryListener- Schnittstelle bereitgestellt :

public class DefaultListenerSupport extends RetryListenerSupport { @Override public void close(RetryContext context, RetryCallback callback, Throwable throwable) { logger.info("onClose); ... super.close(context, callback, throwable); } @Override public void onError(RetryContext context, RetryCallback callback, Throwable throwable) { logger.info("onError"); ... super.onError(context, callback, throwable); } @Override public boolean open(RetryContext context, RetryCallback callback) { logger.info("onOpen); ... return super.open(context, callback); } }

Die Rückrufe zum Öffnen und Schließen erfolgen vor und nach dem gesamten Wiederholungsversuch, während onError für die einzelnen RetryCallback- Aufrufe gilt.

6.2. Registrieren des Listeners

Als Nächstes registrieren wir unseren Listener ( DefaultListenerSupport) für unsere RetryTemplate- Bean:

@Configuration public class AppConfig { ... @Bean public RetryTemplate retryTemplate() { RetryTemplate retryTemplate = new RetryTemplate(); ... retryTemplate.registerListener(new DefaultListenerSupport()); return retryTemplate; } }

7. Testen der Ergebnisse

To conclude our example, let's verify the results:

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( classes = AppConfig.class, loader = AnnotationConfigContextLoader.class) public class SpringRetryIntegrationTest { @Autowired private MyService myService; @Autowired private RetryTemplate retryTemplate; @Test(expected = RuntimeException.class) public void givenTemplateRetryService_whenCallWithException_thenRetry() { retryTemplate.execute(arg0 -> { myService.templateRetryService(); return null; }); } }

As we can see from the test logs, the RetryTemplate and the RetryListener have been properly configured:

2020-01-09 20:04:10 [main] INFO o.b.s.DefaultListenerSupport - onOpen 2020-01-09 20:04:10 [main] INFO o.baeldung.springretry.MyServiceImpl - throw RuntimeException in method templateRetryService() 2020-01-09 20:04:10 [main] INFO o.b.s.DefaultListenerSupport - onError 2020-01-09 20:04:12 [main] INFO o.baeldung.springretry.MyServiceImpl - throw RuntimeException in method templateRetryService() 2020-01-09 20:04:12 [main] INFO o.b.s.DefaultListenerSupport - onError 2020-01-09 20:04:12 [main] INFO o.b.s.DefaultListenerSupport - onClose

8. Conclusion

In this article, we have seen how to use Spring Retry using annotations, the RetryTemplate, and callbacks listeners.

The source code for the examples is available over on GitHub.