
Correctif spring retry 1.3.x avec boîte à outils de niche pour CVE-2026-41710
Ce projet fournit un support de nouvelle tentative déclaratif pour les applications Spring. Il est utilisé dans Spring Batch, Spring Integration, et d'autres. La nouvelle tentative impérative est également prise en charge pour un usage explicite.
La version corrige spring-retry avec 2.0.13 pour java8 et spring4 ou spring5, Pour plus d'informations, veuillez vous référer à la version officielle Spring 2.0.13
Cette section fournit une introduction rapide pour démarrer avec Spring Retry. Elle inclut un exemple déclaratif et un exemple impératif.
L'exemple suivant montre comment utiliser Spring Retry dans son style déclaratif :
@Configuration
@EnableRetry
public class Application {
@Bean
public Service service() {
return new Service();
}
}
@Service
class Service {
@Retryable(RemoteAccessException.class)
public void service() {
// ... do something
}
@Recover
public void recover(RemoteAccessException e) {
// ... panic
}
}
Cet exemple appelle la méthode service et, si elle échoue avec une RemoteAccessException, réessaie
(par défaut, jusqu'à trois fois), puis tente la méthode recover en cas d'échec.
Diverses options sont disponibles dans les attributs de l'annotation @Retryable pour inclure et
exclure des types d'exceptions, limiter le nombre de tentatives et définir la politique de backoff.
L'approche déclarative d'application de la gestion des tentatives à l'aide de l'annotation @Retryable présentée plus haut a une dépendance
d'exécution supplémentaire sur les classes AOP. Pour plus de détails sur la façon de résoudre cette dépendance dans votre projet, consultez la
section 'Java Configuration for Retry Proxies'.
L'exemple suivant montre comment utiliser Spring Retry dans son style impératif (disponible depuis la version 1.3) :
RetryTemplate template = RetryTemplate.builder()
.maxAttempts(3)
.fixedBackoff(1000)
.retryOn(RemoteAccessException.class)
.build();
template.execute(ctx -> {
// ... do something
});
Pour les versions antérieures à 1.3, voir les exemples dans la section RetryTemplate.
Spring Retry nécessite Java 1.7 et Maven 3.0.5 (ou supérieur). Pour compiler, exécutez la commande Maven suivante :
$ mvn install
Cette section présente les fonctionnalités de Spring Retry et montre comment utiliser son API.
RetryTemplatePour rendre le traitement plus robuste et moins sujet aux échecs, il est parfois utile de
réessayer automatiquement une opération échouée, au cas où elle réussirait lors d'une tentative ultérieure.
Les erreurs susceptibles de bénéficier de ce type de traitement sont de nature transitoire. Par
exemple, un appel distant à un service web ou à un service RMI qui échoue en raison d'un problème
réseau ou d'une DeadLockLoserException lors d'une mise à jour de base de données peut se résoudre après une
courte attente. Pour automatiser la nouvelle tentative de telles opérations, Spring Retry propose la
stratégie RetryOperations. La définition de l'interface RetryOperations suit :
public interface RetryOperations {
<T> T execute(RetryCallback<T> retryCallback) throws Exception;
<T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback)
throws Exception;
<T> T execute(RetryCallback<T> retryCallback, RetryState retryState)
throws Exception, ExhaustedRetryException;
<T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback,
RetryState retryState) throws Exception;
}
Le callback de base est une interface simple qui vous permet d'insérer une logique métier à réessayer :
public interface RetryCallback<T> {
T doWithRetry(RetryContext context) throws Throwable;
}
Le callback est tenté et, s'il échoue (en levant une Exception), il est réessayé jusqu'à ce qu'il réussisse ou que l'implémentation décide d'abandonner. Il existe un certain nombre de méthodes execute surchargées dans l'interface RetryOperations, pour gérer divers cas d'usage de récupération lorsque toutes les tentatives de réessai sont épuisées et pour gérer l'état de réessai, ce qui permet aux clients et aux implémentations de stocker des informations entre les appels (nous y reviendrons plus tard).
L'implémentation générale la plus simple de RetryOperations est RetryTemplate. L'exemple suivant montre comment l'utiliser :
RetryTemplate template = new RetryTemplate();
TimeoutRetryPolicy policy = new TimeoutRetryPolicy();
policy.setTimeout(30000L);
template.setRetryPolicy(policy);
Foo result = template.execute(new RetryCallback<Foo>() {
public Foo doWithRetry(RetryContext context) {
// Do stuff that might fail, e.g. webservice operation
return result;
}
});
Dans l'exemple précédent, nous exécutons un appel à un service web et renvoyons le résultat à l'utilisateur. Si cet appel échoue, il est réessayé jusqu'à ce qu'un délai d'expiration soit atteint.
Depuis la version 1.3, la configuration fluide de RetryTemplate est également disponible, comme suit :
RetryTemplate.builder()
.maxAttempts(10)
.exponentialBackoff(100, 2, 10000)
.retryOn(IOException.class)
.traversingCauses()
.build();
RetryTemplate.builder()
.fixedBackoff(10)
.withinMillis(3000)
.build();
RetryTemplate.builder()
.infiniteRetry()
.retryOn(IOException.class)
.uniformRandomBackoff(1000, 3000)
.build();
RetryContextLe paramètre de méthode du RetryCallback est un RetryContext. De nombreux callbacks ignorent
le contexte. Cependant, si nécessaire, vous pouvez l'utiliser comme un sac d'attributs pour stocker des données pendant
la durée de l'itération.
Un RetryContext possède un contexte parent s'il y a une nouvelle tentative imbriquée en cours dans le même
thread. Le contexte parent est parfois utile pour stocker des données qui doivent être partagées
entre les appels à execute.
RecoveryCallbackLorsqu'une nouvelle tentative est épuisée, RetryOperations peut transférer le contrôle à un autre
callback : RecoveryCallback. Pour utiliser cette fonctionnalité, les clients peuvent passer les callbacks
ensemble à la même méthode, comme le montre l'exemple suivant :
Foo foo = template.execute(new RetryCallback<Foo>() {
public Foo doWithRetry(RetryContext context) {
// business logic here
},
new RecoveryCallback<Foo>() {
Foo recover(RetryContext context) throws Exception {
// recover logic here
}
});
Si la logique métier n'aboutit pas avant que le template ne décide d'abandonner, le client a la possibilité d'effectuer un traitement alternatif via le callback de récupération.
Dans le cas le plus simple, une nouvelle tentative n'est qu'une boucle while : le RetryTemplate peut continuer d'essayer
jusqu'à ce qu'il réussisse ou échoue. Le RetryContext contient un certain état permettant de déterminer
s'il faut réessayer ou abandonner. Cependant, cet état se trouve sur la pile, et il n'est pas nécessaire de
le stocker globalement. Par conséquent, nous appelons cela une « nouvelle tentative sans état ». La distinction
entre nouvelle tentative sans état et avec état réside dans l'implémentation de RetryPolicy
(RetryTemplate peut gérer les deux). Dans une nouvelle tentative sans état, le callback est toujours exécuté
dans le même thread que celui où il a échoué lors de la nouvelle tentative.