Sommaire Java Message Service Technique Blog

Photos

Liens

Debian GNU/Linux

Valid HTML 4.01 Transitional

JMS Tutorial: La programmation d'une application cliente (Envoi de messages)

Une introduction à l'API de communication en mode message de la plate-forme Java EE (J2EE).

La programmation d'une application cliente utilisant l'API Java Message Service.


Résumé:

Cet exemple de code décrit l'envoi de messages avec l'API Java Message Service (JMS), l'utilisation de l'annuaire JNDI et des objets QueueSender, QueueSession et TextMessage. L'ajout des objets administrés dans l'annuaire JNDI du provider JMS est décrite. L'envoi de messages est fait ici avec une Session transactionnelle. On montre ensuite comment libérer les ressources allouées et fermer le contexte JNDI et la connexion JMS.

Le provider JMS utilisé est le provider JMS de Sun, Sun Java System Message Queue.


Mots clés:

TextMessage, JMS, Envoi de messages, exemples JMS, JMS Client examples, JMS Samples, JMS sample code, Java Message Service, MessageProducer, QueueSender, J2EE, Java EE, Message Oriented Middleware, Communication en mode message, Store and Forward, Publish/Subscribe, Publication/Abonnement, ééchanges asynchrones, Providers, Message Broker.

Les Message Oriented Middleware

Java Message Service (Sommaire)

Les objets utilisés dans l'API JMS

La programmation d'un client JMS - Envoi de messages


L'envoi de messages avec JMS

Provider JMS utilisé

Dans ce programme d'exemple, on utilise le provider Sun Java System Message Queue pour envoyer des messages JMS, mais ce qui est présenté ici fonctionne avec n'importe quel provider JMS pourvu qu'on dispose:

Ajout des objets dans l'annuaire JNDI du Provider JMS

Avec Sun Java System Message Queue, on procèdera de la façon suivante:

Création du répertoire de l'annuaire JNDI

On utilise l'annuaire JNDI en fichier plat de Sun Java System Message Queue.

Pour cela, on crée le répertoire qui contiendra le fichier .bindings:

mkdir -p /var/imq/imq_admin_objects

Ajout d'une QueueConnectionFactory dans JNDI

imqobjmgr add -t qf -l cn=QueueConnectionFactory \
              -j java.naming.factory.initial=com.sun.jndi.fscontext.RefFSContextFactory \
              -j java.naming.provider.url=file:///var/imq/imq_admin_objects

Ajout d'une Queue Queue1 dans JNDI

imqobjmgr add -t q -l cn=Queue1 \
              -o imqDestinationName=MyQueue \
              -j java.naming.factory.initial=com.sun.jndi.fscontext.RefFSContextFactory \
              -j java.naming.provider.url=file:///var/imq/imq_admin_objects

Ici cn=Queue1 fait référence au nom JNDI de la Queue, à savoir Queue1.

Et imqDestinationName=MyQueue désigne le nom physique de la Queue: MyQueue.

Créer un contexte JNDI et une connexion JMS

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;

import javax.naming.NamingException;

import javax.jms.QueueConnectionFactory;
import javax.jms.QueueConnection;

import javax.jms.JMSException;

public class JmsSendExample {

    public static final String JNDI_PREFIX = "cn=";
    public static final String INITIAL_CONTEXT_FACTORY = "com.sun.jndi.fscontext.RefFSContextFactory";
    public static final String PROVIDER_URL = "file:///var/imq/imq_admin_objects";
    public static final String QUEUE_CONNECTION_FACTORY = "QueueConnectionFactory";
    public static final String QUEUE = "Queue1";

    public static void main(String args[]) {
        Hashtable env;
        InitialContext context;
        QueueConnectionFactory qcf;
        QueueConnection connection;

        env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_FACTORY);
        env.put(Context.PROVIDER_URL, PROVIDER_URL);

        try {
            context = new InitialContext(env);
            qcf = (javax.jms.QueueConnectionFactory)context.lookup(JNDI_PREFIX + QUEUE_CONNECTION_FACTORY);
            connection = qcf.createQueueConnection();

            ...
        }
        catch (javax.naming.NamingException ne) {
            ne.printStackTrace();
        }
        catch (javax.jms.JMSException jms) {
            jms.printStackTrace();
        }
    }
}

Dans l'exemple précédent, on notera:

Créer une Session JMS et un QueueSender

On ajoute les imports suivants:

import javax.jms.QueueSession;
import javax.jms.Queue;
import javax.jms.QueueSender;

Puis:

QueueSession session;
Queue queue;
QueueSender sender;

try {
    session = connection.createQueueSession(true, 0);
    queue = (javax.jms.Queue)context.lookup(JNDI_PREFIX + QUEUE);
    sender = session.createSender(queue);
}
catch (javax.naming.NamingException ne) {
    ne.printStackTrace();
}
catch (javax.jms.JMSException jms) {
    jms.printStackTrace();
}

On crée ici:

Créer et envoyer un message texte JMS

On ajoute les imports suivants:

import javax.jms.TextMessage;

Puis:

TextMessage message;

try {
    message = session.createTextMessage("This is a sample JMS message");
    sender.send(message);
    session.commit();
}
catch (javax.jms.JMSException jms) {
    jms.printStackTrace();
}

On a:

Libérer les ressources JMS

Le langage Java ne dispense pas de libérer les ressources allouées.

Avec l'API JMS, cela se fait par l'appel des méthodes close() de certains objets JMS.

Dans cet exemple d'envoi de message JMS, nous avons créé un contexte JNDI, une connexion et une session JMS ainsi qu'un QueueSender.

Le premier objet à libérer est le contexte JNDI. La fermeture du contexte JNDI peut être faites dès que tous les appels à lookup() sont effectués ; inutile d'attendre la fin de l'applicatif JMS:

try {
    context.close();
}
catch (javax.naming.NamingException ne) {
    ne.printStackTrace();
}

On va ensuite fermer la Connection JMS comme suit:

try {
    connection.close();
}
catch (javax.jms.JMSException jms) {
    jms.printStackTrace();
}

Le fait de fermer la Connection JMS fermera automatiquement la ou les Session(s) associées ainsi que l'objet QueueSender.

Si l'on veut être certain que la fermeture de la Connection soit faites systématiquement, cet appel à connection.close(); peut être placé dans un bloc finally qui sera exécuté même en cas d'Exception.

Attention: En cas d'appel à System.exit(), le code du bloc finally ne sera pas appelé.

La fermeture de la Connection JMS est particulièrement importante car la plupart des providers JMS implémentent cette connexion par une connexion TCP/IP, qui, si elle n'est pas fermée par l'applicatif JMS, sera toujours active si le Thread Java qui l'a créé continue de s'exécuter.

Il n'est pas besoin de fermer les objets ConnectionFactory ; l'interface ConnectionFactory ne comporte pas de méthode close().


Voir aussi Message Oriented Middleware,

Réception synchrone de messages JMS,

Télécharger les programmes d'exemple JMS