Advanced   Java   Services JMS  Grundlagen


Was ist JMS

JMS ist ein in Java realisiertes Nachrichtensystem mit dem ein Sender Nachrichten verschicken kann und ein Empfänger diese erhalten kann. Da der Empfänger auch antworten kann, kann der Empfänger auch zum Sender werden und umgekehrt. Weder Sender noch Empfänger müssen ständig verfügbar sein. Je nach Situation kann es mehrere Sender und mehrere Empfänger geben. Abgeschickte bzw. noch nicht abgeholte Nachrichten werden von einer eigenen Instanz verwaltet, dem Java Message Service. Der JMS ist also eine Schicht zwischen Sender und Empfänger und ermöglicht so eine asynchrone Nachrichtenübertragung. Diese Schicht wird gerne auch MOM genannt und dieses Kürzel steht für Message Oriented Middleware.


Wer stellt JMS zur Verfügung

Die JMS-Middleware wird meist von einem WebServer zur Verfügung gestellt. Sowohl Glassfish als auch JBoss stellen JMS zur Verfügung. Apache Tomcat dagegen ist lediglich ein ServletContainer und enthält keine Unterstützung für JMS. Es gibt jedoch JMS-Systeme wie OpenJMS, die man mit Tomcat zusammen verwenden kann.


JMS ist ein Teil von EJB

Alle zur Durchführung notwendigen Aktionen werden durch Javaklassen realisiert die Bestandteil der Java Enterprise Edition sind, einer Erweiterung der Standard Edition mit denen man Enterprise Java Beans realisieren kann. Das zuständige Paket trägt den Namen javax.jms. Die Dokumentation der EJB-Klassen erhält man bei der Installation des Glassfishservers oder hier.


Fabriken und Nachrichtenkanäle

Javaclients müssen also mit dem JMS-System Verbindung aufnehmen und dann ihre Nachrichten schicken bzw. abholen. JMS stellt Mechanismen zur Verbindungsaufnahme und zum Senden und Empfangen von Nachrichten bereit. ConnectionsFactories ermöglichen eine Verbindungsaufnahme und Nachrichtenkanäle ermöglichen das Verschicken und Empfangen von Nachrichten.


JMS-Server muß konfiguriert werden

Ein JMS-fähiger Sebserver muß erst konfiguriert werden bevor ihn ein Client benützen kann. Dazu müssen auf Serverseite die Factories und die Nachrichtenkanäle eingerichtet werden. Für jede Factory und für jeden Kanal werden dabei eindeutige Namen vergeben. Über diese Namen sind die Factories und die Kanaäle durch einen Client ansprechbar. Die Verwaltung der Namen übernimmt das JNDI (java naming and directory service). Wer mehr über JNDI wissen will kann diesem Link folgen. Hier brauchen wir nicht mehr zu wissen, als daß für die Namensauflösung eine eigene Instanz verantwortlich ist. Die Konfiguration von Glassfish werden wir weiter unten beschreiben. Die prinzipiellen Vorgänge sind aber für alle Webserver die gleichen.


Die Nachrichtenkonzepte

JMS unterscheidet zwei grundsätzliche Nachrichtenkonzepte, je nachdem ob eine Nachricht an einen Empfänger oder an mehrere Empfänger geht. Der Sender hei&szig;t auch (Message-) Producer oder Publisher und der Empfänger (Receiver) (Message-)Consumer oder Subscriber.


1 zu 1 Übermittlung (Point to Point Messaging)

Bei dieser Form gibt es genau einen Sender und genau einen Empfänger. Jede Nachricht wird einem genau bestimmten Nachrichtenkanal übergeben und dort aufbewahrt bis der Empfänger sie abholt. Die Nachrichten werden nach dem FIFO-Prinzip (First In First Out) im Kanal gespeichert. Dort bleiben sie bis sie entweder abgeholt werden oder ihre Lebenszeit endet. haben sich mehrere Empfänger mit dem Nachrichtenkanal verbunden erhält derjenige die Nachricht der sie zuerst anfordert (First Come First Serve). Empfänger müssen sich registrieren um überhaupt Nachrichten erhalten zu können.


Queue (Realisierung vonP2P)

Die Realisierung dieses Konzepts wird Queue (Schlange) genannt. Auch die zugehörige Javaklasse heißt Queue, genauer javax.jms.Queue.


1 zu n Übermittlung (Publisher/Subscriber Messaging)

Bei diesem Konzept veröffentlicht der Sender, in diesem Fall auch Publisher genannt eine Nachricht für viele Abnehmer (Subscriber). Die Nachricht wird an alle registrierten Abnehmer automatisch verteilt. Auch hier ist die Lebenszeit einer Nachricht begrenzt.


Topic (Realisierung von Pub/Sub)

Die Realisierung dieses Konzepts wird Topic (Thema, Inhalt) genannt. Auch die zugehörige Javaklasse heißt Topic, javax.jms.Topic.

