Applications Réparties - Partie II: approche client/serveur par objets distribués
Cours Polytech'Nice, SI4, 2013-2014, 2015, 2016
Sujet de TP5
Objectif/Contenu :
- Découverte de JMS, en utilisant l'outil ActiveMQ de Apache
ActiveMQ
de Apache, est un MOM (broker), permettant d'héberger des queues de
messages. Il permet aussi d'offrir plusieurs supports programmatiques
pour accéder à ces queues, dont la spécification JMS. De même il
implémente en interne plusieurs protocoles de messaging comme AMQP,
MQTT, etc.
Exercice 1: installation de ActiveMQ, démarrage et découverte de la console d'administration
- Selon votre OS, téléchargez l'installation adéquate.
- Dézippez là.
- Déplacez vous dans le répertoire bin, et lancez le script activemq adéquat.
Analysez un peu les traces de lancement
- Ouvrez la page d'accueil sur http://localhost:8161
- Pour accéder à la console d'administration, authentifiez vous : user, user
Vous avez accès à un ensemble d'onglets permettant de créer,
administrer, des queues, voir leur remplissage, etc. Regardez un peu
quels sont les ressources JMS présentes au démarrage. Postez quelques
messages sur une de ces ressources
Exercice 2: Un cas simple de programme utilisant une Queue, programmé avec l'API JMS
Il consiste en une queue et implémenter le modèle Un producteur / Un consommateur .
L'environnement de développement sera Java, et vous devrez utiliser des jars externes supplémentaires; d'une part activemq-all-5.9.1.jar, et d'autre part, les librairies de l'API JMS (par exemple, si on a installé la version EE de Java7, le jar à utiliser est javaee.jar).
Question 1: Création de la queue par programme
Dans cet exercice, on utilisera une Destination de type PTP (cad une
Queue JMS) par programme. Une fois créée, cad, une fois que le programme
aura été lancé avec succès une fois, la queue existera (le MOM se sera
chargé de l'instancier) et est donc aussi manipulable via la console
d'administration de ActiveMQ!
Il s'agit du cas le plus simple. Il consiste en un unique programme
qui implémente le code du producteur et du consommateur (recevant les
messages de manière réactive par le biais de la méthode onMessage()).
Réaliser l'exercice par étapes:
- Création de la connection qui permettra de se brancher
correctement au broker. (voir
http://docs.oracle.com/javaee/6/api/javax/jms/Connection.html pour plus
d'infos sur une Connection)
- Code du producteur qui crée une session,http://docs.oracle.com/javaee/6/api/javax/jms/Session.html et qui crée explicitement un accès à la queue grâce à un nom (ceci n'est pas JMS compliant mais propre à AvtiveMQ) et se déclare producer. Puis, il devrait produire quelques messages, mais, attendre la question suivante !
- Code du consommateur qui crée une session et se déclare consommateur
sur la queue (qu'on a explicitement identifiée dans le code au point
2). Il code donc la méthode onMessage(), et dans cette question, il ne
fait qu'afficher un print sur la console pour dire qu'un message a été
reçu (sans regarder le contenu du message, ce sera fait plus bas)
- Création des messages et envoi dans la queue, par la console d'administration
Correction Exo2_Question 1
L'opération de création de la queue est telle que si la queue existe
déjà, ce n'est pas grave! On peut détruire la queue par la console
d'administration. On peut aussi détruire la queue et la recréer en lui
donnant le même nom, par la console, émettre quelques messages: si l'on
relance le programme, les onMessage() invoqués montrent qu'il vide bien
la queue.
Question 2: Utilisation de JNDI pour identifier la queue
La spécification JMS requiert d'utiliser JNDI pour localiser le
broker, ainsi que pour localiser les objets de type
java.jmx.Destionation que sont les queues, et topics. Cela permet donc
de s'abstraire totalement du broker utilisé.
Le service de nommage JNDI utilisé dans ActiveMQ place les noms de
queues dans un contexte nommé dynamicQueues. Ainsi les noms de queues qui seront recherchés dans le service de nommage sont de la forme dynamicQueues/queueExo2.
Soit (et c'est mieux) on peut utiliser des propriétés de JVM, pour
spécifier le type du contexte de nommage, et la manière de s'y
connecter (accès à ce service). Il faut penser à utiliser les bonnes
propriétés de JVM (dont le nom se trouve p.37 du cours sur JNDI, par
exemple java.naming.provider.url)
Soit on peut indiquer ces propriétés en passant par une Hashtable mais
on perd l'avantage de ne pas avoir à recompiler si on change
l'emplacement ou la technologie utilisée pour le service de nommage. On
doit mettre dans la hashtable par put, le nom de la propriété ou une
constante (ex, de nom Context.PROVIDER_URL) qui permet d'indiquer le nom
de cette propriété de JVM.
Correction Exo2 Question 2
Question 3: Echanger des messages typés
Jusqu'à présent, notre programme ne traitait pas les messages, donc leur contenu (body) nous était indifférent.
Commencez par afficher le message reçu par la méthode onMessage(). Vous voyez toutes les propriétés qu'il contient.
- Faites en sorte pour commencer que chaque message envoyé soit un
javax.jms.TextMessage. Vous devriez voir le texte qu'il contient lors de
l'affichage du message complet
- Modifiez le message pour qu'il soit à présent un javax.jms.MapMessage
, et donnez lui au moins 2 champs de type différent. Coté récepteur, affichez clairement ces champs et leurs valeurs
- Positionnez un sélecteur de messages sur la destination, simulant le
fait que le consommateur n'est pas intéressé par tous les messages
postés. Pour cela, chaque message contiendra aussi une propriété
(applicative), et on pourra positionner un sélecteur de message. Exemple
lors de la fabrication d'un message: if (i%2==0)
mess.setStringProperty("typeMess","important"); , et donc, le sélecteur se positionnera ainsi javax.jms.MessageConsumer qReceiver = receiveSession.createConsumer(queue,"typeMess = 'important'"); Constatez que des messages vont donc rester dans la queue une fois produits.
- Illustration du fait que plusieurs MessageReceiver peuvent consommer
de la même queue. Extension du modèle 1 producteur - 1 consommateur,
vers 1 producteur - 2 consommateurs: Rajoutez simplement une autre
propriété, et faites en sorte que le second MessageReceiver sélectionne
les messages selon une autre règle que le premier MessageReceiver .
Chacun des MessageReceiver va consommer les messages sélectionnés, et il
pourra donc encore rester des messages dans la quueue.
Correction Exo2 Question 3
Exercice 3: Aspect multi-protocole de ActiveMQ
Sans aller très loin pour autant, étudiez les exemples fournis dans
l'installation de ActiveMQ. Un des exemples fournis est celui qui publie
et qui souscrit à des messages, sur un topic. Il y a une implémentation
fournie utilisant l'API JMS (se trouvant dans le répertoire apache-activemq-5.9.1\examples\openwire\java\src\main\java\example, et une autre utilisant un autre protocole, par exemple, MQTT. Celui ci se trouve dans le répertoire apache-activemq-5.9.1\examples\mqtt\java\src\main\java\example.
Quelles sont les différences majeures ?
Page maintenue par Francoise Baude @2014-