Atelier JMS-JMX, Inspiré du chapitre 13 de ce livre http://www.manning.com/sullins/

Thèmes :


Exemple : Automatisation d'un système de contrôle/commandes d'une salle de spectacles.

Pour cette application, les contrôles et les commandes des actionneurs (projecteurs, effets visuels, son, ...) utilisent un bus de communication basé sur JMS. Le système reçoit une commande particulière d'éclairage et en fonction de la scène déclenche une série d'action précise sur les actionneurs. Ces séries d'action sont programmables et dépendent du contexte.

Par exemple lors d'une scène romantique, l'intensité des projecteurs est adaptée et la musique devient douce...

 

[Image]

  figure extraite de ce livre http://www.manning.com/sullins/

L'application utilise un MBean de contrôle (ControllerMBean cf figure) qui écoute les messages destinés au système d'éclairage/(controlMessages), et publie en conséquence les messages destinés aux actionneurs/(deviceMessages).

Par exemple lors de la commande MOVIELIGHTSon, le MBean de contrôle déclenche la descente de l'écran(ScreenDown) et autorise le "surround-sound system"(SurroundOn). De façon complémentaire MOVIELIGHTSoff, remonte l'écran(ScreenUp) et coupe le son(SurroundOff).

 

Le bus JMS utilise le modèle Publish-Suscribe , soit deux "topic" controlMessages et deviceMessages.

Afin de développer cette application vous devez :

 

 

Un "diagramme de séquences possibles " associé à la commande MOVIELIGHTSon

l'interface JMSControllerMBean

public interface JMSControllerMBean{
  public void turnOnHomeTheater();
  public void turnOffHomeTheater();
}

la classe JMSController à compléter

public class JMSController implements MessageListener, JMSControllerMBean{
public void onMessage( Message m ){
  // déclarations 
  try{
    msg = ((TextMessage)m).getText();

    if( msg.equals("MOVIELIGHTSOn") ){
      msg="SurroundOn";
      msg2="ScreenDown";
      publishMessages(msg,msg2); // publier au topic deviceMessages
    }else if( msg.equals("MOVIELIGHTSOff") ){
      msg="SurroundOff";
      msg2="ScreenUp";
      publishMessages(msg,msg2);
    }
 // ...
}

ci-dessous l'adaptateur HTTP de la classe JMSSetup qui est à compléter (voir

  
    public void setHTTPAdapter(int port) throws Exception {
      HtmlAdaptorServer adapter = new HtmlAdaptorServer();
      adapter.setPort(port);
      ObjectName name = new ObjectName("HtmlAdaptorServer:name=html,port="+ port);
      mbs.registerMBean(adapter, name);
      adapter.start();
    }

la classe JMSPublisher complète

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicConnection;
import javax.jms.TopicSession;
import javax.jms.TopicPublisher;
import javax.jms.Topic;
import javax.jms.TextMessage;
import javax.jms.Session;
import javax.jms.JMSException;

import java.util.Hashtable;

public class JMSPublisher{

  private TopicConnection topicConnection=null;
  private TopicSession topicSession=null;
  private TopicPublisher topicPublisher=null;
  private Topic topic=null;
  private TopicConnectionFactory topicFactory = null;

  public JMSPublisher( String factoryJNDI, String topicJNDI ) throws JMSException, NamingException{

    // Get the initial context
    //Context context = new InitialContext();
    Hashtable<String,String> properties = new Hashtable<String,String>();
    properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.exolab.jms.jndi.InitialContextFactory");
    properties.put(Context.PROVIDER_URL, "tcp://localhost:3035/");
    
    Context context = new InitialContext(properties);

    // Get the connection factory
    topicFactory=(TopicConnectionFactory)context.lookup(factoryJNDI);

    // Create the connection
    topicConnection = topicFactory.createTopicConnection();

    // Create the session
    topicSession=topicConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);

    // Look up the destination
    topic = (Topic)context.lookup(topicJNDI);

    // Create a publisher
    topicPublisher = topicSession.createPublisher(topic);
  }

  public void publish(String msg) throws JMSException{

    // Create a message
    TextMessage message = topicSession.createTextMessage();
    message.setText(msg);

    // Publish the message
    topicPublisher.publish(topic, message);
  }

  public void close() throws JMSException {
    topicSession.close();
    topicConnection.close();
  }

  public static void main(String[] args) {
    JMSPublisher publisher=null;

    try{
      publisher= new JMSPublisher("JmsTopicConnectionFactory", "controlMessages");
      String msg = "MOVIELIGHTSOn";

      System.out.println("Publishing message: "+msg);
      publisher.publish(msg);
      try{Thread.sleep(2000);}catch(InterruptedException e){}

      msg = "MOVIELIGHTSOff";
      System.out.println("Publishing message: "+msg);
      publisher.publish(msg);
      try{Thread.sleep(2000);}catch(InterruptedException e){}

      msg = "doNothing";
      System.out.println("Publishing message: "+msg);
      publisher.publish(msg);

      // Close down your publisher
      publisher.close();
    }
    catch(Exception ex) {
      System.err.println("An exception occurred " + "while testing Publisher: " + ex);
      ex.printStackTrace();
    }

  }
}
  

 

l'archive à compléter, le projet bluej, à télécharger ici

 


Paramètres du "contexte" avec OpenJMS pour une utilisation locale

