Blue Flower

Chercher

Recevoir des Messages de façon synchrone

Ici on décrit comment une application cliente JMS reçoit des messages de façon synchrone; ce client utilise la méthode receive pour recevoir de façon synchrone les messages; le fournisseur JMS utilisé est le serveur d'application Glassfish.

Le Client SynchConsumer.java

/**
 */
package aomara.synchconsumer;

import javax.annotation.Resource;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSConsumer;
import javax.jms.JMSContext;
import javax.jms.JMSException;
import javax.jms.JMSRuntimeException;
import javax.jms.Message;
import javax.jms.Queue;
import javax.jms.TextMessage;
import javax.jms.Topic;

/**
 * The SynchConsumer class consists only of a main method, which fetches one or
 * more messages from a queue or topic using synchronous message delivery. Run
 * this program in conjunction with Producer. Specify "queue" or "topic" on the
 * command line when you run the program.
 */
public class SynchConsumer {

    @Resource(lookup = "java:comp/DefaultJMSConnectionFactory")
    private static ConnectionFactory connectionFactory;
    @Resource(lookup = "jms/MyQueue")
    private static Queue queue;
    @Resource(lookup = "jms/MyTopic")
    private static Topic topic;

    /**
     * Main method.
     *
     * @param args the destination name and type used by the example
     */
    public static void main(String[] args) {
        String destType;
        Destination dest = null;
        JMSConsumer consumer;

        if (args.length != 1) {
            System.err.println("Program takes one argument: ");
            System.exit(1);
        }

        destType = args[0];
        System.out.println("Destination type is " + destType);

        if (!(destType.equals("queue") || destType.equals("topic"))) {
            System.err.println("Argument must be \"queue\" or \"topic\"");
            System.exit(1);
        }

        try {
            if (destType.equals("queue")) {
                dest = (Destination) queue;
            } else {
                dest = (Destination) topic;
            }
        } catch (JMSRuntimeException e) {
            System.err.println("Error setting destination: " + e.toString());
            System.exit(1);
        }

        /*
         * In a try-with-resources block, create context.
         * Create consumer.
         * Receive all text messages from destination until
         * a non-text message is received indicating end of
         * message stream.
         */
        try (JMSContext context = connectionFactory.createContext();) {
            consumer = context.createConsumer(dest);
            int count = 0;
            
            while (true) {
                Message m = consumer.receive(1000);

                if (m != null) {
                    if (m instanceof TextMessage) {
                        // Comment out the following two lines to receive
                        // a large volume of messages
                        System.out.println(
                                "Reading message: " + m.getBody(String.class));
                        count += 1;
                    } else {
                        break;
                    }
                }
            }
            System.out.println("Messages received: " + count);
        } catch (JMSException e) {
            System.err.println("Exception occurred: " + e.toString());
            System.exit(1);
        }
        System.exit(0);
    }
}


Le client SynchConsumer.java exécute les étapes suivantes:

Injection des ressources pour la fabrique de connexion (Connection factory), la file d'attente de message (queue) et le sujet (Topic); pour cela donc il:

  • Assigne la file d'attente de message (queue) et le sujet (Topic) à l'objet Destination spécifié,

  • Créé un objet JMSContext avec un "try-with-resources block",

  • Crée un objet JMSConsumer, qui initie l'envoi des messages comme suit,

    consumer = context.createConsumer(dest);
    
  • Il reçoit les messages provenant de la Destination jusqu'à recevoir le "end-of-message-stream control" qui précise la fin du message:

    int count = 0;
    while (true) {
        Message m = consumer.receive(1000); 
        if (m != null) { 
            if (m instanceof TextMessage) { 
                System.out.println(
                        "Reading message: " + m.getBody(String.class));
                count += 1; 
            } else { 
                break; 
            } 
        }
    }
    System.out.println("Messages received: " + count);
    

    Comme le contrôle des messages n'est pas une boucle TextMessagewhile, il s'arrête et cesse de recevoir des messages une fois que le contrôle de fin de réception est arrivé.

  • Capture et traite toutes les exceptions; la fin automatique du block "try-with-resources" provoque la fermeture de l'objet JMSContext.

L'application cliente SynchConsumer utilise une boucle infinie "While" pour la réception des messages et fait appel à la réception des messages avec un argument de Timout.

Exécuter l'application cliente SynchConsumer et l'application cliente Producer

On peut exécuter l'application cliente en exécutant la commande appclient. L'application cliente SynchConsumer nécessite un seul argument à savoir le type de Destination.

Les étapes suivantes montrent comment recevoir/envoyer des messages de façon synchrone en utilisant une file d'attente de message (queue) ou un Topic. Ses étapes considèrent que l'application cliente Producer est déjà lancée et qu'elle a trois messages en attente dans la file d'attente de messages (queue).

  1. Dans le même terminal que celui où on exécute Producer, aller dans le répertoire de l'application synchconsumer:

    cd ../synchconsumer
    
  2. Exécuter le client SynchConsumer en spécifiant la file de message (queue):

    appclient -client target/synchconsumer.jar queue
    

    La sortie après exécution de l'application Cliente est:

    Destination type is queue
    Reading message: This is message 1 from producer
    Reading message: This is message 2 from producer
    Reading message: This is message 3 from producer
    Messages received: 3
    
  3. Après essayer l’exécution de des applications clientes dans l'ordre opposé . Exécuter le client SynchConsumer:

    appclient -client target/synchconsumer.jar queue
    

    L'application affiche te type de Destination et attend les messages.

  4. Ouvrir un autre terminal et exécuter l'application cliente Producer (on se positionne dans son répertoire pour l'exécuter):

    appclient -client target/producer.jar queue 3
    

    Quand les messages sont envoyés, l'application cliente SynchConsumer les reçoit et sort (se termine).

  5. Maintenant exécuter l'application cliente Producer en mode "Topic" plutôt que la file d'attente de message (queue):

    appclient -client target/producer.jar topic 3
    

    La sortie du programme donne:

    Destination type is topic
    Sending message: This is message 1 from producer
    Sending message: This is message 2 from producer
    Sending message: This is message 3 from producer
    Text messages sent: 3
    
  6. Maintenant, dans un terminal, exécuter l'application cliente SynchConsumer en mode "Topic":

    appclient -client target/synchconsumer.jar topic
    

    Le résultat est quand même différent; en effet on a utilisé le système de communication "Topi" au lieu de la file d'attente de message.

  7. Quitter l'exécution de l'application cliente SynchConsumer et exécuter l'application cliente Producer encore:

    appclient -client target/producer.jar topic 3
    

    Maintenant le client SynchConsumer reçoit les messages:

    Destination type is topic
    Reading message: This is message 1 from producer
    Reading message: This is message 2 from producer
    Reading message: This is message 3 from producer
    Messages received: 3
    

    En effet ces messages ont été envoyés après que le consommateur ait démarré, le client les reçoit.

précédent