Java EE (Java Platform, Enterprise Edition) ist eine durch Schnittstellen definierte Architektur f�r Unternehmensanwendungen, bestehend aus verschiedenen Komponenten.
JMS (Java Message Service) stellt einen wichtigen Bestandteil von Java EE dar, um asynchrone Kommunikation (�ber einen Message Broker) zu erm�glichen, was auch unter dem Begriff MOM (Message Oriented Middleware) bekannt ist.
Die Vorteile von asynchroner Kommunikation per JMS sind:
+ Zeitliche Entkopplung zwischen Beauftragung und Bearbeitung
+ Lose Kopplung erleichtert Austausch einzelner Systeme
+ Flexibel konfigurierbare Kommunikation und Diensteverteilung
+ Plattform- und programmiersprachenunabh�ngige Kommunikation
+ Anbindung an Fremdsysteme, z.B. Hosts
+ Batchbetrieb ist m�glich
+ Verteilte
Anwendungen
+ Verteilte Transaktionen
+ Standardisierung, Wartungsfreundlichkeit
+ Definierte Sicherheitsmechanismen
+ Hohe Ausfallsicherheit erreichbar
+ Hohe Skalierbarkeit
Inhalt
- Wichtige Klassen und Methoden
- �berblick, Nachrichtenkan�le, Transaktion/Best�tigung, Nachrichtenempf�nger,
Nachrichtensender
- �berblick, Nachrichtenkan�le, Transaktion/Best�tigung, Nachrichtenempf�nger,
Nachrichtensender
- Vorbereitungen f�r die Beispiele
- Namen im JNDI-Context
- Queue (Point-to-Point)
- QueueSender, Queue-receive, Queue-Listener
- QueueSender, Queue-receive, Queue-Listener
- Topic (Publish-and-Subscribe)
- TopicPublisher, Topic-receive, Topic-Listener (mit
Filter)
- TopicPublisher, Topic-receive, Topic-Listener (mit
Filter)
- QueueRequestor
- QueueRequestor, QueueRequestor-reply
- QueueRequestor, QueueRequestor-reply
- MDB (Message Driven Bean)
- Links auf weiterf�hrende Informationen
Wichtige Klassen und Methoden
�berblickQueue (Point-to-Point, "PTP") | Topic (Publish-and-Subscribe, "pub-sub") | |
InitialContext | InitialContext | InitialContext |
ConnectionFactory | QueueConnectionFactory | TopicConnectionFactory |
Connection | QueueConnection | TopicConnection |
Session | QueueSession | TopicSession |
Destination | Queue | Topic |
MessageConsumer | QueueReceiver | TopicSubscriber |
MessageProducer | QueueSender | TopicPublisher |
Requestor | QueueRequestor | TopicRequestor |
Message | Message | Message |
MessageListener . onMessage( Message ) Anders als bei 'receive()' braucht ein Listener nicht auf Messages zu warten, sondern empf�ngt sie asynchron, indem er sich �ber 'setMessageListener()' registriert, wodurch Messages an die 'onMessage(Message)'-Callback-Methode geschickt werden. Nachrichtensender QueueSender . send( Message )
TopicPublisher . publish( Message )
'send()' und 'publish()' versenden Nachrichten ohne eine Antwortnachricht zu erwarten. QueueRequestor . request( Message )
TopicRequestor . request( Message )
Ein Requestor verschickt eine Nachricht, �ffnet einen tempor�ren R�ckkanal, macht diesen �ber das JMSReplyTo-Feld zug�nglich, registriert sich als Empf�nger und wartet auf eine Antwortnachricht. Messages
Header | Enth�lt vom JMS gesetzte allgemeine Nachrichteninformationen wie: JMSCorrelationID, JMSDeliveryMode, JMSDestination, JMSExpiration, JMSMessageID, JMSPriority, JMSRedelivered, JMSReplyTo, JMSTimestamp, JMSType. |
Properties | Enth�lt von den Anwendungen gesetzte Nachrichtenzusatzinformationen als Attribute in Form von Key/Value-Paaren, deren Values von verschiedenen Java-Typen sein k�nnen. Die Attribute werden gesetzt und gelesen �ber 'get<Type>Property()' und 'set<Type>Property()'. Ein m�glicher Verwendungszweck dieser Attribute ist eine m�gliche Filterung der Nachrichten bei den Empf�ngern. |
Body | Enth�lt die eigentliche Nachricht, die einem der folgenden f�nf Message-Typen entspricht. |
TextMessage | �bermittelt einzelnen Text-String. |
MapMessage | �bermittelt (mehrere) Attribute als Key/Value-Paare. Dabei k�nnen die Values nicht nur Strings sein, sondern auch viele andere Java-Typen. |
ObjectMessage | �bermittelt ein Java-Object (welches 'Serializable' implementieren muss). |
StreamMessage | �bermittelt Streams �hnlich wie 'DataOutputStream'. Anders als 'BytesMessage' �bergibt 'StreamMessage' auch Datentypen. |
BytesMessage | �bermittelt Streams �hnlich wie 'DataOutputStream'. Anders als 'StreamMessage' �bergibt 'BytesMessage' nicht interpretierte Rohdaten. |
Vorbereitungen f�r die Beispiele
F�r die folgenden Beispiel wird ein Java EE Application Server f�r die JNDI- und JMS-Dienste ben�tigt. Es wird im Folgenden davon ausgegangen, dass JBoss installiert wird. Mit kleinen Modifikationen sind die Beispiele auch mit anderen Java EE Application Servern lauff�hig.
Installieren Sie JBoss wie beschrieben unter 'jee-ejb2.htm#InstallationJBoss'.
Wenn Sie nicht JBoss verwenden wollen, m�ssen Sie einen anderen Java EE Application Server f�r die JNDI- und JMS-Dienste installieren.
Legen Sie ein Projektverzeichnis an, z.B. 'D:\MeinWorkspace\MeinJmsProjekt' (im Folgenden '<MeinJmsProjekt>' genannt).
-
Legen Sie im Projektverzeichnis '<MeinJmsProjekt>' das Unterverzeichnis '<MeinJmsProjekt>\lib' an und kopieren Sie dort hinein die vom Client ben�tigten Libs. F�r JBosss ist dies die Datei 'jbossall-client.jar' aus dem JBoss-Verzeichnis 'C:\JBoss\client'.
-
Legen Sie im Projektverzeichnis '<MeinJmsProjekt>' das Unterverzeichnis '<MeinJmsProjekt>\conf' und darin die folgende Datei 'jndi.properties' an (wird von 'InitialContext()' ben�tigt):
java.naming.provider.url=jnp://localhost:1099 java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory jnp.socket.Factory=org.jnp.interfaces.TimedSocketFactoryWenn Sie nicht JBoss verwenden oder wenn JBoss auf einem anderen Rechner installiert ist, m�ssen Sie die Datei anpassen, wie zum Beispiel beschrieben unter: jee-jndi.htm#jndi.properties.
-
JMS-Queues und -Topics m�ssen beim Java EE Application Server bzw. JMS-Provider angemeldet werden. F�r JBoss muss hierf�r eine '*-service.xml'-Datei in das JBoss-Deploy-Verzeichnis kopiert werden.
Legen Sie im Unterverzeichnis '<MeinJmsProjekt>\conf' die folgende Datei 'wetter-service.xml' an:
<?xml version="1.0" encoding="UTF-8"?> <!-- Destination without a configured SecurityManager or without a SecurityConf will default to role guest with read=true, write=true, create=false. --> <server> <mbean code="org.jboss.mq.server.jmx.Topic" name="jboss.mq.destination:service=Topic,name=WetterTopic"> <depends optional-attribute-name="DestinationManager"> jboss.mq:service=DestinationManager </depends> <depends optional-attribute-name="SecurityManager"> jboss.mq:service=SecurityManager </depends> </mbean> </server>Kopieren Sie diese Datei in das JBoss-Deploy-Verzeichnis:
copy D:\MeinWorkspace\MeinJmsProjekt\conf\wetter-service.xml C:\JBoss\server\default\deploy
Bei anderen Java EE Application Servern m�ssen entweder �hnliche Dateien erstellt werden oder JMS wird �ber die Server-Konfiguration (z.B. Web-Konsole) eingerichtet.
Namen im JNDI-Context anzeigen
JNDI (Java Naming and Directory Interface) bietet einen Namens- und Verzeichnisdienst, �ber den Objekte und Dienste gefunden und verf�gbar gemacht werden.
Besonders zu Beginn kann es sehr hilfreich sein, die genauen Namen aller JNDI-Eintr�ge anzeigen zu lassen, da sie bei den verschiedenen Java EE Application Servern unterschiedlich vergeben werden k�nnen.
F�hren Sie hierf�r das Testprogramm unter jee-jndi.htm#Auslesen-Namen-im-JNDI aus.
Queue (Point-to-Point)
-
QueueSender
Vergegenw�rtigen Sie sich den Unterschied zwischen 'Queue' und 'Topic'.
Der folgende QueueSender sendet zehn Nachrichten an ein Queue.
Speichern Sie im Verzeichnis '<MeinJmsProjekt>\src\meinjmspackage' die folgende Datei 'MyQueueSender.java':
package meinjmspackage; import javax.jms.*; import javax.naming.*; public class MyQueueSender { public static void main( String[] args ) throws NamingException, JMSException { final String MEINE_QUEUE = "queue/testQueue"; Context ctx = null; QueueConnection connect = null; QueueSession session = null; Queue queue = null; QueueSender sender = null; try { ctx = new InitialContext(); QueueConnectionFactory fact = (QueueConnectionFactory) ctx.lookup( "ConnectionFactory" ); connect = fact.createQueueConnection(); session = connect.createQueueSession( false, Session.AUTO_ACKNOWLEDGE ); try { queue = (Queue) ctx.lookup( MEINE_QUEUE ); } catch( NameNotFoundException ex ) { queue = session.createQueue( MEINE_QUEUE ); ctx.bind( MEINE_QUEUE, queue ); } sender = session.createSender( queue ); connect.start(); for( int i=0; i<10; i++ ) { TextMessage msg = session.createTextMessage(); msg.setText( "Die " + (i+1) + ". Meldung des MyQueueSenders." ); sender.send( msg ); System.out.println( "Sending " + msg.getText() ); // System.out.println( "Sending " + msg.toString() ); } } finally { try { if( null != sender ) sender.close(); } catch( Exception ex ) {/*ok*/} try { if( null != session ) session.close(); } catch( Exception ex ) {/*ok*/} try { if( null != connect ) connect.close(); } catch( Exception ex ) {/*ok*/} try { if( null != ctx ) ctx.close(); } catch( Exception ex ) {/*ok*/} } } } -
Queue-receive
Der folgende QueueReceiver empf�ngt maximal 20 Sekunden lang bis zu 20 Nachrichten von einer Queue.
Anders als ein Listener wartet 'QueueReceiver.receive(1000)' synchron auf Messages (mit vorgegebenem Timeout).
Speichern Sie im Verzeichnis '<MeinJmsProjekt>\src\meinjmspackage' die folgende Datei 'MyQueueReceive.java':
-
Queue-Listener
Der folgende Queue-Listener empf�ngt 20 Sekunden lang Nachrichten von einer Queue.
Anders als bei 'receive()' braucht er als Listener nicht auf Messages zu warten, sondern empf�ngt sie asynchron, indem er sich �ber 'QueueReceiver.setMessageListener(new MyQueueListener())' registriert, wodurch Messages an die 'onMessage(Message message)'-Callback-Methode geschickt werden.
Speichern Sie im Verzeichnis '<MeinJmsProjekt>\src\meinjmspackage' die folgende Datei 'MyQueueListener.java':
package meinjmspackage; import javax.jms.*; import javax.naming.*; public class MyQueueListener implements MessageListener { public static void main( String[] args ) throws Exception { final String MEINE_QUEUE = "queue/testQueue"; Context ctx = null; QueueConnection connect = null; QueueSession session = null; Queue queue = null; QueueReceiver receiver = null; try { ctx = new InitialContext(); QueueConnectionFactory fact = (QueueConnectionFactory) ctx.lookup( "ConnectionFactory" ); connect = fact.createQueueConnection(); session = connect.createQueueSession( false, Session.AUTO_ACKNOWLEDGE ); try { queue = (Queue) ctx.lookup( MEINE_QUEUE ); } catch( NameNotFoundException ex ) { queue = session.createQueue( MEINE_QUEUE ); ctx.bind( MEINE_QUEUE, queue ); } receiver = session.createReceiver( queue ); receiver.setMessageListener( new MyQueueListener() ); connect.start(); Thread.sleep( 20000 ); } finally { try { if( null != receiver ) receiver.close(); } catch( Exception ex ) {/*ok*/} try { if( null != session ) session.close(); } catch( Exception ex ) {/*ok*/} try { if( null != connect ) connect.close(); } catch( Exception ex ) {/*ok*/} try { if( null != ctx ) ctx.close(); } catch( Exception ex ) {/*ok*/} } } public void onMessage( Message message ) { try { TextMessage msg = (TextMessage) message; System.out.println( msg.getText() ); message.acknowledge(); } catch( JMSException ex ) { System.out.println( ex.getMessage() ); } } } Achten Sie darauf, dass die 'Vorbereitungen' durchgef�hrt sind.
Pr�fen Sie mit der 'JNDI-Context-Testroutine', ob unter 'queue' der Eintrag 'queue/testQueue' aufgelistet ist.
Starten Sie JBoss und �ffnen Sie drei Kommandozeilenfenster.
Geben Sie im ersten Kommandozeilenfenster ein:
cd \MeinWorkspace\MeinJmsProjekt
set CLASSPATH=.;bin;conf;lib/jbossall-client.jar
javac -d bin src/meinjmspackage/*.java
java meinjmspackage.MyQueueListener
Geben Sie im zweiten Kommandozeilenfenster ein:
cd \MeinWorkspace\MeinJmsProjekt
set CLASSPATH=.;bin;conf;lib/jbossall-client.jar
java meinjmspackage.MyQueueReceive
Geben Sie im dritten Kommandozeilenfenster ein:
cd \MeinWorkspace\MeinJmsProjekt
set CLASSPATH=.;bin;conf;lib/jbossall-client.jar
java meinjmspackage.MyQueueSender
Starten Sie dabei das jeweils letzte 'java ...'-Kommando in der Reihenfolge der Kommandozeilenfenster, also 'MyQueueSender' zuletzt. Starten Sie diese drei Kommandos m�glichst kurz hintereinander.
In allen drei Kommandozeilenfenstern sollen Nachrichten erscheinen. Im 'MyQueueSender'-Kommandozeilenfenster erscheinen alle zehn Nachrichten. Die beiden anderen Kommandozeilenfenster teilen sich die Nachrichten, jede Nachricht erscheint also in genau einem Empf�nger-Kommandozeilenfenster.
Topic (Publish-and-Subscribe)
-
TopicPublisher
Vergegenw�rtigen Sie sich den Unterschied zwischen 'Queue' und 'Topic'.
Der folgende TopicPublisher sendet zehn Wetternachrichten an ein Topic.
Dabei gibt es eine Besonderheit: W�hrend 'Wetterlage', 'Windrichtung' und 'Temperatur' normal �ber eine 'MapMessage' im Body der 'Message' �bermittelt werden, wird die 'Stadt'-Information getrennt davon als 'Message'-Property gesetzt. Dies werden wir weiter unten im 'Topic-Listener'-Beispiel f�r einen Nachrichtenfilter ausnutzen.
Speichern Sie im Verzeichnis '<MeinJmsProjekt>\src\meinjmspackage' die folgende Datei 'MyTopicPublisher.java':
package meinjmspackage; import javax.jms.*; import javax.naming.*; public class MyTopicPublisher { public static void main( String[] args ) throws NamingException, JMSException { final String WETTER_TOPIC = "topic/WetterTopic"; final String[] STAEDTE = { "Aachen", "Berlin" }; final String[] WETTERLAGEN = { "Sonnig", "Wolkig", "Regen " }; final String[] WINDRICHTUNGEN = { "Nord", "West", "Sued", "Ost " }; Context ctx = null; TopicConnection connect = null; TopicSession session = null; Topic topic = null; TopicPublisher sender = null; try { ctx = new InitialContext(); TopicConnectionFactory fact = (TopicConnectionFactory) ctx.lookup( "ConnectionFactory" ); connect = fact.createTopicConnection(); session = connect.createTopicSession( false, Session.AUTO_ACKNOWLEDGE ); try { topic = (Topic) ctx.lookup( WETTER_TOPIC ); } catch( NameNotFoundException ex ) { topic = session.createTopic( WETTER_TOPIC ); ctx.bind( WETTER_TOPIC, topic ); } sender = session.createPublisher( topic ); connect.start(); for( int i=0; i<10; i++ ) { int rndm = (int) (Math.random() * 300); String stadt = STAEDTE[rndm % STAEDTE.length]; String wetterlage = WETTERLAGEN[rndm % WETTERLAGEN.length]; String windrichtung = WINDRICHTUNGEN[rndm % WINDRICHTUNGEN.length]; double temperatur = (double) (rndm - 50) / 10; MapMessage msg = session.createMapMessage(); msg.setStringProperty( "Stadt", stadt ); msg.setString( "Wetterlage", wetterlage ); msg.setString( "Windrichtung", windrichtung ); msg.setDouble( "Temperatur", temperatur ); sender.publish( msg ); System.out.println( "Sending Stadt=" + stadt + " Wl=" + wetterlage + " Wr=" + windrichtung + " T=" + temperatur + "C" ); // System.out.println( "Sending " + msg.toString() ); } } finally { try { if( null != sender ) sender.close(); } catch( Exception ex ) {/*ok*/} try { if( null != session ) session.close(); } catch( Exception ex ) {/*ok*/} try { if( null != connect ) connect.close(); } catch( Exception ex ) {/*ok*/} try { if( null != ctx ) ctx.close(); } catch( Exception ex ) {/*ok*/} } } } -
Topic-receive
Der folgende Topic-Empf�nger empf�ngt maximal 20 Sekunden lang bis zu 20 Wetternachrichten von einem Topic.
Anders als ein Listener wartet 'TopicSubscriber.receive(1000)' synchron auf Messages (mit vorgegebenem Timeout).
Speichern Sie im Verzeichnis '<MeinJmsProjekt>\src\meinjmspackage' die folgende Datei 'MyTopicReceive.java':
package meinjmspackage; import javax.jms.*; import javax.naming.*; public class MyTopicReceive { public static void main( String[] args ) throws Exception { final String WETTER_TOPIC = "topic/WetterTopic"; Context ctx = null; TopicConnection connect = null; TopicSession session = null; Topic topic = null; TopicSubscriber subscrib = null; try { ctx = new InitialContext(); TopicConnectionFactory fact = (TopicConnectionFactory) ctx.lookup( "ConnectionFactory" ); connect = fact.createTopicConnection(); session = connect.createTopicSession( false, Session.AUTO_ACKNOWLEDGE ); try { topic = (Topic) ctx.lookup( WETTER_TOPIC ); } catch( NameNotFoundException ex ) { topic = session.createTopic( WETTER_TOPIC ); ctx.bind( WETTER_TOPIC, topic ); } subscrib = session.createSubscriber( topic ); connect.start(); for( int i=0; i<20; i++ ) { MapMessage msg = (MapMessage)subscrib.receive( 1000 ); if( null != msg ) { System.out.println( "Receiving: Stadt=" + msg.getStringProperty( "Stadt" ) + " Wl=" + msg.getString( "Wetterlage" ) + " Wr=" + msg.getString( "Windrichtung" ) + " T=" + msg.getDouble( "Temperatur" ) + "C" ); msg.acknowledge(); } } } finally { try { if( null != subscrib ) subscrib.close(); } catch( Exception ex ) {/*ok*/} try { if( null != session ) session.close(); } catch( Exception ex ) {/*ok*/} try { if( null != connect ) connect.close(); } catch( Exception ex ) {/*ok*/} try { if( null != ctx ) ctx.close(); } catch( Exception ex ) {/*ok*/} } } } -
Topic-Listener (mit Filter)
Der folgende Topic-Listener empf�ngt 20 Sekunden lang Wetternachrichten von einem Topic.
Anders als bei 'receive()' braucht er als Listener nicht auf Messages zu warten, sondern empf�ngt sie asynchron, indem er sich �ber 'TopicSubscriber.setMessageListener(new MyTopicListener())' registriert, wodurch Messages an die 'onMessage(Message message)'-Callback-Methode geschickt werden.
Dabei gibt es eine Besonderheit: Oben im 'TopicPublisher'-Beispiel wurden 'Wetterlage', 'Windrichtung' und 'Temperatur' normal �ber eine 'MapMessage' im Body der 'Message' �bermittelt, w�hrend die 'Stadt'-Information getrennt davon als 'Message'-Property gesetzt wurde. Dies wird jetzt f�r einen Nachrichtenfilter ausgenutzt. Wird ein Stadtname als Kommandozeilen-Argument �bergeben, wird 'createSubscriber()' nicht mit
subscrib = session.createSubscriber( topic ); sondern stattdessen mit
subscrib = session.createSubscriber( topic, "Stadt='"+ args[0] + "'", true ); aufgerufen, und es werden nur Nachrichten f�r die gew�hlte Stadt ausfiltert und �bermittelt.Speichern Sie im Verzeichnis '<MeinJmsProjekt>\src\meinjmspackage' die folgende Datei 'MyTopicListener.java':
package meinjmspackage; import javax.jms.*; import javax.naming.*; public class MyTopicListener implements MessageListener { public static void main( String[] args ) throws Exception { final String WETTER_TOPIC = "topic/WetterTopic"; Context ctx = null; TopicConnection connect = null; TopicSession session = null; Topic topic = null; TopicSubscriber subscrib = null; try { ctx = new InitialContext(); TopicConnectionFactory fact = (TopicConnectionFactory) ctx.lookup( "ConnectionFactory" ); connect = fact.createTopicConnection(); session = connect.createTopicSession( false, Session.AUTO_ACKNOWLEDGE ); try { topic = (Topic) ctx.lookup( WETTER_TOPIC ); } catch( NameNotFoundException ex ) { topic = session.createTopic( WETTER_TOPIC ); ctx.bind( WETTER_TOPIC, topic ); } if( null != args && 0 < args.length ) subscrib = session.createSubscriber( topic, "Stadt='"+ args[0] + "'", true ); else subscrib = session.createSubscriber( topic ); subscrib.setMessageListener( new MyTopicListener() ); connect.start(); Thread.sleep( 20000 ); } finally { try { if( null != subscrib ) subscrib.close(); } catch( Exception ex ) {/*ok*/} try { if( null != session ) session.close(); } catch( Exception ex ) {/*ok*/} try { if( null != connect ) connect.close(); } catch( Exception ex ) {/*ok*/} try { if( null != ctx ) ctx.close(); } catch( Exception ex ) {/*ok*/} } } public void onMessage( Message message ) { try { MapMessage msg = (MapMessage)message; System.out.println( "Receiving: Stadt=" + msg.getStringProperty( "Stadt" ) + " Wl=" + msg.getString( "Wetterlage" ) + " Wr=" + msg.getString( "Windrichtung" ) + " T=" + msg.getDouble( "Temperatur" ) + "C" ); message.acknowledge(); } catch( JMSException ex ) { System.out.println( ex.getMessage() ); } } } Achten Sie darauf, dass die 'Vorbereitungen' durchgef�hrt sind.
Pr�fen Sie mit der 'JNDI-Context-Testroutine', ob unter 'topic' der Eintrag 'topic/WetterTopic' aufgelistet ist.
Starten Sie JBoss und �ffnen Sie drei Kommandozeilenfenster.
Geben Sie im ersten Kommandozeilenfenster ein:
cd \MeinWorkspace\MeinJmsProjekt
set CLASSPATH=.;bin;conf;lib/jbossall-client.jar
javac -d bin src/meinjmspackage/*.java
java meinjmspackage.MyTopicListener
Geben Sie im zweiten Kommandozeilenfenster ein:
cd \MeinWorkspace\MeinJmsProjekt
set CLASSPATH=.;bin;conf;lib/jbossall-client.jar
java meinjmspackage.MyTopicReceive
Geben Sie im dritten Kommandozeilenfenster ein:
cd \MeinWorkspace\MeinJmsProjekt
set CLASSPATH=.;bin;conf;lib/jbossall-client.jar
java meinjmspackage.MyTopicPublisher
Starten Sie dabei das jeweils letzte 'java ...'-Kommando in der Reihenfolge der Kommandozeilenfenster, also 'MyTopicPublisher' zuletzt. Starten Sie diese drei Kommandos m�glichst kurz hintereinander.
In allen drei Kommandozeilenfenstern erscheinen die gleichen Wetternachrichten (allerdings nicht immer in der gleichen Reihenfolge).
Geben Sie anschlie�end in einem Kommandozeilenfenster ein:
java meinjmspackage.MyTopicListener Aachen
Geben Sie sofort danach in einem anderen Kommandozeilenfenster ein:
java meinjmspackage.MyTopicPublisher
Jetzt werden nur noch Wetternachrichten f�r Aachen empfangen.
QueueRequestor
-
QueueRequestor
Der folgende QueueRequestor sendet zehn Nachrichten an ein Queue. Anders als die bisherigen Sender/Publisher erwartet er eine Antwortnachricht. F�r jede Nachricht �ffnet er einen tempor�ren R�ckkanal, macht diesen �ber das JMSReplyTo-Feld zug�nglich, registriert sich als Empf�nger und wartet auf eine Antwort.
Speichern Sie im Verzeichnis '<MeinJmsProjekt>\src\meinjmspackage' die folgende Datei 'MyQueueRequestor.java':
package meinjmspackage; import javax.jms.*; import javax.naming.*; public class MyQueueRequestor { public static void main( String[] args ) throws NamingException, JMSException { final String MEINE_QUEUE = "queue/testQueue"; Context ctx = null; QueueConnection connect = null; QueueSession session = null; Queue queue = null; QueueRequestor sender = null; try { ctx = new InitialContext(); QueueConnectionFactory fact = (QueueConnectionFactory) ctx.lookup( "ConnectionFactory" ); connect = fact.createQueueConnection(); session = connect.createQueueSession( false, Session.AUTO_ACKNOWLEDGE ); try { queue = (Queue) ctx.lookup( MEINE_QUEUE ); } catch( NameNotFoundException ex ) { queue = session.createQueue( MEINE_QUEUE ); ctx.bind( MEINE_QUEUE, queue ); } sender = new QueueRequestor( session, queue ); connect.start(); for( int i=0; i<10; i++ ) { TextMessage msg = session.createTextMessage(); msg.setText( "Die " + (i+1) + ". Anfrage des MyQueueRequestors." ); System.out.println( "Sending: " + msg.getText() ); TextMessage answer = (TextMessage) sender.request( msg ); System.out.println( "Reveived: " + answer.getText() ); } } finally { try { if( null != sender ) sender.close(); } catch( Exception ex ) {/*ok*/} try { if( null != session ) session.close(); } catch( Exception ex ) {/*ok*/} try { if( null != connect ) connect.close(); } catch( Exception ex ) {/*ok*/} try { if( null != ctx ) ctx.close(); } catch( Exception ex ) {/*ok*/} } } } -
QueueRequestor-reply
Der folgende Nachrichtenbeantworter empf�ngt 20 Sekunden lang Nachrichten von einer Queue und beantwortet sie.
Speichern Sie im Verzeichnis '<MeinJmsProjekt>\src\meinjmspackage' die folgende Datei 'MyQueueRequestorAnswer.java':
package meinjmspackage; import javax.jms.*; import javax.naming.*; public class MyQueueRequestorAnswer implements MessageListener { final String MEINE_QUEUE = "queue/testQueue"; Context ctx = null; QueueConnection connect = null; QueueSession session = null; Queue queue = null; QueueReceiver receiver = null; QueueSender replySnd = null; public static void main( String[] args ) throws Exception { new MyQueueRequestorAnswer(); } public MyQueueRequestorAnswer() throws Exception { try { ctx = new InitialContext(); QueueConnectionFactory fact = (QueueConnectionFactory) ctx.lookup( "ConnectionFactory" ); connect = fact.createQueueConnection(); session = connect.createQueueSession( false, Session.AUTO_ACKNOWLEDGE ); try { queue = (Queue) ctx.lookup( MEINE_QUEUE ); } catch( NameNotFoundException ex ) { queue = session.createQueue( MEINE_QUEUE ); ctx.bind( MEINE_QUEUE, queue ); } receiver = session.createReceiver( queue ); receiver.setMessageListener( this ); connect.start(); Thread.sleep( 20000 ); } finally { try { if( null != replySnd ) replySnd.close(); } catch( Exception ex ) {/*ok*/} try { if( null != receiver ) receiver.close(); } catch( Exception ex ) {/*ok*/} try { if( null != session ) session.close(); } catch( Exception ex ) {/*ok*/} try { if( null != connect ) connect.close(); } catch( Exception ex ) {/*ok*/} try { if( null != ctx ) ctx.close(); } catch( Exception ex ) {/*ok*/} } } public void onMessage( Message message ) { try { TextMessage msg = (TextMessage) message; System.out.println( "Reveived: " + msg.getText() ); TextMessage answer = session.createTextMessage(); answer.setText( "Echo '" + msg.getText() + "'." ); System.out.println( "Answering: " + answer.getText() ); Queue reply = (Queue)msg.getJMSReplyTo(); replySnd = session.createSender( reply ); replySnd.send( answer ); replySnd.close(); replySnd = null; message.acknowledge(); } catch( JMSException ex ) { System.out.println( ex.getMessage() ); } } } Achten Sie darauf, dass die 'Vorbereitungen' durchgef�hrt sind.
Pr�fen Sie mit der 'JNDI-Context-Testroutine', ob unter 'queue' der Eintrag 'queue/testQueue' aufgelistet ist.
Starten Sie JBoss und �ffnen Sie zwei Kommandozeilenfenster.
Geben Sie im ersten Kommandozeilenfenster ein:
cd \MeinWorkspace\MeinJmsProjekt
set CLASSPATH=.;bin;conf;lib/jbossall-client.jar
javac -d bin src/meinjmspackage/*.java
java meinjmspackage.MyQueueRequestorAnswer
Geben Sie im zweiten Kommandozeilenfenster ein:
cd \MeinWorkspace\MeinJmsProjekt
set CLASSPATH=.;bin;conf;lib/jbossall-client.jar
java meinjmspackage.MyQueueRequestor
Starten Sie dabei das jeweils letzte 'java ...'-Kommando in der Reihenfolge der Kommandozeilenfenster, also 'MyQueueRequestor' zuletzt. Starten Sie diese zwei Kommandos m�glichst kurz hintereinander.
In den beiden Kommandozeilenfenstern k�nnen Sie das Anfrage-/Antwort-Spiel beobachten.
MDB (Message Driven Bean)
Erl�uterungen und ein Programmierbeispiel zu MDB (Message Driven Bean) finden Sie in jee-ejb2.htm#Beispiel-MDB.
Links auf weiterf�hrende Informationen
- JMS: //www.oracle.com/technetwork/java/jms
- Java EE Tutorial: //docs.oracle.com/javaee/7/tutorial
- Java EE API: //docs.oracle.com/javaee/7/api
- Java SE API: //docs.oracle.com/javase/7/docs/api
- JBoss: //www.jboss.org/jbossas
- Bond/Law/Longshaw/Haywood/Roxburgh, J2EE in 21 Days, 2004: Rezension, Amazon.de 0672325586
- Stark, J2EE, 2004: Rezension, Amazon.de 3827321840
© 1998-2007 Torsten Horn, Aachen