Conception d'une application d'entreprise pour utilisation de JMS
Vous devez tenir d'un grand nombre d'éléments lorsque vous concevez une application pour utiliser les API JMS directement pour la messagerie asynchrone.
Procédure
- Pour les opérations de messagerie, vous devez écrire des programmes d'application
utilisant uniquement les références aux interfaces définies dans le module javax.jms de
Sun. JMS définir une vue générique de messagerie mappée au transport sous-jacent. Une application d'entreprise qui utilise JMS utilise les interfaces suivantes définies dans le package javax.jms de Sun :
- Connexion
- Fournit l'accès au transport sous-jacent et est utilisé pour créer des sessions.
- Session
- Fournit un contexte pour produire et utiliser des messages, y compris les méthodes utilisées pour créer MessageProducers et MessageConsumers.
- MessageProducer
- Utilisé pour envoyer des messages.
- MessageConsumer
- Utilisé pour recevoir des messages.
Les interfaces JMS génériques sont subdivisées en versions plus spécifiques pour le comportement Point à point et Publication/Abonnement.Tableau 1. Versions Point à point et Publication/Abonnement des interfaces JMS communes. La première colonne de ce tableau répertorie les interfaces JMS communes. La deuxième colonne décrit les interfaces point à point correspondantes et la troisième colonne recense les interfaces Publication/Abonnement correspondantes. Interfaces habituelles de JMS Interfaces point-à-point Interfaces de publication/abonnement ConnectionFactory QueueConnectionFactory TopicConnectionFactory Connexion QueueConnection TopicConnection Destination File d'attente Sujet Session QueueSession, TopicSession, MessageProducer QueueSender TopicPublisher MessageConsumer QueueReceiver,
QueueBrowserTopicSubscriber Pour plus d'informations sur l'utilisation de ces interfaces JMS, voir la documentation sur Java™ Message Service et la section Using Java du centre de documentation IBM MQ.
La section "Java Message Service (JMS) Requirements" de la spécification J2EE contient une liste des méthodes qui ne doivent pas être appelées dans les conteneurs Web et EJB :javax.jms.Session method setMessageListener javax.jms.Session method getMessageListener javax.jms.Session method run javax.jms.QueueConnection method createConnectionConsumer javax.jms.TopicConnection method createConnectionConsumer javax.jms.TopicConnection method createDurableConnectionConsumer javax.jms.MessageConsumer method getMessageListener javax.jms.MessageConsumer method setMessageListener javax.jms.Connection setExceptionListener javax.jms.Connection stop javax.jms.Connection setClientID
Cette restriction de méthode est appliquée dans WebSphere Application Server en générant une exception javax.jms.IllegalStateException!.
- Sous WebSphere Application
Server, les applications font référence aux ressources JMS prédéfinies en tant qu'objets administrés.
Les caractéristiques des ressources JMS utilisées par les applications d'entreprise sont définies pour WebSphere Application Server et liées à l'espace de nom JNDI par le support d'administration de WebSphere. Une application d'entreprise peut extraire ces objets de l'espace de nom JNDI et les utiliser sans avoir à connaître quoi que ce soit de leur mise en oeuvre. L'architecture de messagerie sous-jacente définie par les ressources JMS peut ainsi être modifiée sans nécessiter de changements de l'application d'entreprise.
Tableau 2. Ressources JMS pour la messagerie Point à point et Publication/Abonnement. La première colonne du tableau contient les ressources JMS de la messagerie point à point et la seconde colonne répertorie les ressources JMS de publication/abonnement. Point-à-point Publication/Abonnement ConnectionFactory (ou QueueConnectionFactory)
File d'attenteConnectionFactory (ou TopicConnectionFactory)
SujetUne fabrique de connexions sert à créer des connexions entre le fournisseur JMS et le système de messagerie et encapsule les paramètres de configuration nécessaires pour créer des connexions.
- Afin d'améliorer les performances, le serveur d'applications met en pool les connexions et les sessions avec le fournisseur JMS. Vous devez configurer les propriétés du pool de connexions et de sessions de façon appropriée pour vos applications, sinon, vous risquez de ne pas obtenir le comportement de connexion et de session que vous souhaitez.
- Les applications ne doivent pas placer en mémoire cache les connexions JMS, les sessions, les producteurs ou les consommateurs. WebSphere Application
Server ferme ces objets lorsqu'un bean ou un servlet se termine ; dans ce cas, les tentatives d'utilisation d'un objet en cache échouent avec une exception javax.jms.IllegalStateException.
Pour améliorer les performances, les applications peuvent placer en mémoire cache des objets JMS qui ont été recherchés avec JNDI. Par exemple, un EJB ou un servlet ne doivent rechercher une fabrique de connexions JMS qu'une seule fois, mais ils doivent appeler la méthode createConnection à chaque instanciation. Du fait de l'impact du regroupement des connexions et des sessions avec le fournisseur JMS, il ne doit pas y avoir d'effets sur les performances.
- Un abonné non durable ne peut être utilisé que dans le contexte de transaction (par exemple, une transaction globale ou un contexte de transaction non indiqué) qui existait lors de la création de l'abonné.
- Utilisation d'abonnements durables avec le fournisseur de messagerie par
défaut. Un abonnement durable à une rubrique JMS permet à un abonné de recevoir une copie
de tous les messages publiés sur cette rubrique, même pendant les périodes où l'abonné
n'est pas connecté au serveur. En conséquence, les applications de l'abonné peuvent
fonctionner sans connexion au serveur sur de longues périodes, puis se reconnecter et
traiter les messages publiés en leur absence.
Lorsqu'une application crée un abonnement
durable, il est ajouté dans la liste d'exécution que les administrateurs peuvent afficher
et modifier via la console d'administration.A chaque abonnement durable est attribué un identificateur unique, IDclient##subName où :
- ICclient
- Identificateur du client permettant d'associer une connexion et ses objets aux messages gérés pour les applications (comme clients du fournisseur JMS). Vous devez utiliser une convention d'appellation qui vous aide à identifier les applications, au cas où vous auriez besoin de relier des abonnements durables aux applications associées pour l'administration de l'environnement d'exécution.
- NomAbon
- Nom d'abonnement utilisé pour identifier de manière unique un abonnement durable dans un identificateur de client donné.
Pour les abonnements durables créés par des beans gérés par message, ces valeurs sont définies dans la spécification d'activation JMS. Pour les autres abonnements durables, l'dentificateur client est défini dans la fabrique de connexions JMS et le nom d'abonnement est spécifié par l'application dans l'opération createDurableSubscriber.
Pour créer un abonnement durable à un sujet, une application utilise l'opération createDurableSubscriber définie dans l'API JMS :public TopicSubscriber createDurableSubscriber(Topic topic, java.lang.String subName, java.lang.String messageSelector, boolean noLocal) throws JMSException
- rubrique
- Nom de la rubrique JMS sur laquelle porte l'abonnement. Il s'agit du nom de l'objet qui prend en charge les interfaces javax.jms.Topic, telles que celles trouvées en recherchant une entrée JNDi pertinente.
- subName
- Nom utilisé pour identifier cet abonnement.
- messageSelector
- Seuls les messages dont les propriétés correspondent à l'expression du sélecteur de message sont distribués aux clients. Une valeur nulle ou une chaîne vide demandent la distribution de tous les messages.
- noLocal
- Si ce paramètre est défini sur true, les messages publiés sur la même connexion que l'abonnement durable ne sont pas distribués.
Les applications peut utiliser deux formes d'arguments de l'opération createDurableSubscriber qui acceptent uniquement les paramètres topic et subName. Cet appel alternatif appelle directement la version à quatre arguments indiquée mais affecte la valeur null à messageSelector (tous les messages sont donc remis) et la valeur false à noLocal (les messages publiés sur la connexion sont donc remis). Par exemple, pour créer un abonnement durable au sujet myTopic avec le nom d'abonnement mySubscription :session.createDurableSubscriber(myTopic,"mySubscription");
Si l'opération createDurableSubscription échoue, elle envoie une exception JMS qui fournit un message et une exception liée qui fournit des détails supplémentaires concernant la cause de l'incident.
Pour supprimer un abonnement durable, une application utilise l'opération unsubscribe définie dans l'API JMS
Normalement, il ne peut y avoir qu'un seul abonné actif (connecté) à la fois par abonnement durable. Toutefois, une application d'abonnement peut s'exécuter sur un serveur d'applications cloné, à des fins de reprise en ligne et d'équilibrage de la charge de travail. Auquel cas, la restriction concernant l'"abonné actif" et levée pour fournir un abonnement durable partagé acceptant simultanément plusieurs clients.
Pour plus d'informations sur l'usage que font les application des abonnements durable, voir la section "Utilisation d'abonnements durables" dans la spécification JMS.
- Déterminez les sélecteurs de messages nécessaires. Le mécanisme de sélection de messages JMS permet de sélectionner un sous ensemble des messages dans une file d'attente afin que ce sous ensemble soit retourné par un appel de réception. Le sélecteur peut faire référence aux zones de l'en-tête du message JMS et aux zones des propriétés du message.
- Intervention sur les messages reçus. Lorsqu'un message est reçu, vous pouvez agir dessus en fonction de ce qui est nécessaire à l'aide de logique de gestion de l'application. Certaines des actions JMS générales consistent à vérifier
que le type de message est correct et à extraire le contenu du message. Pour extraire le contenu du corps du message,
transtypez la classe générique Message (qui est le type de retour déclaré
des méthodes de réception) vers une sous-classe plus spécifique, telle que
TextMessage. Il est préférable de tester la classe du message avant
transtypage, afin de gérer toute erreur imprévue.
Dans cet exemple, l'opérateur instanceof permet de vérifier que le message reçu est de type TextMessage. Le contenu du message est alors extrait en transtypant la sous-classe TextMessage.
if ( inMessage instanceof TextMessage ) ... String replyString = ((TextMessage) inMessage).getText();
- JMS applications using the default messaging provider can access, without any restrictions, the content of messages that have been received from WebSphere Application Server Version 5 embedded messaging or IBM MQ.
- Les applications JMS peuvent accéder à l'ensemble des propriétés JMS_IBM*. These properties are of value to JMS applications that use resources provided by the default
messaging provider, the V5 default messaging provider, or the IBM MQ provider.
For messages handled by IBM MQ, the JMS_IBM* properties are mapped to equivalent IBM MQ Message Descriptor (MQMD) fields. Pour plus d'informations sur les propriétés JMS_IBM* et les zones MQMD, voir la section Using Java du centre de documentation IBM MQ.
- Les applications JMS peuvent utiliser des messages de rapport comme forme de traitement des requêtes/réponses gérées, afin de fournir aux expéditeurs des messages des informations en retour sur le résultat des opérations qu'ils ont envoyé et sur la manière dont leurs messages ont été traités. Les applications JMS peuvent demander un ensemble complet d'options de rapport en utilisant des propriétés de message JMS_IBM_Report_Xxxx. Pour plus d'informations sur l'utilisation des messages de rapport JMS, voir Messages de rapport JMS.
- Les applications JMS peuvent utiliser la propriété JMS_IBM_Report_Discard_Msg pour définir la suppression des messages qui ne peuvent pas être placés dans la file d'attente de destination.
- MQRO_Dead_Letter_Queue
- Il s'agit de la valeur par défaut. Le message de demande doit être écrit dans la file d'attente de rebut.
- MQRO_Discard
- Le message de demande doit être éliminé. Option généralement utilisée conjointement avec MQRO_Exception_With_Full_Data de manière à renvoyer un message de non distribution à l'expéditeur du message de demande.
- Utilisation d'un programme d'écoute pour recevoir les messages de
façon asynchrone. Sur un client, et non un servlet ou un bean enterprise, un
autre moyen d'effectuer des appels vers QueueReceiver.receive() consiste à enregistrer
une méthode qui est appelée automatiquement lorsqu'un message approprié est disponible,
par exemple :
... MyClass listener =new MyClass(); queueReceiver.setMessageListener(listener); //application continues with other application-specific behavior. ...
Lorsqu'un message est disponible, il est extrait par la méthode onMessage() sur l'objet de programme d'écoute.import javax.jms.*; public class MyClass implements MessageListener { public void onMessage(Message message) { System.out.println("message is "+message); //application specific processing here ... } }
Lors de la transmission de messages de façon asynchrone, le code de l'application ne peut pas capturer les exceptions provoquées par des échecs à recevoir des messages. Cela est dû au fait que le code de l'application d'exécute pas des appels explicites vers les méthodes receive(). Pour résoudre ce problème, vous pouvez enregistrer un programme d'écoute ExceptionListener qui est une instance d'une classe qui implémente la méthode onException(). En cas d'erreur, cette méthode est appelée avec l'exception envoyée JMSException comme unique paramètre de la méthode.
Pour plus de détails sur l'utilisation d'écouteurs pour la réception asynchrone de messages, voir la documentation JMS (Java Message Service).
Remarque : Au lieu de développer votre propre classe de programme d'écoute JMS, vous pouvez utiliser un bean géré par message, comme indiqué dans la rubrique Programmation à l'aide de beans gérés par messages. Attention lorsque vous exécutez une méthode receive() JMS depuis un composant d'application serveur et que cet appel receive() attend un message produit par un autre composant d'application déployé sur le même serveur. Une telle méthode receive() est synchrone et elle se bloque jusqu'à la réception du message.
Ce type de conception d'application peut générer des problèmes au niveau du consommateur ou du client, où l'ensemble des unités d'exécution de travail peut être épuisé par le composant destinataire bloqué en attendant les réponses. Dans ce cas il ne reste plus d'unité d'exécution pour pouvoir envoyer le composant d'application qui génère le message JMS de réponse. Supposons qu'un servlet et un bean géré par message soient déployés sur le même serveur. Lorsque le servlet envoie une réponse, il envoie un message à une file d'attente gérée par le bean géré par message (à savoir que les messages générés par le servlet sont consommée par la méthode onMessage() du bean géré par message). Le servlet envoie ensuite un receive() et attend une réponse dans une file d'attente temporaire ReplyTo. La méthode onMessage() du bean géré par message exécute une requête de base de données et envoie une réponse au servlet dans la file d'attente temporaire. Si le nombre de demandes de servlet simultanées est important (par rapport au nombre d'unités d'exécution de travail du serveur), il est probable que toutes les unités d'exécution de travail disponibles du serveur seront utilisées pour transmettre une demande de servlet, envoyer un message et attendre une réponse. Le serveur d'applications génère une erreur, car il ne reste aucune unité d'exécution pour traiter les beans gérés par message en attente. Par conséquent, comme les réponses attendues par les servlets sont toutes bloquées, le serveur se bloque, ce qui risque de provoquer un échec de l'application.
Les solutions possibles sont les suivantes :
- Définissez un nombre d'unités d'exécution auxiliaires (nombre d'unités d'exécution par région de serveur * nombre de régions de serveur par serveur) supérieur au nombre d'envois simultanés du composant d'application qui exécute receive() pour qu'une unité d'exécution auxiliaire soit toujours disponible pour envoyer le composant produisant le message.
- Utilisez une topologie d'application qui place le composant d'application du destinataire sur un serveur distinct de celui du composant d'application du générateur. L'utilisation d'unités d'exécution de travail doit toujours être étudiée avec précaution dans ce scénario de déploiement, mais cette séparation garantit qu'il y aura toujours des unités d'exécution qui ne peuvent pas être bloquées par le composant générateur de messages. Il peut exister d'autres interactions à prendre en compte (Par exemple, un serveur d'applications sur lequel plusieurs applications sont installées).
- Modifiez votre application pour effectuer les réceptions de message à partir d'un composant client, qui n'aura pas à partager les unités d'exécution de travail avec le composant du générateur. De plus, le composant client peut effectuer des réceptions asynchrones (non bloquante), interdites par les serveur J2EE. Ainsi, par exemple, l'exemple d'application précédent a pu être modifié pour qu'un client puisse envoyer des messages à une file d'attente et attendre une réponse du MDB.
- If you want to use authentication with IBM MQ or the Version 5 Embedded Messaging support, you cannot have user IDs longer than 12 characters. Par exemple, l'ID utilisateur par défaut de Windows NT, administrator, n'est pas valable avec la messagerie interne WebSphere car il comporte 13 caractères.
- Comme défini dans la spécification EJB, les points suivants s'appliquent à l'utilisation d'indicateurs sur les appels createxxxSession :
- L'indicateur comportant une transaction et transmis sur createxxxSession est ignoré dans une transaction globale et tout le travail est effectué dans le cadre de la transaction. En dehors d'une transaction, l'indicateur comportant une transaction est utilisé et, s'il a pour valeur true, l'application doit utiliser session.commit() et session.rollback() pour contrôler l'exécution du travail. Dans un module EJB 2.0, si l'indicateur comportant une transaction est défini sur true et est situé en dehors d'une transaction XA, la session est impliquée dans la transaction locale WebSphere et l'attribut d'action non résolue de la méthode s'applique au travail JMS, s'il n'est pas validé ou annulé par l'application.
- Les clients ne peuvent pas utiliser Message.acknowledge() pour accusé réception des messages. Si une valeur CLIENT_ACKNOWLEDGE est transmise sur l'appel createxxxSession, le serveur d'applications accuse automatiquement réception des messages et Message.acknowledge() n'est pas utilisé.
- If you want your application to use IBM MQ as an external
JMS provider, then send messages within a container-managed transaction.
When you use IBM MQ as an external JMS provider, messages sent within a user-managed transaction can arrive before the transaction commits. This occurs only when you use IBM MQ as an external JMS provider, and you send messages to a IBM MQ queue within a user-managed transaction. Le message arrive dans la file d'attente de destination avant que la transaction ne soit validée.
The cause of this problem is that the IBM MQ resource manager has not been enlisted in the user-managed transaction.
La solution consiste à utiliser une transaction gérée par conteneur.


http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=tmj_desap
Nom du fichier : tmj_desap.html