31 mars 2010
Imprimer ce billet

JMS/ActiveMQ : Spring vs Grails

Vous avez peut être entendu parler de Grails, ce nouveau framework Web Java qui vise à fournir une solution simple, rapide et efficace pour créer des applications Web JEE. Grails est une plateforme de développement qui grâce à son système de plugins intègrent plusieurs APIs et frameworks de l'écosystème Java visant ainsi à fournir une stack complète packagée et intégrée pour répondre d'une manière efficace et élégante aux différentes problématiques liées à la création des applications d'entreprises orientées Web...

Dans ce premier billet, nous nous attarderons sur la comparaison entre deux implémentations d'une application utilisant JMS et ActiveMQ : une première implémentation avec Spring et JMS et une deuxième avec le plugin grails-activemq.

JMS et ActiveMQ avec Spring

Je vous propose dans un premier temps une implémentation de base d'ActiveMQ avec Spring. Pour cela plusieurs étapes sont nécessaires :

  • Télécharger et installer ActiveMQ.
  • Créer un pom.xml avec les dépendances nécessaires.
  • Déclarer les beans nécessaires dans le fichier applicationContext-services.xml :
<?xml version="1.0" encoding="ISO-8859-1"?>
<beans>

<!-- pool de connection JMS -->
<bean id="jmsFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy- method="stop">
  <property name="connectionFactory">
    <bean class="org.apache.activemq.ActiveMQConnectionFactory">
      <property name="brokerURL">
        <value>tcp://localhost:61616</value>
      </property>
    </bean>
  </property>
</bean>

<!-- template JMS Spring simplifiant la gestion des message JMS -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
  <property name="connectionFactory">
    <ref local="jmsFactory"/>
   </property>
</bean>

<!-- Définition d'une queue permettant d'échanger les message JMS -->
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
  <constructor-arg index="0">
    <value>queue.destination</value>
   </constructor-arg>
</bean>

<!-- Template JMS Spring simplifiant la gestion des message JMS -->
<bean id="listenerSample" class="sample.activemq.ListenerSample "/>
<bean id="listenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
  <property name="concurrentConsumers" value="3"/>
  <property name="connectionFactory" ref="jmsFactory" />
  <property name="destination" ref="destination" />
  <property name="messageListener" ref="listenerSample" />
</bean>

<!-- création d'un bean spring qui utilise le template JMS et la destination pour envoyer les message -->
<bean id="springProducer" class="sample.activemq.ProducerSample">
  <property name="template" ref="jmsTemplate"/>
  <property name="destination" ref="destination"/>
</bean>

</beans>

  • Créer le bean ProducerSample, qui s'appuie sur JmsTemplate de Spring pour créer et envoyer les messages JMS :
package sample.activemq;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import java.util.Date;

/**
 * @author karl verger
 */

public class ProducerSample {
   private JmsTemplate jmsTemplate;
   private Destination destination;

   public void sendMessage(){
      MessageCreator messageCreator = new MessageCreator() {
        public Message createMessage(Session session) throws JMSException {
           TextMessage textMessage = session.createTextMessage();
           textMessage.setText("Hi, this is a Hello World with JMS & ActiveMQ, " + new Date());
           textMessage.setJMSType("text");
           return textMessage;
        }
      };
      getTemplate().send(getDestination(), messageCreator);
    }

    public JmsTemplate getJmsTemplate() {
      return jmsTemplate;
    }

    public void setJmsTemplate(JmsTemplate template) {
      this.jmsTemplate = jmsTemplate;
    }

    public Destination getDestination() {
      return destination;
    }

    public void setDestination(Destination destination) {
     this.destination = destination;
    }
}

  • Créer le bean ListenerSample pour consommer les messages de manière asynchrone :
package sample.activemq;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

/**
 * @author karl verger
 */

public class ListenerSample implements MessageListener {

   public void onMessage(Message message) {
     try {
        System.out.println("GOT MESSAGE: "+ ((TextMessage)message).getText() );
     } catch (JMSException ex) {
        Logger.getLogger(JmsListenerSample.class.getName()).
        log(Level.SEVERE, null, ex);
     }
   }
}

JMS et ActiveMQ avec Grails

Je vais essayer de démontrer à quel point l'utilisation de Grails permet de simplifier l'implémentation d'ActiveMQ et de booster la productivité. La mise en place de JMS avec Grails et ActiveMQ nécessite les étapes suivantes :

  • Installer le plugin ActiveMQ avec la commande : grails install-plugin activemq
  • Installer le plugin JMS avec la commande : grails install-plugin jms
  • Créer une classe Groovy pour la production de messages :
class ProducerSample {
    def index = {
        def message = "Hi, this is a Hello World with JMS & ActiveMQ, " + new Date()
        sendJMSMessage("queue.destination", message)
        render message
    }
}

  • Créer un service Groovy pour la réception des messages :
class ListenerSample {
    boolean transactional = false
    static expose = ['jms']
    static destination = "queue.destination"

    def onMessage = {
       println "GOT MESSAGE: $it"
    }
}

Retour d'expérience

La création et la préparation du projet Grails est très simple, l'outil create-app permet de générer rapidement la structure du projet avec des exemples de code fonctionnel. Avec Spring plusieurs étapes sont nécessaires pour la création et la configuration du projet.

Avec Grails, la configuration par défaut est générée lors de l'installation des plugins JMS et ActiveMQ ce qui n'est pas le cas pour l'exemple Spring ou une déclaration des beans est nécessaire dans le fichier application-services.xml.

Le plugin grails-activemq fournit une solution simple pour l'échange de messages entre applications et composants permettant ainsi de booster la productivité et de produire un code simple et facilement maintenable. Toutefois, ce plugin n'est toujours pas production ready et reste donc, pour le moment, à tester à petite échelle.