Java, SOA, Architecture & Methodes agiles par Thomas Recloux

Spring JMS : Augmenter les performances

Publié le 29 octobre 2008 par Thomas Recloux

A plusieurs occasions, j’ai eu l’occasion de conseiller l’utilisation de Spring JMS car cette API simplifie énormément la manipulation de l’API JMS qui il faut l’avouer n’est vraiment intuitive.

En effet l’API JMS nécessite de manipuler 6 objets (QueueConnectionFactory, QueueConnection, QueueSession, Queue, MessageProducer, TextMessage) pour simplement envoyer un message texte !

Avant de pouvoir utiliser l’api Spring JMS, il faut configurer une ConnectionFactory  (Exemple avec Active MQ) :

<bean name="activeMqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://theactivemqserver:61616" />
</bean>

Ensuite, il faut récupérer un objet JmsTemplate dans lequel la ConnectionFactory aura été injectée.

Enfin, l’envoi d’un message peut se faire de différentes manières mais un simple appel de la méthode convertAndSend pourra suffir.

Il se trouve que par défaut le JmsTemplate peut limiter les performances des applications car il entraine la création des objets Connection, Session et MessageProducer pour chaque envoi.

La solution peut se trouver du coté du provider JMS qui comme ActiveMQ peut proposer une ConnectionFactory adaptée en gérant un pool d’objets Connection, Session  et MessageProducer.

La solution peut aussi venir d’un objet fourni par Spring depuis la V2.5.3 : CachingConnectionFactory cette ConnectionFactory peut encapsuler n’importe quelle autre ConnectionFactory et mettre en place le cache de Connection, Session et MessageProducer.

Dans mon cas, l’utilisation de la CachingConnectionFactory a résolu nos problèmes. Un profiling de l’application avait montré que nos Threads passait leur temps à ouvrir des Session JMS.

Websphere MQ en JMS / JNDI

Publié le 14 janvier 2008 par Thomas Recloux

Petit problème technique rencontré la semaine dernière : Configurer un logiciel pour utiliser Websphere MQ comme provider JMS via JNDI. En effet, le logiciel (propriétaire) ne propose pas d’instancier directement la ConnectionFactory mais demande une factory JNDI, une URL et un nom JNDI.

Après quelques recherches, j’ai trouvé un article chez IBM qui explique qu’il faut télécharger des support pacs (MS0B & ME01)

La factory à utiliser est « com.ibm.mq.jms.context.WMQInitialContextFactory »

L’url est de la forme « hostWebsphereMq:portManager/channel ». Par exemple : « 192.168.0.25:1414/SYSTEM.DEF.SVRCONN »

Le nom de la connectionFactory est le nom du manager MQ

Voici un exemple de code qui envoie un message texte dans Websphere MQ en JMS via JNDI.

	    /* Environement JNDI */
	    Properties env = new Properties();
	    /* Factory fournie par les support pacs */
	    env.put(Context.INITIAL_CONTEXT_FACTORY,  
               "com.ibm.mq.jms.context.WMQInitialContextFactory");
	    /* serveur:port/channel */
	    env.put(Context.PROVIDER_URL, "mymanager:1414/SYSTEM.DEF.SVRCONN");
	    /* Connexion JNDI */
	    Context context = new InitialContext(env);  

	    /* Recherche de la connection factory (nom du manager) */
	    QueueConnectionFactory queueFactory = (QueueConnectionFactory) context.lookup("MYTSTA"); 

	    /* API JMS classique */
	    QueueConnection queueConnection = queueFactory.createQueueConnection();
	    QueueSession queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
	    Queue queue = queueSession.createQueue("TEST.QUEUE");
	    QueueSender queueSender = queueSession.createSender(queue);
	    TextMessage message = queueSession.createTextMessage();
	    message.setText("Hello World !");
	    queueSender.send(message);
	    queueSession.close();