topic.jpg


Die Architektur der einzelnen Komponenten

Die folgende Graphik zeigt das Zusammenspiel der einzelnen Komponenten. Man sieht, das man alle Komponenten aus einer ConnectionFactory ableiten kann. Die Factory selbst erhält man über einen Initialkontext. Der Kontext stellt dabei die Verbindung zum Server her.

creates2.jpg

Es ergeben sich also die folgenden Schritte:

Wir werden gleich die entsprechenden JavaStatements dazu sehen. Zunächst aber müssen wir den Server konfigurieren.


Einrichten von JMS mit Glassfish

Wir verbinden uns über den port 4848 mit der Admin Console und wählen dann über Resources zunächst JMS Resources und dann Connection Factories an.

creates2.jpg     creates2.jpg

Hier tragen wir als Erstes die Connection Factories ein. Es gibt drei verschiedene.


Die drei ConnectionFactories
Factory JNDI Name
java.jms.ConnectionFactory jms/ConnectionFactory
java.jms.QueueConnectionFactory jms/QueueConnectionFactory
java.jms.TopicConnectionFactory jms/TopicConnectionFactory

Die JNDI-Namen sind übrigens frei wählbar, die angegebenen Werte folgen jedoch der üblichen Konvention in Java/JMS.

creates2.jpg

creates2.jpg

creates2.jpg

creates2.jpg

Genauso trägt man auch die TopicFactory ein.


Einrichten der Nachrichtenkanäle

Nun müssen noch die Nachrichtenkanäle selbst eingetragen werden. Wie erwähnt gibt es Queue und Topic. Will man dem Empfänger einer Nachricht aus der Queue die Möglichkeit einer Antwort einräumen, muß eine zweite Queue mit einem eigenen Namen eingerichtet werden. Analog auch für Topic.

Factory JNDI Name
java.jms.Queue jms.Queue
java.jms.Topic jms.Topic

In diesem Fall ist die JNDI-Namensgebung nicht so standardisiert wie bei den Factories. Auf jeden Fall sollte aus dem Namen hervorgehn, ob es sich um Queue oder Topic handelt.

creates2.jpg

creates2.jpg

creates2.jpg

creates2.jpg

creates2.jpg

Je nach Situation trägt man weitere Nachrichtenkanäle ein. Jeder Kanal wird über einen eindeutigen JNDI-Namen identifiziert. Ein Client muß die JNDI-Namen der Factories und der Kanäle kennen um Verbindung aufnehmen zu können.


Was braucht der Client

Leider ist es nicht so einfach herauszufinden, welche Javaarchive auf Clientseite notwendig sind, um überhaupt einen Sender oder Empfänger starten zu können. Nach einiger Recherche findet man folgendes:

Hier das Ergebnis für GlassFish 4


Notwendige Archive

jms.jar

Dieses Archiv findet man in <glassfish4home>\mq\lib. Es enthält die Klassen aus dem Package javax.jms und man kann es an einen Ort seiner Wahl kopieren.


gf-client.jar

Dieses Archiv findet man in <glassfish4home>\glassfish\lib. Es ist leider kein echtes Archiv sondern enthält geschätzt mehrere Hundert relative Verweise auf (echte) Archive im Verzeichnis <glassfish4home>/glassfish/modules. Aus diesem Grund darf dieses 'Archiv' auch nicht bewegt werden, sondern der Java Build Path muß genau auf diesen Ort zeigen, was für einen echten Client ja unmöglich ist...


Eine GlassFish 3 Lösung

Für die Vorgängerversion gibt es eine Auflistung echter Archive auf stackoverflow. es sind 38 Archive, die hier alphabetisch geordnet aufgeführt werden.

auto-depends.jar
bean-validator.jar
common-util.jar
config-api.jar
config-types.jar
config.jar
connectors-internal-api.jar
container-common.jar
deployment-common.jar
dol.jar
ejb-container.jar
ejb.security.jar
glassfish-api.jar
glassfish-corba-asm.jar
glassfish-corba-codegen.jar
glassfish-corba-csiv2-idl.jar
glassfish-corba-internal-api.jar
glassfish-corba-newtimer.jar
glassfish-corba-omgapi.jar
glassfish-corba-orb.jar
glassfish-corba-orbgeneric.jar
glassfish-naming.jar
gmbal.jar
hk2-core.jar
internal-api.jar
javax.ejb.jar
javax.jms.jar
javax.resource.jar
javax.servlet.jar
javax.transaction.jar
jta.jar
kernel.jar
management-api.jar
orb-connector.jar
orb-iiop.jar
security.jar
ssl-impl.jar
transaction-internal-api.jar

stackoverflow: connecting-a-remote-jms-client-to-glassfish-3
stackoverflow: standalone-java-glasshfish-client-reference-to-gf-client-jar
stackoverflow: how-to-include-javax-jms-in-eclipse