    Hashtable<String,String> properties = new Hashtable<String,String>();
    properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.exolab.jms.jndi.InitialContextFactory");
    properties.put(Context.PROVIDER_URL, "tcp://localhost:3035/");
    context = new InitialContext(properties);

 

un exemple de commandes à adapter selon votre environnement, (en 31 3 02, voir le répertoire c:\openjms)

// initialisation d'OpenJMS 
D:\openjms-0.7.7-beta-1\bin>set JAVA_HOME=C:\jdk1.6.0
D:\openjms-0.7.7-beta-1\bin>admin
// création des deux "topics" : ControlMessages et DeviceMessages
>start java -cp .;D:\openjms-0.7.7-beta-1\lib\openjms-0.7.7-beta-1.jar;C:\BlueJ\lib\userlib\jdmkrt.jar JMSSetup 
>start java -cp .;D:\openjms-0.7.7-beta-1\lib\openjms-0.7.7-beta-1.jar DeviceSubscriber
>start java -cp .;D:\openjms-0.7.7-beta-1\lib\openjms-0.7.7-beta-1.jar JMSPublisher

 

un essai d'accès à votre MBean, ici depuis votre navigateur ici http://localhost:8082/

déclenchez "turnOnHomeTheater" depuis votre navigateur et cette page devrait être affichée

 

ou bien l'exécution de JMSPublisher

start java -cp .;D:\openjms-0.7.7-beta-1\lib\openjms-0.7.7-beta-1.jar JMSPublisher

 


Ajoutez une nouvelle fonctionnalité, un MBean. Vérifiez le couplage faible induit par ce type d'architecture ...

Une nouvelle commande, un nouveau MBean, ...

 

Faites un essai en "intranet" au Cnam. 

Le serveur JNDI est sur un poste du cnam : vivaldi.cnam.fr, port 3035

Hashtable<String,String> properties = new Hashtable<String,String>();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.exolab.jms.jndi.InitialContextFactory");
properties.put(Context.PROVIDER_URL, "tcp://vivaldi.cnam.fr:3035/");
 
context = new InitialContext(properties);

Vérifiez que toute publication engendre bien le réveil de tous les souscripteurs sur toutes les machines

Les mêmes commandes avec le serveur JNDI sur la machine vivaldi.cnam.fr

>start java -cp .;D:\openjms-0.7.7-beta-1\lib\openjms-0.7.7-beta-1.jar;C:\BlueJ\lib\userlib\jdmkrt.jar JMSSetup 
>start java -cp .;D:\openjms-0.7.7-beta-1\lib\openjms-0.7.7-beta-1.jar DeviceSubscriber
>start java -cp .;D:\openjms-0.7.7-beta-1\lib\openjms-0.7.7-beta-1.jar JMSPublisher
Pour vos essais, sur vivaldi.cnam.fr, deux "Topics" supplémentaires peuvent être utilisés : controlMessages2 et deviceMessages2



Installation, utilisation d'OpenJMS avec bluej


OpenJMS Java Message Service

Installation d'OpenJMS

Suivez les instructions d'installation d'OpenJMS sur votre poste

Usage d'OpenJMS avec BlueJ

1) Placez ces archives dans le répertoire d'installation de BlueJ /lib/userlib/

2) Compilez les exemples fournis par OpenJMS, accessibles ici

  • Seule la compilation est possible, l'exécution sera effectuée depuis une console en ligne de commande

3) Démarrez OpenJMS, la mise en oeuvre en ED/JMS est ici

console> \openjms-0.7.7-beta-1\bin>admin
(Actions/Start OpenJMS, puis Connections/online), sans oublier de positionner JAVA_HOME

cette interface vous permettra de créer les files, "topic", etc.. nécessaires ensuite

4) Exécutez dans deux consoles ces deux commandes, votre répertoire se nomme /tp_jms/ !

  • console Sender :

  • console Receiver

En résumé

  • Usage de BlueJ pour la l'édition, compilation et soumissions avec JNEWS
  • L'exécution s'effectue depuis une console avec l'environnement openjms-0.7.7-beta-1/lib