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


