Ausarbeitung - Department of Information Systems

Werbung
Westfälische Wilhelms-Universität Münster
Ausarbeitung
Message Oriented Middleware:
Technische Aspekte der Umsetzung von EAI
im Rahmen des Seminars Enterprise Architecture Management
Benjamin Oberste-Berghaus
Themensteller: Prof. Dr. Herbert Kuchen
Betreuer: Dipl.- Wirt.Inform. Christoph Lembeck
Institut für Wirtschaftsinformatik
Praktische Informatik in der Wirtschaft
Inhaltsverzeichnis
1
Middleware und Enterprise Application Intergration................................................ 3
2
Message Oriented Middleware .................................................................................. 4
3
2.1
Middleware ....................................................................................................... 4
2.2
Remote Procedure Call ..................................................................................... 5
2.3
Object Oriented Middleware ............................................................................ 5
2.4
Message Oriented Middleware ......................................................................... 6
2.5
MOM und Enterprise Application Integration.................................................. 7
Java Message Service ................................................................................................ 9
3.1
Grundlagen........................................................................................................ 9
3.2
Kommunikationsmodelle................................................................................ 10
3.2.1
3.2.2
3.3
Nachrichten..................................................................................................... 12
3.4
Interfaces......................................................................................................... 13
3.5
Erweiterte Konzepte ....................................................................................... 16
3.5.1
3.5.2
3.5.3
4
Point-to-Point.............................................................................................. 10
Publish/Subscribe........................................................................................ 11
Zuverlässigkeit............................................................................................ 16
Transaktionen.............................................................................................. 18
Request Reply ............................................................................................. 20
Message Driven Beans ............................................................................................ 21
4.1
Grundlagen...................................................................................................... 21
4.2
Lebenszyklus .................................................................................................. 22
4.3
Beurteilung...................................................................................................... 23
5
Zusammenfassung ................................................................................................... 25
A
WM-Ticket-Beispiel ................................................................................................ 26
Literaturverzeichnis ........................................................................................................ 34
II
Kapitel 1: Middleware und Enterprise Application Intergration
1 Middleware und Enterprise Application Intergration
In Unternehmen gibt es häufig eine Vielzahl von unterschiedlichen Applikationen,
Plattformen und Datenbanken, die historisch nebeneinander gewachsen sind. Neben
diesen Altsystemen ist die Nutzung von neueren Technologien, wie Intranet und Internet, für eine effiziente und effektive Wettbewerbsstrategie erforderlich. Middleware
ermöglicht diesen unterschiedlichen Softwarekomponenten miteinander zu kommunizieren. Ziel der Enterprise Application Integration ist es die intra- und interorganisatorischen Geschäftsprozesse zu optimieren. Dafür ist die Kommunikation zwischen den
Softwaresystemen, und deswegen Middleware notwendig. Innerhalb dieser Ausarbeitung wird zunächst begründet, weshalb sich gerade Message Oriented Middleware auf
dem Gebiet der Enterprise Application Integration durchsetzt (Kapitel 2). Anschließend
wird der Java Message Service, als eine mögliche Spezifikation für Message Oriented
Middleware, näher erläutert (Kapitel 3). Abschließend werden Message Driven Beans
vorgestellt, welche die asynchrone Kommunikation auf Ebene der Enterprise Java
Beans unterstützen (Kapitel 4).
3
Kapitel 2: Message Oriented Middleware
2 Message Oriented Middleware
Dieses Kapitel führt zunächst in den Begriff „Middleware“ ein (Abschnitt 2.1) und stellt
in den Abschnitten 2.2 - 2.4 drei Typen von Middleware vor. Abschließend soll in Abschnitt 2.5.herausgearbeitet werden, warum sich gerade Message Oriented Middleware
für die Enterprise Application Integration eignet.
2.1 Middleware
Der Begriff „Middleware“ ist, wie viele andere in wissenschaftlichen Diskussionen,
nicht einheitlich definiert. Eine weit gefasste Definition von Linthicum dient als Grundlage dieser Ausarbeitung: „Middleware is basically any type of software that facilitates
communication between two or more software systems“ [Li99, S. 100]. Anhand dieser
Definition lassen sich die wichtigsten Merkmale von Middleware identifizieren. Zunächst ist Middleware ein softwarebasiertes Konzept. Ein weiterer Bestandteil der Definition ist, dass Middleware eingesetzt wird, um Kommunikation zu ermöglichen. Auf
Softwaresysteme bezogen, bedeutet Kommunikation den Austausch von Daten bzw.
Informationen. Diese kann hierbei sowohl zwischen zwei, als auch zwischen mehreren
Softwaresystemen stattfinden. Die Softwaresysteme zwischen denen die Kommunikation ermöglicht werden soll, weisen i.d.R. einen hohen Grad an Heterogenität auf. Die
Heterogenität der Softwaresysteme kann sich auf viele Bereiche der Softwaresysteme,
wie die Programmiersprache, Plattformen und Inhalt, beziehen. Das Verbergen der Heterogenität der zu Grunde liegenden Netzwerke, Hardware, Betriebssysteme und Programmiersprachen ist nach Coulouris das zentrale Ziel der Middleware [CDK01, S. 35].
Der Name „Middleware“ resultiert aus der Tatsache, dass die von Middleware angebotenen Dienste zwischen der Betriebssystemschicht und der Applikationsschicht ausgeführt werden [JBLN01, S. 27].
Middleware wird je nach Zweck unterschiedlich klassifiziert. Eine gängige Klassifizierung unterteilt Middleware anhand der beteiligten Softwaresysteme bzw. der ausgetauschten Informationen in Remote Procedure Calls, Object Oriented Middleware, Database Oriented Middleware und Message Oriented Middleware [Li99, JBLN01, Ke02].
Da Message Oriented Middleware im Mittelpunkt dieser Ausarbeitung steht, wird eine
grobe, aber für das Ziel der Ausarbeitung zweckmäßige Klassifizierung in synchrone
4
Kapitel 2: Message Oriented Middleware
und asynchrone Middleware vorgenommen. Dadurch ist es möglich die Unterschiede
zwischen den Kommunikationsparadigmen deutlich herauszustellen. Wie noch gezeigt
wird, arbeiten Remote Procedure Calls und Objekt Oriented Middleware mit synchroner
Kommunikationsmechanismen und Message Oriented Middleware mit einem asynchronen Mechanismus. Diese drei Typen von Middleware sollen im Folgenden näher beschrieben werden.
2.2 Remote Procedure Call
Der Remote Procedure Call (RPC) ermöglicht die Kommunikation zwischen Applikationen, die auf heterogenen Plattformen laufen. RPC basiert auf prozeduralen Konzepten
und unterstützt entfernte Funktionsaufrufe. RPC blendet die Details der Kommunikation, die Low-Level Netzwerkkommunikation, vor der Applikation und dem Programmierer aus. Dieser braucht sich um die Details nicht zu kümmern. Zentrales Anliegen
des RPC ist es, einem lokalen Programm eine entfernte Funktion nutzbar zu machen.
Für das lokale Programm ist der entfernte Funktionsaufruf genauso wie ein lokaler Aufruf [CDK01, S. 215]. Ein RPC ist für das lokale Programm also transparent. Diese Art
der Transparenz erfordert, dass die aufrufende Applikation, wie bei einem lokalen Aufruf, auf die Antwort wartet und nicht weiterarbeitet; sie blockiert. Dieser Kommunikationsmechanismus, bei der ein Prozess blockiert während seine Anfrage bearbeitet wird,
heißt synchrone Kommunikation. Ausführlichere Informationen über RPC können beispielsweise in [CDK01] nachgelesen werden.
2.3 Object Oriented Middleware
Object Oriented Middelware (OOM) unterstützt die Kommunikation zwischen verteilten Objekten und Komponenten [JBLN01, S. 31f.]. Realisiert wird OOM meistens mit
Hilfe von Object Request Broker (ORB). Sie ermöglichen lokalen Objekten oder Komponenten die Methoden entfernter Objekte oder Komponenten mittels Schnittstellen zu
benutzen. Im Prinzip ist OOM eine weitere Schicht über RPC. Deswegen arbeitet auch
OOM mit dem synchronen Kommunikationsmechanismus und blendet Details der
Kommunikation aus. Um hinsichtlich der Programmiersprachen und der Plattformen
Transparenz zu ermöglichen, sind Standards für die Schnittstellen erforderlich, an welche sich die Hersteller von ORB halten können.
5
Kapitel 2: Message Oriented Middleware
Die drei wichtigsten Standards für ORB sind CORBA von OMG, JAVA RMI und RMIIIOP von SUN sowie COM/DCOM/COM+ von Microsoft. Viele ORB Produkte sind
mit den CORBA ORB Spezifikationen und den verschiedenen RMI und RMI-IIOP
Implementierungen kompatibel. Insbesondere die Unterstützung von RMI-IIOP ist
wichtig, da es das gleiche Kommunikationsprotokoll wie CORBA benutzt, IIOP (Internet Inter-ORB-Protocol), und dadurch RMI und CORBA zusammenarbeiten können.
Verteilte Objekte sind die Grundlage von Enterprise Java Beans (EJB) und dementsprechend ist die mittels RMI bzw. RMI-IIOP durchgeführte Kommunikation zentraler Bestandteil der gesamten J2EE Plattform. Der Microsoft Standard, welcher des Öfteren
den Namen gewechselt hat, unterscheidet sich in einigen Punkten deutlich von RMI und
CORBA. Trotzdem ist eine Verbindung zwischen diesen Technologien möglich. Da
eine detaillierte Auseinandersetzung mit den genannten ORB Standards nicht Gegenstand dieser Ausarbeitung ist, sei auf die weiterführende Literatur verwiesen: zum Thema CORBA [CDK01, Kap.17] und zum Thema RMI und RMI-IIOP siehe [MAY03,
Kap.4].
2.4 Message Oriented Middleware
Wie in den Abschnitten 2.2 und 2.3 gezeigt, sind RPC und OOM klassische Vertreter
auf synchroner Kommunikation basierender Middleware. Message Oriented Middleware (MOM) ermöglicht asynchrone Kommunikation mittels Nachrichten. Diese werden
nicht direkt von einer Sender-Applikation zur Empfänger-Applikation gesendet, sondern gelangen über einen Vermittler an ihr Ziel. Dieser Mittler ist die MOM und deren
technische Realisierung wird als Message-Server oder auch Message Broker bezeichnet
[Mo02, S. 10]. Durch die Verwendung von Nachrichten und einen Vermittler ist ein
hohes Maß an Interoperabilität zwischen sehr heterogenen Softwaresystemen möglich,
da diese keine Details übereinander kennen müssen [JBLN01, S.28]. Außerdem sind die
kommunizierenden Applikationen, wie in Abbildung 1 [JBLN01, S. 28] dargestellt,
entkoppelt. Die Sender-Applikation sendet die Nachricht an den Vermittler und arbeitet
sofort weiter, ohne dass sie, wie bei Verwendung von RPC oder OOM, blockiert. Der
Vermittler ist für die Weiterleitung der Nachricht an die Empfänger-Applikation verantwortlich. Ist diese temporär nicht verfügbar, dann verwahrt der Message-Server die
Nachricht solange, bis die Applikation empfangsbereit ist [JBLN01, S. 28].
6
Kapitel 2: Message Oriented Middleware
Abbildung 1: Prinzip von MOM
Auch in einer anderen Hinsicht sind die Applikationen entkoppelt. Da die Kommunikation über Nachrichten stattfindet, benötigen die Applikationen keine Informationen darüber, wer die Nachrichten wann und wie bearbeitet. Genauso wie bei RPC und OOM
reduziert MOM die Komplexität, da Details der Kommunikation, bezüglich des Transports und des Netzwerks, versteckt werden. Die Funktionalität von MOM wird über ein
Application Programming Interface (API) zugänglich.
2.5 MOM und Enterprise Application Integration
Um verschiedene Softwaresysteme eines Unternehmens miteinander zu verbinden, ist
Middleware, als „Motor von Enterprise Application Integration (EAI)“, notwendig
[Li99, S. 99]. Gerade MOM ist ein wichtiger Bestandteil von EAI, da sie einige wichtige Eigenschaften besitzt [Li99, S. 110]. Diese Eigenschaften resultieren zum einen aus
der Verwendung eines zentralen Vermittlers, dem Message-Server, und zum anderen
aus der Verwendung des asynchronen Kommunikationsmechanismus mittels Nachrichten.
Die Verwendung eines Message-Servers und die damit verbundene zentrale Architektur
ermöglicht eine einfache Umsetzung nicht nur der Point-to-Point, sondern auch der Many-to-Many Kommunikation. Letztere Art der Kommunikation ist im Rahmen der EAI
notwendig, da es innerhalb eines Unternehmens häufig erforderlich ist, dass viele Applikationen miteinander kommunizieren [Li99, S.113f.]. Die Applikationen treten jeweils nur direkt mit dem Message-Server in Kontakt. Dadurch ist die gesamte Architek7
Kapitel 2: Message Oriented Middleware
tur flexibel, denn Änderungen sind leicht durchzuführen. Außerdem brauchen Applikationen deswegen die Details der anderen Applikationen und Plattformen nicht zu kennen [JBLN01, S.28]. Zudem stellt ein Message-Server neben der reinen Nachrichtenübermittlung i.d.R noch weitere Dienste, wie Lastverteilung und Transaktionen, bereit.
Besonders die gesicherte Kommunikation mittels Transaktionen ist vor dem Hintergrund der EAI relevant [Li99, S.118f.]. Die Verwendung eines zentralen Servers kann
allerdings auch einen großen Nachteil haben, weil dann die gesamte Architektur von
diesem abhängig ist. Können die Applikationen nur mit dem Server eines Anbieters
kommunizieren, ist die Architektur sogar von dem Server eines bestimmten Anbieters
abhängig. Um diese Abhängigkeit zu vermeiden, hat die Firma SUN eine allgemeine
Schnittstelle bereitgestellt, mittels der die Message-Server aller Anbieter kontaktiert
werden können, den Java Message Service (JMS). Dieser wird in Kapitel 3 näher beschrieben. Durch den JMS entfällt zwar die Abhängigkeit von einem speziellen Anbieter, allerdings müssen die Applikationen in Java geschrieben sein.
Durch die Verwendung von Nachrichten ist die asynchrone Kommunikation zwischen
Applikationen möglich. Da die Applikationen dabei nicht blockieren, ist MOM grundsätzlich performanter als RPC oder OOM. Wie in diesem Kapitel deutlich wurde, hat
MOM viele Vorteile gegenüber der „klassischen“ Middleware RPC und OOM. MOM
ist aber vor allem eine Ergänzung von RPC und OOM, insbesondere im Rahmen der
EAI, und kein vollständiger Ersatz. In vielen Situationen findet die Kommunikation
weiterhin über die „klassische“ Middleware statt.
8
Kapitel 3: Java Message Service
3 Java Message Service
Innerhalb dieses Kapitels wird der Java Message Service der Firma SUN vorgestellt.
Zunächst wird im ersten Abschnitt erklärt was der Java Message Service ist. Die Abschnitte 3.2 bis 3.4 beschreiben die grundsätzliche Funktionsweise, sowie die notwendigen Bestandteile. Das letzte Kapitel erläutert weiterführende Konzepte, die insbesondere im Rahmen von EAI interessant sind.
3.1 Grundlagen
Java Message Service (JMS) ist ein Messaging Standard. Eine vollständige Darstellung
des Java Message Service ist in [JMS1.1] nachzulesen. JMS stellt eine Spezifikationen
dar, welche Schnittstellen und Semantik definiert. Diese ermöglichen es Java Applikationen Dienste von allen JMS kompatiblen Message-Servern zu nutzen. JMS besteht aus
zwei Teilen; einem Application Programming Interface (API), um Nachrichten zu
schreiben und zu verschicken, und ein Service Provider Interface (SPI), welches die
Seite des Servers spezifiziert [RAJ02, S.203]. Die Java Applikation kann mit einem
beliebigen Message-Server kommunizieren, wenn dieser JMS kompatibel ist, also das
JMS SPI umsetzt. Im Kontext von JMS werden diese Message-Server auch als JMS
Provider bezeichnet. Es ist wichtig zu beachten, dass SUN derzeit keine Kompatibilitätstests durchführt. Deswegen gibt es keinen Standard, um die auf Seiten der Anbieter
erklärte JMS Kompatibilität zu überprüfen [MC01, S.133]. Eine Applikation, welche
die JMS Spezifikation umsetzt, ist nicht mehr an den Message-Server eines bestimmten
Herstellers gekoppelt. Dieser Zusammenhand ist in Abbildung 2 verdeutlicht.
Abbildung 2: Java Message Service
9
Kapitel 3: Java Message Service
Fünf große JMS Provider sind WebSphere MQ von IBM, SonicMQ von Progress, FioranoMQ von Fiorano, Java Message Queue von Sun Microsystems und WebLogic Server von BEA. Diese sind in [MC01, Kap.9] näher beschrieben. Das Message Produkt
Message Queue der Firma Microsoft unterstützt JMS nicht.
JMS wurde entwickelt, um die Vorteile von asynchroner Kommunikation auch für Java
Applikationen zu nutzen. An der Entwicklung von JMS waren außer SUN weitere große
Unternehmen beteiligt. Das ist ein Grund, weshalb die JMS Spezifikation von vielen
Server Anbietern unterstützt wird. Ein weiterer Grund für die weit verbreitete Unterstützung ist, dass JMS nur die direkt mit der Kommunikation zusammenhängenden Aspekte festlegt. Beispielsweise werden keine Vorgaben bezüglich der Lastverteilung oder
von Sicherheitsaspekten gemacht [JMS1.1, S.16f.] Die Spezifikation ist dadurch leichtgewichtig und die Anbieter von JMS Providern können sich anhand zusätzlicher Merkmale untereinander differenzieren. Um JMS benutzen zu können, werden Nachrichten,
administrative Objekte und JMS Clients benötigt. Bevor diese näher Erläutert werden,
sollen die beiden in JMS spezifizierten Kommunikationsmodelle erklärt werden.
3.2 Kommunikationsmodelle
JMS unterstützt zwei Kommunikationsmodelle, Point-to-Point und Publish/Subscribe.
Die an der Kommunikation beteiligten Komponenten werden allgemein als Produzent,
Konsument und Destination bezeichnet. Der Produzent ist der Erzeuger der Nachricht,
der Konsument ist der Abnehmer. Eine Destination agiert als Vermittler der Nachrichten. Diese Komponenten werden in Abhängigkeit von dem zugrunde liegenden Kommunikationsmodell entweder als Sender, Receiver und Queue oder als Publisher, Abonnent und Topic bezeichnet.
3.2.1 Point-to-Point
Das Point-to-Point (P-t-P) Modell realisiert Kommunikation zwischen einem Sender
und einem Receiver mittels einer Queue (s. Abbildung 3).
Abbildung 3: Das Point-to-Point Kommunikationsmodell
10
Kapitel 3: Java Message Service
Dabei hat jede Nachricht genau einen Receiver. Der Kommunikationsaustausch findet
zwischen genau zwei Komponenten statt. Ein oder mehrere Sender schicken eine Nachricht an die Queue. Eine Queue kann mehrere Receiver haben an die sie Nachrichten
weiterleitet. Die Queue stellt sicher, dass jede Nachricht genau einmal versendet wird.
JMS unterstützt für die Weiterleitung von Nachrichten durch die Queue den Pull- und
den Push- Mechanismus. Beim Pull-Mechanismus ruft der Receiver Nachrichten aktiv
ab, indem er bei der Queue anfragt, ob Nachrichten für ihn vorhanden sind. Leitet die
Queue Nachrichten automatisch an den Receiver weiterleitet, ist der Push-Mechanismus
umgesetzt. Weitere Einstellungen hinsichtlich der Bearbeitung von Nachrichten durch
die Queue, beispielsweise die Lastverteilung, werden Herstellerspezifisch umgesetzt.
3.2.2 Publish/Subscribe
Das Publish/Subscribe (Pub/Sub) Kommunikationsmodell ermöglicht die Kommunikation zwischen einem Publisher und einem oder mehreren Abonnenten mittels eines Topics. Dieses Modell ist die Umsetzung der Many-to-Many Kommunikation. Der Nachrichtenaustausch ist nicht auf zwei beteiligte Komponenten beschränkt. Unter einem
Topic können ein oder mehrere Publisher Nachrichten veröffentlichten, also Nachrichten an das Topic senden. Diese Nachrichten eines Topics erhalten alle Abonnenten, die
bei dem Topic registriert sind. Deswegen kann eine Nachricht viele Konsumenten haben. Dieser Zusammenhang ist in Abbildung 4 dargestellt.
Abbildung 4: Das Publish/Subscribe Kommunikationsmodell
Publisher und Abonnenten können dynamisch während der Laufzeit hinzugefügt werden, dadurch lassen sich Systeme einfach verändern und vergrößern. Das Pub/Sub
Kommunikationsmodell in JMS unterstützt nur den Push-Mechanismus, also die automatische Weitergabe der Nachrichten durch das Topic an die Abonnenten.
11
Kapitel 3: Java Message Service
3.3 Nachrichten
Der Inhalt der Kommunikation zwischen Produzent und Konsument wird mittels Nachrichten weitergegeben. Nachrichten sind zentraler Bestandteil von jeder MOM. Ihre
Struktur wird im Folgenden erklärt. Wie in Abbildung 5 zu erkennen, besteht eine
Nachricht aus drei Teilen: Header, Property und Body.
Abbildung 5: Struktur einer Nachricht
Im Header sind Metadaten enthalten, welche die Nachricht beschreiben, bspw. das Ziel
der Nachricht und der Zeitpunkt, wann sie erhalten wurde. Mit dem Inhalt des Headers
lassen sich die Nachrichten vom JMS Provider an das gewünschte Ziel weiterleiten.
Die Properties ermöglichen es dem Entwickler neben den Standardinformationen des
Headers optional weitere zusätzliche Informationen, wie applikationsspezifische und
serverspezifische Eigenschaften, hinzuzufügen.
Der Body enthält die eigentlichen Daten, die transportiert werden sollen. Die Art des
Inhalts ist unterschiedlich und hängt vom Typ der Nachrichten ab. Die Typen von JMS
werden durch das javax.jms.Message Interface festgelegt und sind in Tabelle 1
aufgelistet.
Tabelle 1: JMS Nachrichten Typen
12
Kapitel 3: Java Message Service
3.4 Interfaces
Neben dem Message Interface stellt JMS noch weitere Interfaces bereit, die in jeder
JMS Applikation genutzt werden. Im Einzelnen sind dies die administrativen Objekte
Destination, ConnectionFactory, Connection und Session, sowie
MessageProducer und MessageConsumer. Der in Abbildung 6 [JMS1.1, S. 24]
dargestellte Zusammenhang zwischen den Interfaces ist für die beiden Kommunikationsmodelle P-t-P und Pub/Sub grundsätzlich gleich. Für jedes Modell gibt es jeweils
eigene Subinterfaces.
Connection
Factory
erzeugt
Connection
erzeugt
erzeugt
Message
Producer
sendet an
erzeugt
Session
erzeugt
Destination
Message
Consumer
erhält von
Destination
Message
Abbildung 6: Zusammenhang zwischen den Interfaces
Ohne auf Details der einzelnen Interfaces einzugehen, lassen sich anhand dieser Abbildung bereits die notwendigen Schritte beschreiben, die zur Nutzung des JMS durchzuführen sind. Die Interfaces werden weiter unten ausführlicher beschrieben. Voraussetzung zur Durchführung der Schritte sind eine bereits vorhandene ConnectionFactory und eine Destination. Diese Komponenten werden im JMS Provider konfiguriert und sind nicht Bestandteil der Applikation. Um sie nutzen zu können, ist ein
JNDI lookup notwendig. Zur Funktionsweise des JNDI siehe [MAY03, Kap.11]. Die
ConnectionFactory erzeugt ein Connection Objekt. Mit dem Connection
Objekt lässt sich eine Session erstellen. Das Session Objekt erzeugt einen Mes13
Kapitel 3: Java Message Service
sageProducer, wenn eine Nachricht versendet werden soll, bzw. einen MessageConsumer, wenn eine Nachricht empfangen werden soll. Im ersten Fall wird auch
Objekt vom Typ Message von der Session erstellt. Diese wird dann durch den
MessageProducer versendet. Im Anhang ist ein kompletter Beispielcode aufgeführt, an dem die Zusammenhänge verdeutlicht werden.
Eine Destination ist das Ziel einer Nachricht. Spezielle Destinations sind im Kontext von JMS die Queue oder das Topic, je nach dem zugrunde liegenden Kommunikationsmodell. Normalerweise werden diese im JMS Provider konfiguriert und können
nicht direkt in der Applikation instanziiert werden. Eine Ausnahme bilden temporaryQueue und temporaryTopic, die in Abschnitt 3.5.3 beschrieben werden. Das
Interface ist javax.jms.Destination. Die Subinterfaces sind Queue für die
P-t-P Kommunikation und Topic für das Pub/Sub Modell.
Objekte vom Typ Connection werden in JMS ausschließlich mittels ConnectionFactories erzeugt. ConnectionFactories sind nur für die Erstellung von Connections zuständig. Auch die ConnectionFactory muss, wie die Destination, über einen JNDI
lookup aufgerufen werden. Das Interface ist javax.jms.ConnectionFactory.
Für die Kommunikationsmodelle P-t-P bzw. Pub/Sub sind die Subinterfaces QueueConnectionFactory und TopicConnectionFactory vorhanden. Ab der JMS
Version 1.1 ist allerdings eine Unterscheidung nicht mehr notwendig [MAY03, S. 237];
es kann für beide Modelle das Interface ConnectionFactory benutzt werden. Nur
aus Gründen der Abwärtskompatibilität mit älteren Versionen, sind die Subinterfaces
noch vorhanden.
JMS Connections repräsentieren eine Verbindung zwischen einem Client und einem
JMS Provider, über welche Nachrichten gesendet werden [MC01, S. 142]. Connections steuern die Low-Level Kommunikation über das Netzwerk. Das Connection
Interface ist javax.jms.Connection. Entsprechend der ConnectionFactory
hat auch Connection Subinterfaces, QueueConnection und TopicConnection,
welche ebenfalls lediglich wegen der Abwärtskompatibilität vorhanden sind.
Ein Objekt vom Typ Session arbeitet wie eine Fabrik für Objekte des Typs Message, MessageProducer und MessageConsumer [MC01, S. 27]. Nachrichten werden nicht direkt über Connections versendet, sondern durch ein Session Objekt
erzeugt. Um ein Objekt vom Typ Session zu erstellen ist ein Connection Objekt
14
Kapitel 3: Java Message Service
notwendig. Da ein Session Objekt eine Connection nutzt, stellt sie die Verbindung
zwischen einem Client und dem JMS Provider her. Für die Kommunikation zwischen
zwei Clients sind folglich mindestens zwei Sessions, vom MessageProducer zur
Destination und von der Destination zum MessageConsumer, erforderlich.
Das Interface ist javax.jms.Session. Die Subinterfaces QueueSession und
TopicSession werden auch nur für ältere Versionen benötigt.
Nachdem die notwendigen administrativen Objekte (Destination, ConnectionFactory, Connection und Session) erzeugt sind, können Nachrichten versendet
und empfangen werden. Außer Nachrichten, deren Struktur in Abschnitt 3.3 beschrieben ist, erzeugt eine Session auch MessageProducer und MessageConsumer.
Um Nachrichten versenden zu können, ist ein Objekt vom Typ MessageProducer
notwendig. Das Interface für diesen ist javax.jms.Message-Producer und hat
zwei Subinterfaces: QueueSender und TopicPublisher. Zur Erzeugung eines
MessageProducers ist ein Session Objekt erforderlich.
Mit dem Interface javax.jms.Message-Consumer lässt sich ein Objekt vom Typ
MessageConsumer erzeugen. Auch dieses stellt zwei Subinterfaces bereit, QueueReceiver und TopicReceiver. Wie in Abschnitt 3.2.1 erwähnt, unterstützt JMS
zur Weiterleitung von Nachrichten durch den JMS Provider den Pull und den PushMechanismus. Diese Mechanismen werden durch den MessageConsumer entweder
mit der Methode receive() oder dem Interface MessageListener() umgesetzt
[Mo02, S.36].
Wird der Pull-Mechanismus realisiert, holt sich der Konsument die Nachrichten vom
JMS Provider ab. Dafür wendet der Client die receive() Methode an. Durch den
Aufruf der Methode liefert der Server die nächste Nachricht. Ist momentan keine Nachricht vorhanden, blockiert der Konsument so lange, bis eine neue kommt. Um diese
Blockade zu begrenzen, kann als Argument ein Zeitintervall in Millisekunden angegeben werden. Die Methode hat dann die Form receive(long timeout). Der Konsument blockiert nur in dem vorgegebenen Intervall. Durch Anwendung der Methode
receiveNoWait() wird die Blockierung des Konsumenten verhindert.
Alternativ kann der Push-Mechanismus realisiert werden. Der Konsument lässt sich
Nachrichten zustellen, sobald sie verfügbar sind. Dazu muss ein Objekt erzeugt werden,
welches das MessageListener()Interface implementiert. Dieses Interface enthält
15
Kapitel 3: Java Message Service
nur die Methode onMessage(). Die Methode definiert was gemacht werden soll,
wenn eine Nachricht eintrifft. Sie enthält ein Argument vom Typ Message. Ein MessageListener Objekt verhält sich wie ein asynchroner event handler für Nachrichten. Durch den Aufruf der Methode setMessageListener()wird ein MessageListener bei einem spezifischen QueueReceiver oder TopicSubscriber
registriert. Wird eine Nachricht überbracht, ruft der Client automatisch die onMessage() Methode auf. Wie in Kapitel 4 noch gezeigt wird, sind Message Driven Beans
eine spezielle Form des Typs MessageListener.
3.5 Erweiterte Konzepte
Nachdem die bisherigen Abschnitte die Grundlagen zur Nutzung des JMS gelegt haben,
soll nun auf einige erweiterte Konzepte eingegangen werden. Hierbei wurden Konzepte
ausgewählt, die Sicherheitsaspekte adressieren und dementsprechend insbesondere im
Rahmen der EAI relevant sind. Dazu zählen Aspekte der Zuverlässigkeit, Transaktionen
und der Request/Reply Mechanismus.
3.5.1 Zuverlässigkeit
Die Zuverlässigkeit der Nachrichtenübertragung kann auf den drei Ebenen Nachrichtenproduzent, JMS Provider und Nachrichtenkonsument beeinflusst werden. Auf Ebene
des Produzenten kann der Übertragungsmodus, auf Ebene des JMS Providers das Quittierungsverhalten und auf Ebene des Konsumenten der Subskriptionstyp festgelegt werden. Diese drei Möglichkeiten zur Beeinflussung der Zuverlässigkeit sind Gegenstand
dieses Abschnitts. Bei der Wahl des gewünschten Zuverlässigkeitsgrads ist zu berücksichtigen, dass höhere Zuverlässigkeit immer schlechtere Performanz nach sich zieht.
Auf Ebene des Nachrichtenproduzenten kann Übertragungsmodus festgelegt werden,
der sich auf die Art der Nachrichtenspeicherung durch den Server bezieht [MC01,
S.85]. In Abhängigkeit, ob eher Zuverlässigkeit oder Performanz gewünscht ist, unterstützt JMS die Übertragungsmodi „nicht-persistent“ oder „persistent“. Wenn die Performanz wichtiger und der Verlust einer Nachricht als nicht kritisch zu bewerten ist,
kann der Modus „nicht-persistent“ gewählt werden. Da die Nachricht vom Server nicht
auf einen stabilen Speicher abgelegt werden muss, entsteht weniger Overhead. Allerdings kann die Nachricht bei einem Serverabsturz verloren gehen. Ist die zuverlässige
Nachrichtenübermittlung unerlässlich, muss der Modus „persistent“ gewählt werden.
16
Kapitel 3: Java Message Service
Die Nachricht wird von dem JMS Provider so abgespeichert, dass sie auch bei einem
Serverabsturz nicht verloren geht. „Persistent“ ist der default Wert. Das von JMS bereitgestellte DeliveryMode Interface sieht folgendermaßen aus:
public interface DeliveryMode {
static final int NON_PERSISTENT = 1;
static final int PERSISTENT = 2;
}
Informationen über die Art des Übertragungsmodus sind im Header der Nachricht hinterlegt.
Ist eine Nachricht bei dem JMS Provider angekommen, dann obliegt es seiner Verantwortung die Nachricht an den oder die Konsumenten weiterzuleiten. Erst wenn die
Nachricht nachweislich das gewünschte Ziel erreicht hat, löscht der Server die Nachricht. Der Nachweis erfolgt in Form einer Rückmeldung bzw. Quittierung vom Konsument. Solange eine Nachricht nicht quittiert wurde, versucht der Server sie erneut zu
versenden, bis er die Rückmeldung erhält. Dieses Verhalten des Servers ist bei der Wahl
des Modus zu beachten. Im JMS sind die drei in Tabelle 2 beschriebenen Rückmeldungsmodi möglich.
Modus
Beschreibung
Session.AUTO_ACKNOWLEDGE
Session.CLIENT_ACKNOWLEDGE
Session.DUPS_OK_ACKNOWLEDGE
Sobald die Session des Konsumenten eine
Nachricht erhält, quittiert sie den Empfang
automatisch. Dieser Modus garantiert das
eine Nachricht once-and-only-once ein Ziel
erreicht und wird normalerweise
angewendet.
Nicht die Session, sondern der Client
quittiert den Empfang einer Nachricht. Er
braucht nicht sofort jede einzeln zu
quittieren, sondern kann dies für mehrere auf
einmal machen.
Bei diesem Modus erfolgt die Quittierung
mittels der Session nicht automatisch.,
sondern es bleibt der Session überlassen,
wann sie dies macht.
Tabelle 2: Die drei Rückmeldungsmodi
Der Modus wird bei der Erstellung einer Session als zweites Argument angegeben und
ist vom Typ int. Das Mapping zwischen den int Werten und den Modi ist Serverspezifisch. Im Beispiel sieht das folgendermaßen aus:
17
Kapitel 3: Java Message Service
session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Bei der Wahl des Rückmeldungsmodus ist zu beachten, dass jede Nachricht, die ein
JMS Provider an einen Konsument versendet, quittiert werden muss. Ist der Empfang
einer Nachricht noch nicht quittiert, verschickt der JMS Provider sie erneut. Die Modi
Session.CLIENT_ACKNOWLEDGE
und
Session.DUPS_OK_ACKNOWLEDGE
ermöglichen eine bessere Performanz, da mehrer Nachrichten zusammen quittiert werden können. Allerdings müssen die Konsumenten bei diesen Modi den wiederholten
Empfang der gleichen Nachricht verarbeiten können [Mo02, S.34].
Das JMS Publish/Subscribe Kommunikationsmodell unterstützt zwei mögliche Subskriptionstypen, nicht-dauerhaft und dauerhaft. Nicht-dauerhaft bedeutet, dass ein Client
eine Nachricht nur erhält, wenn der Abonnent zum Zeitpunkt der Veröffentlichung aktiv
ist. Ist er nicht aktiv, erhält der Client die Nachricht nicht. Abonnenten dieser Art werden mit der Methode Session.createSubsriber() erzeugt. Durch die Methode
Session.createDurableSubsriber()lässt sich ein dauerhafter Abonnent erzeugen, der alle unter einem Topic veröffentlichten Nachrichten bekommt, auch wenn
er nicht immer aktiv ist. Der JMS Provider stellt die Nachricht an den Abonnenten zu,
sobald dieser wieder welche empfangen kann. Dieser Mechanismus ist auch unter dem
Namen „store-and-forward“ bekannt [MAY03, S.236]. Da sichergestellt ist, dass der
Abonnent alle Nachrichten erhält, ist das Pub/Sub Modell durch diesen Mechanismus
genauso zuverlässig, wie das P-t-P Modell.
Zwischen den Ebenen bestehen Zusammenhänge, die bei der Implementierung berücksichtigt werden müssen. Wenn beispielsweise eine Nachricht an einen dauerhaften Abonnenten geschickt und der Modus „nicht-persistent“ benutzt wird, kann die Nachricht
verloren gehen. Das ist möglich, wenn der Abonnent nicht aktiv ist und der Server abstürzt. Deswegen sollte für Nachrichten die an dauerhafte Abonnenten gesendet werden
immer der Modus „persistent“ gewählt werden.
3.5.2 Transaktionen
Durch Verwendung von Transaktionen kann sichergestellt werden, dass zusammenhängende Nachrichten entweder alle zusammen oder gar nicht versendet werden [MC01,
18
Kapitel 3: Java Message Service
S.95ff.]. Das Transaktionskonzept bietet erweiterte, auf mehrere Nachrichten bezogene
Zuverlässigkeit. Das Transaktionsverhalten wird bei der Erzeugung einer Session festgelegt. Es ist vom Typ boolean. Sollen mehrere Nachrichten atomar versendet bzw.
empfangen werden, ist der Wert true als Argument einzutragen. Sind Transaktionen
nicht erwünscht, wird false als Argument angegeben. Eine Transaktion wird innerhalb einer Session ausgeführt. Da Produzent und Konsument unterschiedliche Sessions
benutzen, bezieht sich eine Transaktion entweder auf das Versenden oder den Empfang
von Nachrichten. Es ist möglich eine Nachricht, die über eine transaktionale Session
versendet wurde, innerhalb einer nicht-transaktionalen Session zu empfangen et vice
versa [DP02, S.265].
Ein Produzent benutzt eine Transaktion, um zuverlässig mehrere Nachrichten zusammen zu versenden. Die Transaktion startet automatisch, wenn eine Session mit Transaktionsverhalten erstellt wird. Nachrichten, die der Produzent innerhalb einer Transaktion
erzeugt, werden erst als ein Paket an die Queue oder das Topic gesendet, wenn der
Produzent session.commit()aufruft. Danach startet innerhalb der Session automatisch die nächste Transaktion. Da es keine Methode zum manuellen Aufruf einer Transaktion gibt, sind deswegen verschachtelte Transaktionen nicht möglich. Der Aufruf von
session.rollback() bewirkt, dass alle Nachrichten nach dem letzten Aufruf von
commit()verworfen werden. Die Nutzung von Transaktionen durch den Produzent
wird an einem Beispiel dargestellt:
session = connection.createSession(true,
Session.Auto_ACKNOWLEDGE);
MessageProducer producer = session.createProducer();
/** Sende einige Nachrichten durch den Produzenten */
if(erfolgreich)
session.commit();
else
session.rollback();
Auf Seite des Konsumenten läuft die Transaktion ähnlich ab. Durch den session.commit()Aufruf quittiert der Konsument die empfangenen Nachrichten. Erst
nach Aufruf dieser Methode löscht der JMS Provider die Nachricht. Wenn sessi19
Kapitel 3: Java Message Service
on.rollback() vom Konsument aufgerufen wird, versendet der JMS Provider alle
Nachrichten seit dem letzten session.commit() erneut. Da bei einer Transaktion
der Empfang der Nachrichten erst durch den Aufruf der commit() Methode quittiert
werden kann, sind die anderen Rückmeldungsmodi, die in Abschnitt 3.5.2 beschrieben
wurden, für Transaktionen nicht relevant.
3.5.3 Request Reply
Grundsätzlich entspringt die Idee der asynchronen Kommunikation aus der Entkopplung von dem Produzent und dem Konsumenten einer Nachricht. Nachdem der Produzent die Nachricht an den JMS Provider versendet hat, arbeitet er weiter, ohne auf ein
Ergebnis bzw. eine Antwort zu warten. Er hat auch keine Informationen darüber, wer
seine Nachricht wann bearbeitet. Der Konsument bekommt die Nachricht vom JMS
Provider und hat seinerseits keine Informationen über den Produzenten. Für manche
Prozesse benötigt der Produzent aber eine Antwort auf eine spezielle Nachricht, um
weiterarbeiten zu können. Der von JMS spezifizierte Request/Reply Mechanismus gewährleistet dieses Verhalten [DP02, S. 269ff.;Mo02, Kap.6]. Dieser Mechanismus ermöglicht synchrone Kommunikation. Von zentraler Bedeutung für die Umsetzung, ist
die Erzeugung einer temporären Destination, an die der Konsument die Antwort senden
kann. Temporärere Destinations gibt es in der Form TemporaryQueue und TemporarayTopic.
Durch
die
on.createTemporaryQueue
beiden
Methoden
und
QueueSessiTopicSessi-
on.createTemporaryTopic werden sie dynamisch erstellt. Sie existieren nur
solange, wie die Connection besteht, innerhalb der sie erzeugt wurden. Nur die Konsumenten, die von der gleichen Connection wie die temporäre Destination erzeugt
wurden, können die Antworten verarbeiten. Wenn eine temporäre Destination erzeugt
wurde und im Header Feld JMSReplyTo der Nachricht an den Konsumenten übergeben wird, kann dieser eine Antwort an die angegebene Destination zurücksenden.
20
Kapitel 4: Message Driven Beans
4 Message Driven Beans
Inhalt dieses Kapitels sind die Message Driven Beans, welche zunächst in Abschnitt 4.1
allgemein eingeordnet werden. Anschließend werden die wichtigsten Bestandteile anhand ihres Lebenszyklus beschrieben (4.2). Im letzten Abschnitt werden noch kurz Vorund Nachteile, die durch die Verwendung von Message Driven Beans entstehen, diskutiert.
4.1 Grundlagen
Ab der Version Enterprise Java Beans (EJB) 2.0 gibt es neben den Entity und Session
Beans noch zusätzlich Message Driven Beans (MDB). Diese wurden eingeführt, um
EJB Komponenten asynchrone Kommunikation zu ermöglichen. Entity und Session
Beans können zwar problemlos JMS Nachrichten erstellen und senden. Allerdings ist es
für sie laut EJB Spezifikation 2.1 nicht möglich ein MessageListener zu sein und
Nachrichten asynchron zu empfangen [EJB2.1, S.337]. Im JMS Kontext fungiert der
Container als Konsument von Nachrichten aus Topics oder Queues und kann alle zulässigen JMS Nachrichten verarbeiten. Aus Sicht des Clients sind die MDBs, wie in Abbildung 7 [EJB2.1, S. 335] zu sehen, hinter der Destination versteckt.
Container
MDB Pool
Client
Destination
MDB Instanzen
Abbildung 7: MDB Prinzip
21
Kapitel 4: Message Driven Beans
Der Container ist für das Management der MDB verantwortlich. Durch den Container
werden einzelne MDB erzeugt und gelöscht. Ein großer Vorteil von MDB ist, dass sie
eingehende Nachrichten parallel verarbeiten können [MC01, S. 129]. Denn innerhalb
eines Pools werden mehrere MDB Objekte verwaltet. Je nach der Menge eintreffender
Nachrichten, kann der Container dynamisch MDB Objekte zusätzlich erzeugen oder
überflüssige löschen.
Im Gegensatz zu den Entity und Session Beans können Clients MDB nicht direkt, sondern nur indirekt via Nachrichten ansprechen. Deswegen benötigen MDBs auch weder
ein remote noch ein home Interface.
Da MDB nur innerhalb eines Containers existieren, werden sie auch als abhängige Konsumenten bezeichnet. Im Gegensatz zu unabhängigen JMS Nachrichten Konsumenten,
die nicht von einem Container gesteuert werden.
4.2 Lebenszyklus
Ein MDB besteht aus einer Bean Klasse und einem XML Deployment Descriptor. Da
die Aufgabe der MDB nur im Empfangen von asynchronen Nachrichten besteht, sind
sie sehr leichtgewichtig. MDB besitzen nur zwei Zustände und die Bean Klasse hat nur
vier Methoden. In Abbildung 8 [EJB2.1, S. 343] ist der Lebenszyklus sowie die Methoden dargestellt. Die Methoden stellen jeweils einen Aufruf vom Container an das MDB
Objekt dar.
Existiert nicht
1: newInstance()
2:setMessageDrivenContext()
ejbRemove()
3:ejbCreate()
Existent
onMessage()
Abbildung 8: Lebenszyklus einer MDB
22
Kapitel 4: Message Driven Beans
Eine
MDB-Klasse
implementiert
die
beiden
Interfaces
ja-
vax.jms.MessageListener und javax.ejb.MessageDrivenBean mit den
Methoden onMessage() bzw. ejbRemove() und setMessageDrivenContext(MessageDrivenContext). Zusätzlich muss jede MDB-Klasse die argumentlose ejbCreate() Methode bereitstellen.
Die onMessage() Methode ist notwendig, um den Push-Mechanismus zu realisieren
und Nachrichten asynchron zu empfangen. Da ein MDB das gleiche MessageListener Interface implementiert wie ein unabhängiger JMS Konsument, ist auch die Funktionsweise identisch. Diese ist in Abschnitt 3.4 beschrieben. Um ein Bean Objekt zu
erstellen ruft der Container die ejbCreate() Methode auf. Gelöscht wird ein Bean
Objekt durch den Aufruf der Methode ejbRemove().
Über die Methode setMessageDrivenContext(MessageDrivenContext)
erhält das Bean Informationen über die Umgebung, in der es ausgeführt wird.
Weitere Einstellungen werden im Deployment Descriptor konfiguriert. In diesem werden die Connection und die Session Objekte festgelegt, sowie der Name der
Destination eingetragen. Auch die mit diesen Objekten assoziierte Einstellungen,
wie Transaktionsverhalten, Rückmeldungsmodus und Subskriptionstyp, sind im
Deployment Descriptor vorzunehmen. Details hierzu können in [RAJ02, S. 219ff. ;
MAY03, S.570ff.] nachgelesen werden. Im Anhang ist ein Beispiel zum Deployment
Descriptor aufgeführt.
4.3 Beurteilung
Die Vorteile bei der Nutzung von MDB gegenüber unabhängigen JMS Konsument resultieren aus der Verwendung des Containers. Erstens stellt dieser Transaktionsdienste
bereit, welche die Abwicklung von Transaktionen entweder auf Ebene der Beans (beanmanaged-transactions) oder vom Container (container-managed-transactions) ermöglicht. Zweitens kann die Anzahl der Bean Objekte einfach über die Größe des Pools
angepasst werden. Dadurch wird die Effizienz gesteigert und eine optimale Lösung der
Lastverteilung gewährleistet [RAJ02, S.224]. Drittens können im Container neben
MDB noch Entity und Session Beans vorhanden sein. Deswegen ist keine Netzwerkkommunikation zwischen Nachrichtenempfänger und dem Bean, welches die Geschäftslogik bereitstellt, erforderlich. Außer den drei aufgeführten Vorteilen ist es
23
Kapitel 4: Message Driven Beans
grundsätzlich einfacher MDB zu erstellen, da administrative Objekte, wie Connection und Session, vom Container bereitgestellt werden.
Auch Nachteile können aus der Verwendung eines Containers entstehen [MAY03,
S.575]. In der Regel stellt ein Container mehrere MDB Objekte zugleich bereit und ermöglicht dadurch die parallele Verarbeitung von eingehenden Nachrichten. Wenn die
Nachrichten in einer bestimmten Reihenfolge bearbeitet werden sollen, kann das zu
Problemen führen. Das die richtige Reihenfolge sichergestellt wird, ist bei der Implementierung gegebenenfalls zu beachteten.
24
Kapitel 5: Zusammenfassung
5 Zusammenfassung
Message Oriented Middleware stellt eine umfassende Möglichkeit dar, den Datenaustausch zwischen verschiedenen Softwaresystemen zu gewährleisten. Sie ist flexibel,
gegenüber anderen Middlewaretypen performanter und erlaubt auf elegante Weise die
Interoperabilität heterogener Systeme. Trotzdem kann auf RPC und OOM nicht gänzlich verzichtet werden. Der Java Message Service stellt eine wohldefinierte Spezifikation bereit, die von fast allen namhaften Anbietern von Message-Servern umgesetzt wird.
Allerdings müssen die Applikationen, die JMS Dienste nutzen sollen in Java geschrieben sein. In Zusammenhang mit den unternehmensweiten Lösungen rund um die J2EE
Plattform von SUN, unterstützen Message Driven Beans die Umsetzung asynchroner
Kommunikation. In Zukunft ist es vielleicht möglich den asynchronen Kommunikationsmechanismus auf RPC bzw. OOM auszuweiten, um diese performanter zu gestalten.
25
Anhang A: Titel von Anhang 1
A WM-Ticket-Beispiel
Als Beispiel wird eine P-t-P Kommunikation umgesetzt. Inhaltlicher Hintergrund soll
der Ticketverkauf für die Weltmeisterschaft 2006 in Deutschland sein. Dazu wird die
Klasse TicketService mit der Methode request() erstellt, welche einen speziellen Ticket Typ nachfragt. Ein Objekt der Klasse TicketService ist ein MessageProducer. Als Typen stehen normale Tickets zum normalen Preis, exklusive VIPTickets und günstige Studenten-Tickets zur Verfügung (Die Typen entsprechen nicht
den originalen Klassen 1-4 der FIFA). Die Methode benutzt eine QueueConnection,
die während der Initialisierung erstellt wird, um eine MapMessage an die FIFA zu
senden. Inhalt der Nachricht ist der Typ des Tickets, die Nummer des Spiels (1 = Eröffnungsspiel; 64 = Endspiel) und das Datum. Die Auslosung der Tickets ist nicht Bestandteil des Beispiels. Der TicketService ist ein Singleton, dass ist aber nicht
notwendig. Dadurch wird aber verhindert, dass mehr als ein Connection Objekt erstellt werden kann. Die dfb.TicketOrderQueue wird genauso wie die ConnectionFactory vorausgesetzt. Da die Initialisierung des InitialContext serverspezifisch ist, soll sie nicht näher erläutert werden. Für Details zum JMS Provider
SwiftMQ4.5.1 von IIT Software siehe [www.swiftmq.com]. Das Beispiel orientiert sich
an [MAY03, Kap. 9 und 17].
TicketService
TicketService.java
import java.util.*;
import java.text.DateFormat;
import javax.jms.*;
import javax.naming.*;
public class TicketService {
public static final String NORMAL = "normal";
public static final String VIP = "vip";
public static final String STUDENT = "student";
26
Anhang A: Titel von Anhang 1
private static TicketService singleton = null;
private Connection connection;
private Queue ticketOrderQ;
private TicketService() {
try {
/**Zuständige JMS Objekte initialisieren und den
JNDI InitialContext erhalten */
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.swiftmq.jndi.InitialContextFactoryImpl");
env.put(Context.PROVIDER_URL,
"smqp://localhost:4001/timeout=10000");
Context ctx = new InitialContext(env);
/**ConnectionFactory erhalten und eine Connection
erzeugen */
ConnectionFactory cf = (ConnectionFactory)ctx.lookup(
"QueueConnectionFactory");
connection = cf.createConnection();
/**Die Destination Queue erhalten */
ticketOrderQ =
(Queue)ctx.lookup("dfb.TicketOrderQueue");
}
catch(NamingException ne) {
ne.printStackTrace();
}
catch(JMSException je) {
je.printStackTrace();
}
}
public static TicketService getTicketService(){
if(singleton == null)
singleton = new TicketService();
return singleton;
}
27
Anhang A: Titel von Anhang 1
public void request(int spiel, Date date) {
request(NORMAL, spiel, date);
}
public void request(String type, int spiel, Date date)
{
MessageProducer qSender;
Session session;
try {
/** Eine Session erzeugen */
session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
/** Einen MessageProducer erzeugen */
qSender = session.createProducer(ticketOrderQ);
/** Die MapMessage erzeugen */
MapMessage msg = session.createMapMessage();
msg.setString("ticketType", type);
msg.setInt("spiel", spiel);
msg.setString("date",
DateFormat.getDateInstance().format(date));
/** DeliveryMode setzen */
msg.setJMSDeliveryMode(DeliveryMode.Persistent);
/** Versenden der Nachricht */
qSender.send(msg);
qSender.close();
session.close();
}
catch(JMSException e) {
e.printStackTrace();
}
}
28
Anhang A: Titel von Anhang 1
public void close() {
try {
connection.close();
singleton = null;
}
catch(JMSException e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
TicketService service = TicketService.getTicketService();
service.request(64, new Date());
service.close();
System.exit(0);
}
}
Fifa mittels eines unabhängigen MessageConsumer
Empfänger
der
Ticket
Anfragen
und
damit
der
Nachrichten
aus
der
dfb.TicketOrderQueue ist die Fédération Internationale de Football Association (FIFA).
Durch die Klasse Fifa lassen sich entsprechende MessageConsumer erzeugen.
Dieser realisiert den Push-Mechansimus und lässt sich deswegen als MessageListener registrieren.
Fifa.java
import javax.naming.*;
import javax.jms.*;
import java.util.*;
public class Fifa implements MessageListener {
private Fifa() {
try {
/** Die Initialisierung sowie das Erzeugen der Connection
29
Anhang A: Titel von Anhang 1
und der Session erfolgt genauso wie bei der Klasse
TicketService */
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.swiftmq.jndi.InitialContextFactoryImpl");
env.put(Context.PROVIDER_URL,
"smqp://localhost:4001/timeout=10000");
Context ctx = new InitialContext(env);
ConnectionFactory cf = (ConnectionFactory)ctx.lookup(
"QueueConnectionFactory");
Connection connection = cf.createConnection();
Queue ticketOrderQ = (Queue)ctx.lookup(
"dfb.TicketOrderQueue");
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
/** Statt eines MessageProducers wird ein MessageConsumer
erzeugt */
MessageConsumer mc = session.createConsumer(
ticketOrderQ);
/** Registrieren des MessageConsumer als
MessageListener */
mc.setMessageListener(this);
/** Um Nachrichten empfangen zu können muss die Methode
start() ausgeführt werden */
connection.start();
}
catch(Exception e) {
e.printStackTrace();
}
}
public void onMessage(Message msg) {
try {
/** Umsetzung einer simplen onMessage Methode, die
30
Anhang A: Titel von Anhang 1
den Inhalt der Nachricht ausdruckt */
MapMessage mmsg = (MapMessage)msg;
System.out.println("Ticket Anfrage für Spiel Nr. "+
mmsg.getString("spiel")+" am"
+mmsg.getString("date"));
}
catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
Fifa f = new Fifa();
}
}
Fifa mittels MDB
Alternativ zum unabhängigen Empfänger von JMS Nachrichten, wie er in der obigen
Klasse realisiert ist, lässt sich auch ein MDB erzeugen. An diesem Beispiel ist gut zu
erkennen, dass das MDB weniger Code benötigt, da die Initialisierung dem Container
obliegt und im Deployment Descriptor festgelegt ist.
Message Driven Bean Fifa
import javax.jms.*;
import javax.ejb.*;
/** MDB implementieren immer die beiden Interfaces */
public class Fifa implements MessageDrivenBean, MessageListener
{
MessageDrivenContetxt ctx;
/** Konstruktor */
public Fifa(){}
31
Anhang A: Titel von Anhang 1
/** Dieselbe Methode wie bei der unabhängigen Umsetzung */
public void onMessage(Message message) {
try {
MapMessage mmsg = (MapMessage)msg;
System.out.println("Ticket Anfrage für Spiel Nr. "+
mmsg.getString("spiel")+" am"
+mmsg.getString("date"));
}
catch(Exception e) {
e.printStackTrace();
}
}
public void ejbRemove()throws javax.ejb.EJBException {}
public void setMessageDrivenContext(
MessageDrivenContext ctx)throws javax.ejb.EJBException {
this.ctx = ctx;
}
public void ejbCreate() {}
}
Fifa Deployment Descriptor
Im Deployment Descriptor sind die Einstellungen hervorgehoben, die bei der unabhängigen Fifa Klasse im Code vorgenommen werden.
<ejb-jar>
<enterprise-beans>
<message-driven>
<ejb-name>Fifa</ejb-name>
<ejb-class>Fifa</ejb-class>
<transaction-type>Container</transaction-type>
32
Anhang A: Titel von Anhang 1
<transaction-scope>Local</transaction-scope>
<jms-acknowledge-mode>
auto-acknowledge
</jms-acknowledge-mode>
<message-driven-destination>
<jms-destination-type>
javax.jms.Topic
</jms-destination-type>
<jms-subscription-durability>
nondurable
</jms-subscription-durability>
</message-driven-destination>
</message-driven>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>Fifa</ejb-name>
<method-name>onMessage</method-name>
<method-params>
<method-param>
javax.jms.Message
</method-param>
</method-params>
</method>
<trans-attribute>NotSupported</trans-attribute>
</container-transaction>
</assembly-descriptor>
<ejb-jar>
33
Literaturverzeichnis
[CDK01] George Coulouris, Jean Dollimore, Tim Kindberg: Verteilte Systeme, Pearson, 2001.
[DP02]
Stefan Denninger, Ingo Peters: Enterprise Java Beans 2.0, 2.Aufl., AddisonWesley, 2002.
[EJB2.1]
SUN Microsystems: Enterprise JavaBeans Specification 2.1, 2003,
http://java.sun.com/products/ejb/docs.html
[JBLN01] Matjaz B. Juric, S. Jeelani Basha, Rick Leander, Ramesh Nagappan: Professional J2EE EAI, Wrox, 2001.
[JMS1.1] SUN Microsystems: Java Message Service Specification 1.1, 2002,
http://java.sun.com/products/jms/docs.html
[Ke02]
Wolfgang Keller, Enterprise Application Integration, Dpunkt, 2002.
[Li99]
David S. Linthicum: Enterprise Application Integration, Addison-Wesley,
1999.
[MAY03] James McGovern, Rahim Adatia, Fain Yakov, et al.: Java 2 enterprise Edition 1.4 Bible, Wiley, 2003.
[MC01]
Richard Monson-Haefel, David A. Chappell: Java Message Service,
O’Reilly, 2001.
[Mo02]
Tarak Modi: Practical Java Message Service, Manning, 2002.
[RAJ02]
Ed Roman, Scott Ambler, Tyler Jewell: Mastering Enterprise JavaBeans,
2nd.ed., Wiley, 2002.
Herunterladen