Question

J'ai un Spring MDP implémenté à l'aide de Spring DefaultMessageListenderContainer écoute d'une file d'attente d'entrée sur WebSphere MQ v7.1.Si un mauvais message arrive (cela provoque RuntimeException), ce qui se passe actuellement, c'est que la transaction est annulée et le message est remis dans la file d'attente.Cependant le MDP entre dans une boucle infinie.

Question 1:Pour mes besoins, j'aimerais pouvoir arrêter le traitement dès qu'il voit un mauvais message.Aucune nouvelle tentative n’est nécessaire.Est-il possible d'arrêter correctement l'écouteur de messages au cas où il verrait un mauvais message (par opposition à un message brut System.exit() ou des méthodes de ce genre) ?Je n’aime vraiment pas que ça entre dans une boucle infinie.

Modifier:

Question 2:Existe-t-il un moyen d'arrêter ou de suspendre le conteneur d'écoute pour arrêter le traitement ultérieur des messages ?

Était-ce utile?

La solution 3

J'ai résolu le problème de la manière suivante, je ne sais pas si c'est la meilleure façon, mais cela fonctionne.

  1. MDP implémente ApplicationContextAware ;Je maintiens également un état d'écoute (énumération avec les valeurs OPEN, CLOSE, ERROR) Fragment de code MDP ci-dessous :
//context
private ConfigurableApplicationContext applicationContext;

//listener state
private ListenerState listenerState = ListenerState.OPEN;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  this.applicationContext = (ConfigurableApplicationContext) applicationContext;
}
//onMessage method
public void processMessages(....) {
  try {
    process(...);
  } catch (Throwable t) {
    listenerState = ListenerState.ERROR;           
    throw new RuntimeException(...);            
  }    
}

@Override
public void stopContext() {        
  applicationContext.stop();  
}
  1. Dans le principal Java qui charge le contexte Spring, je fais ceci :
    //check for errors for exit
    Listener listener = (Listener)context.getBean("listener");
    listenerContainer listenerContainer =
            (ListenerContainer)context.getBean("listenerContainer");

    try {
        while(true) {
            Thread.sleep(1000); //sleep for 1 sec
            if(!listener.getListenerState().equals(ListenerState.OPEN)) {
                listener.stopContext();
                listenerContainer.stop();
                System.exit(1);
            }>             }            
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }

Autres conseils

La manière habituelle de traiter cela consiste à créer une file d’attente d’erreurs et, lorsque vous voyez un mauvais message, à le placer dans la file d’attente d’erreurs.
Certains systèmes gèrent cela pour vous, comme IBM MQ Series.Il vous suffit de configurer la file d'attente des erreurs et le nombre de tentatives souhaitées et il l'y placera.
Un administrateur examinera ensuite ces files d'attente et prendra les mesures appropriées sur les messages qui s'y trouvent (c'est-à-direcorrigez-les et soumettez-les à nouveau)

En fait, System.exit() c'est trop brutal et...ne fonctionnera pas.La nouvelle tentative des messages ayant échoué est gérée du côté du courtier (WMQ), de sorte que le message sera retransmis une fois que vous redémarrerez votre application.

Le problème que vous décrivez s'appelle et doit être géré du côté du courtier.Cela semble être décrit dans Gestion des messages empoisonnés dans le manuel WMQ et dans Comment WebSphere Application Server gère les messages incohérents.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top