Guide to Spring Retry

Guide de printemps Réessayer

1. Vue d'ensemble

Spring Retry permet de ré-invoquer automatiquement une opération ayant échoué. Ceci est utile lorsque les erreurs peuvent être de nature transitoire (comme un problème de réseau momentané). Spring Retry fournit un contrôle déclaratif du processus et du comportement basé sur des règles, facile à étendre et à personnaliser.

Dans cet article, nous allons voir comment utiliserSpring Retry pour implémenter une logique de nouvelle tentative dans les applications Spring. Nous allons également configurer les écouteurs pour recevoir des rappels supplémentaires.

2. Dépendances Maven

Commençons par ajouter la dépendance dans nospom.xml:


    org.springframework.retry
    spring-retry
    1.1.5.RELEASE

Nous pouvons vérifier la dernière version despring-retry dansMaven Central.

Nous devons également ajouter Spring AOP dans notre fichier pom.xml:


    org.springframework
    spring-aspects

3. Activation de Spring Retry

Pour activer Spring Retry dans une application, nous devons ajouter l'annotation@EnableRetry à notre classe@Configuration:

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

4. Réessayer avec des annotations

Nous pouvons effectuer un appel de méthode pour qu'il soit retenté en cas d'échec en utilisant des annotations.

4.1. @Retryable

Pour ajouter une fonctionnalité de nouvelle tentative aux méthodes,@Retryable peut être utilisé:

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

Ici, le comportement de nouvelle tentative est personnalisé à l'aide des attributs de@Retryable. Dans cet exemple, une nouvelle tentative ne sera tentée que si la méthode émet unSQLException. Il y aura jusqu'à 2 tentatives et un délai de 5000 millisecondes.

Si@Retryable est utilisé sans aucun attribut, si la méthode échoue avec une exception, alors une nouvelle tentative sera tentée jusqu'à trois fois, avec un délai d'une seconde.

4.2. @Recover

L'annotation@Recover est utilisée pour définir une méthode de récupération distincte lorsqu'une méthode@Retryable échoue avec une exception spécifiée:

@Service
public interface MyService {
    ...
    @Recover
    void recover(SQLException e, String sql);
}

Donc, si la méthoderetryService() lance unSQLException, la méthoderecover() sera appelée. Un gestionnaire de récupération approprié a son premier paramètre de typeThrowable (facultatif). S Les arguments suivants sont renseignés à partir de la liste des arguments de la méthode ayant échoué dans le même ordre que la méthode ayant échoué et avec le même type de retour.

5. RetryTemplate

5.1 RetryOperations

Spring Retry fournit une interfaceRetryOperations qui fournit un ensemble de méthodesexecute():

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

    ...
}

LeRetryCallback qui est un paramètre duexecute() est une interface qui permet l'insertion d'une logique métier qui doit être réessayée en cas d'échec:

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

5.2. Configuration deRetryTemplate

LeRetryTemplate est une implémentation desRetryOperations. Configurons un beanRetryTemplate dans notre classe@Configuration:

@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;
    }
}

RetryPolicy détermine quand une opération doit être réessayée. UnSimpleRetryPolicy est utilisé pour réessayer un nombre fixe de fois.

BackOffPolicy est utilisé pour contrôler le retour entre les tentatives. UnFixedBackOffPolicy fait une pause pendant une période de temps fixe avant de continuer.

5.3. Utilisation desRetryTemplate

Pour exécuter du code avec la gestion des tentatives, nous appelons les retryTemplate.execute(): __

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

La même chose pourrait être obtenue en utilisant une expression lambda au lieu d'une classe anonyme: __

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

6. Configuration XML

Spring Retry peut être configuré par XML à l'aide de l'espace de noms Spring AOP.

6.1. Ajout d'un fichier XML

Dans le chemin de classe, ajoutonsretryadvice.xml:

...

    
        
        
    

    
        
    

    
        
        
    

    
        
        
            
                
            
        
    

    
        
        
        
        
        
        
    

...

Cet exemple utilise unRetryTemplate personnalisé dans l'intercepteur de la méthodexmlRetryService.

6.2. Utilisation de la configuration XML

Importezretryadvice.xml depuis lesclasspath et activez la prise en charge de@AspectJ:

@Configuration
@EnableRetry
@EnableAspectJAutoProxy
@ImportResource("classpath:/retryadvice.xml")
public class AppConfig { ... }

7. Les auditeurs

Les auditeurs fournissent des rappels supplémentaires lors de nouvelles tentatives. Ils peuvent être utilisés pour diverses préoccupations transversales lors de différentes tentatives.

7.1. Ajouter des rappels

Les callbacks sont fournis dans une interfaceRetryListener:

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);
    }
}

Les rappelsopen etclose interviennent avant et après la tentative complète, etonError s'applique aux appels individuels deRetryCallback.

7.2. Enregistrement de l'auditeur

Ensuite, nous enregistrons notre auditeur (DefaultListenerSupport) dans notre beanRetryTemplate:

@Configuration
public class AppConfig {
    ...

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

8. Tester les résultats

Vérifions les résultats:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
  classes = AppConfig.class,
  loader = AnnotationConfigContextLoader.class)
public class SpringRetryTest {

    @Autowired
    private MyService myService;

    @Autowired
    private RetryTemplate retryTemplate;

    @Test(expected = RuntimeException.class)
    public void givenTemplateRetryService_whenCallWithException_thenRetry() {
        retryTemplate.execute(arg0 -> {
            myService.templateRetryService();
            return null;
        });
    }
}

Lorsque nous exécutons le scénario de test, le texte du journal ci-dessous signifie que nous avons configuré avec succès lesRetryTemplate et Listener:

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

9. Conclusion

Dans cet article, nous avons introduit Spring Retry. Nous avons vu des exemples de nouvelles tentatives utilisant des annotations et desRetryTemplate. Nous avons ensuite configuré des rappels supplémentaires en utilisant des écouteurs.

Vous pouvez trouver le code source de cet articleover on GitHub.