Simple Applications JMS
Cet exemple montre les différentes étapes à suivre pour créer une application cliente JMS:
- la création d'un objet JMSContext
- la création de Producteur et de consommateur de message
- Envoi / Réception de messages
- Envoi de Messages
Dans notre exemple on va utiliser Glassfish comme serveur d'application et JMS (Provider JMS) comme fournisseur; pour comprendre le fonctionnement de Glassfish il faut se reporter à un autre cours. Dans le Glassfish on crée les ressources nécessaires pour l' application JMS à savoir les Objets adminisntrés (Connection Factories et Destination).
Envoi de Messages
Ici on explique comment on procède pour permettre à un client d'envoyer un message. L'application cliente Producer.java va envoyer des messages.
Les différentes étapes à suivre sont les suivantes:
-
Injecter des ressources pour les objets administrés de l'exemple.
-
Accepter et vérifier les arguments saisis en ligne de commande; on peut utiliser cet exemple pour envoyer autant de messages que ce soit en utilisant les files d'attente de messges que les Topic (sujets); on doit spécifier tout ce qu'il faut en ligne de commande quand on exécute le programme.
-
Créer l'objet JMSContext, puis envoyer le nombre de message texte sous forme de caractères.
-
Envoyer un message final pour s'assurer que l'application cliente réceptrice de messages ne peut plus recevoir de messages.
-
Capturer et traiter toutes les exceptions.
Le client producteur de messages Producer.java
package aomara.producer; import javax.annotation.Resource; import javax.jms.ConnectionFactory; import javax.jms.Destination; import javax.jms.JMSContext; import javax.jms.JMSRuntimeException; import javax.jms.Queue; import javax.jms.Topic; /** * The Producer class consists only of a main method, which sends several * messages to a queue or topic. * * Run this program in conjunction with SynchConsumer or AsynchConsumer. Specify * "queue" or "topic" on the command line when you run the program. By default, * the program sends one message. Specify a number after the destination name to * send that number of messages. */ public class Producer { @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 used by the example and, optionally, the * number of messages to send */ public static void main(String[] args) { final int NUM_MSGS; if ((args.length < 1) || (args.length > 2)) { System.err.println( "Program takes one or two arguments: " + " []"); System.exit(1); } String 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); } if (args.length == 2) { NUM_MSGS = (new Integer(args[1])).intValue(); } else { NUM_MSGS = 1; } Destination dest = null; 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); } /* * Within a try-with-resources block, create context. * Create producer and message. * Send messages, varying text slightly. * Send end-of-messages message. */ try (JMSContext context = connectionFactory.createContext();) { int count = 0; for (int i = 0; i < NUM_MSGS; i++) { String message = "This is message " + (i + 1) + " from producer"; // Comment out the following line to send many messages System.out.println("Sending message: " + message); context.createProducer().send(dest, message); count += 1; } System.out.println("Text messages sent: " + count); /* * Send a non-text control message indicating end of * messages. */ context.createProducer().send(dest, context.createMessage()); // Uncomment the following line if you are sending many messages // to two synchronous consumers // context.createProducer().send(dest, context.createMessage()); } catch (JMSRuntimeException e) { System.err.println("Exception occurred: " + e.toString()); System.exit(1); } System.exit(0); } }
L'application cliente productrice de message Producer.java passe par les étapes suivantes:
-
On injecte les ressources pour la "fabrique de connexion" Connection Factories et la file d'attente de messages (queue) et le Topic (sujet):
@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;
-
On récupère et on vérifie les arguments, saisis sur la ligne de commande, qui spécifient le type de destination et le nombre d'arguments:
final int NUM_MSGS; String 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); } if (args.length == 2){ NUM_MSGS = (new Integer(args[1])).intValue(); } else { NUM_MSGS = 1; }
-
Assigner à la fois la file d'attente de message (queue) et le Topic (sujet) un objet Destination adéquat.
Destination dest = null; try { if (destType.equals("queue")) { dest = (Destination) queue; } else { dest = (Destination) topic; } } catch (Exception e) { System.err.println("Error setting destination: " + e.toString()); System.exit(1); }
-
Avec un try-with-resources block créer un objet JMSContext:
try (JMSContext context = connectionFactory.createContext();) {
-
Mettre à zéro le nombre de messages puis créer un objet JMSProducer et envoyer un ou plusieurs messages à la Destination indiquée et incrémenter le compteur.
int count = 0; for (int i = 0; i < NUM_MSGS; i++) { String message = "This is message " + (i + 1) + " from producer"; // Comment out the following line to send many messages System.out.println("Sending message: " + message); context.createProducer().send(dest, message); count += 1; } System.out.println("Text messages sent: " + count);
-
Envoie un un message vide pour le contrôle de la fin des envois des données:
context.createProducer().send(dest, context.createMessage());
Envoie d' un message vide pour le contrôle (le messsage n'a pas de type spécifique) est un moyen de signifier au consommateur que l'envoi des messages est fini.
-
Capturer et traiter les différentes exceptions . la fin de "try-with-resources" block permet la clôture automatique de l'objet JMSContext:
} catch (Exception e) { System.err.println("Exception occurred: " + e.toString()); System.exit(1); } System.exit(0);
Exécuter l'application Producer Client
On peut exécuter l'application cliente en utilisant la commande appclient; l'application Cliente nécessite une ou deux arguments en ligne de commande à savoir le type de Destination et le nombre de messages (qui est optionnel - si ce nombre n'est pas spécifier on a un seul message envoyé -); on se sert de l'application pour envoyer 3 messages dans la file d'attente de message.
-
S'assurer que le serveur est lancé et que toutes les ressources relatives au fonctionnement du programme sont en place:
-
Dans un terminal allez dans le répertoire où se trouve le programme producer (on tape la commande cd producer).
-
Exécuter le programme en envoyant 3 message dans la file d'attente de messages (queue):
appclient -client target/producer.jar queue 3
La sortie du programme donne:
type de Destination est queue 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