Messaging mit JBossMQ

Thomas Darimont

Erfahrenes Mitglied
JMS: Messaging mit JBossMQ

Hallo!

Hier mal ein paar Beispiele zum Einsatz von Messaging mit JMS und JBossMQ
mit möglichst wenig Worten. Dazu verwenden wir den JBoss 4.0.2, Java 5
und Eclipse 3.1 incl. JBoss IDE.

Zunächst etwas Theorie:
Messaging beschreibt das Versenden von "Nachrichten" zwischen unterschiedlichen Komponenten. Die technologie die Java für Messaging bietet heißt JMS. JMS steht für Java Message Service und ist bestandteil der J2EE (JEE) Spezifikation. Die aktuelle Version der JMS Spezifikation lautet 1.1 und findet sich unter: http://java.sun.com/products/jms/docs.html . Bei JMS erfolgt der Nachrichtenversand immer an so genannte Destinations. Destinations sind die "Zielorte" der JMS Nachrichten. bei Destinations gibt es grundsätzlich 2 verschiende Typen die je nach Messaging-Modi Anwendung finden. Diese sind Queue mit dem Messaging Modi Point-to-Point und Topic mit dem Messaging Modi Publish-Subscribe. Point-to-Point Verbindungen erlauben das Versenden von Nachrichten von einem Client an genau einen Empfänger. (Es können sehr wohl mehrere Clients Nachrichten in die Queue senden und auch mehrere Clients aus der Queue lesen, jedoch wird eine eingehende Nachricht immer nur genau von einem Client empfangen dieses Verhalten ist jedoch in der Spezifiaktion nicht festgelegt... ). Beim Publish-Subscribe Modell erfolgt der Nachrichtenversand an ein Topic.Auch hier können mehrere Clients Nachrichten an ein Topic senden. Im Gegensatz zum Point-to-Point Modus empfängt hier jeder an diesem speziellen Topic registrierte (subscribe) Client jede an dieses Topic gesendete Nachricht.

Zum Einstieg hier mal ein Beispiel für beide Szenarien:
Zunächst Konfigurieren wir uns eine eigene Queue und ein eigenes Topic
innerhalb des JBoss Applikationsservers. Dazu wechseln wir in das Verzeichnis unserer Serverkonfiguration (Z.Bsp.: %JBOSS_HOME%/server/default) und editieren dort die Datei jbossmq-destinations-service.xml im verzeichnis ./deploy/jms

Dort ergänzen wir (beispielsweise am Ende) die beiden Einträge:
Code:
                 	<mbean code="org.jboss.mq.server.jmx.Queue"
  		name="jboss.mq.destination:service=Queue,name=TutorialsQueue">
                  		<depends optional-attribute-name="DestinationManager">
                  			jboss.mq:service=DestinationManager
                  		</depends>
                  	</mbean>

und

Code:
                 	<mbean code="org.jboss.mq.server.jmx.Topic"
  		name="jboss.mq.destination:service=Topic,name=TutorialsTopic">
                  		<depends optional-attribute-name="DestinationManager">
                  			jboss.mq:service=DestinationManager
                  		</depends>
                  	</mbean>
Damit haben wir im JBoss die beiden Destinations TutorialsQueue und TutorialsTopic registriert. Diese sind innerhalb des JNDI über den Namen
queue/TutorialsQueue und topic/TutorialsTopic zu finden.
Weitere Informationen zur Konfiguration von JMS findet man in der JBoss Dokumentation: http://www.jboss.com/products/jbossas/docs
(AdminGuide / DevelopersGuide / Getting Started Guide)


Ob wir das vor dem Starten von JBOSS oder zur (POST_STARTUP) Zeit machen ist dem JBoss egal. JBoss bekommt auch änderungen zur Laufzeit mit.

Wir beginnen nun mit einem Beispiel in einem Point-to-Point-Szenario.
Wir senden von einem Client eine Nachricht zur tutorialsQueue und lesen von einem Anderen Client die Nachricht aus der Queue. Dabei warten wir einmal selbst auf die Queue und anschließend verwenden wir einen sogenannten MessageConsumer.

Wir versenden eine Nachricht zur Queue:
Code:
               package de.tutorials.jmstutorial.ptp;
                
                import javax.jms.Message;
                import javax.jms.Queue;
                import javax.jms.QueueConnection;
                import javax.jms.QueueConnectionFactory;
                import javax.jms.QueueSender;
                import javax.jms.QueueSession;
                import javax.jms.Session;
                import javax.naming.InitialContext;
                
                public class PointToPointQueueSenderExample {
                	/**
                	 * @param args
                	 */
                	public static void main(String[] args) throws Exception{
                		InitialContext ctx = new InitialContext();
                		
                		//Wir besorgen uns unsere Queue (Destination) aus dem JNDI
                		Queue queue = (Queue) ctx.lookup("queue/TutorialsQueue");
                
   		//Wir besorgen uns eine ConnectionFactory für den Verbindungsaufbau 
                		//zum JBossMQ Dienst aus dem JNDI.
                		QueueConnectionFactory qcf = (QueueConnectionFactory) ctx
    				.lookup("ConnectionFactory");
                		
                		QueueConnection qc = qcf.createQueueConnection();
                		qc.setClientID("JMS_Client_Sender");
  		QueueSession qsession = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
                		qc.start();
                		
                		QueueSender qsender = qsession.createSender(queue);
                		
                		//Wir versenden 10 Nachrichten in die Queue
                		for (int i = 0; i < 10; i++) {
 			String text = "Hello " + System.currentTimeMillis();
      			Message msg = qsession.createTextMessage(text);
                			qsender.send(msg);
                			System.out.println("Sending: " + text);
                		}
                		
                		String text = "EXIT " + System.currentTimeMillis();
                		Message msg = qsession.createTextMessage(text);
                		qsender.send(msg);
                		System.out.println("Sending: " + text);
                		
                		
                		//Wir räumen auf...
                		qc.stop();
                		qsender.close();
                		qsession.close();
                		qc.close();
                
                		ctx.close();
                	}
                }

Um zu sehen, ob tatsächlich Nachrichten in der Queue stehen gibt es prinzipiel mehrere Möglichkeiten. Hier werde ich näher auf zwei Möglichkeiten eingehen wobei beide über die JMX-Console abgewickelt werden. Die JMX-Console ist eine Web Anwendung mit der die im JBoss lebenden JMX-MBeans verwaltet werden können.
Die Zugriff zur JMX-Console gibt's in der Regel über den Webbrowser unter:
http://localhost:8080/jmx-console .Diese gibt es auch als "größeres" Applet jedoch beschränke ich mich hier nur auf die html Version. Unter der Domäne jboss innerhalb der JMX-Console findet sich der Eintrag: database=localDB,service=Hypersonic . Dieser Eintrag steht für die innerhalb des JBoss verwendete In-Memory Datenbank Hypersonic SQL. Klicken wir auf den Eintrag gelangen wir auf eine Seite in der wir
allerlei Enstellungen tätigen können... uns interessiert aber im Moment nur die Operation "void startDatabaseManager()". Dort klicken wir auf den InvokeButton und alsbald sehen wir, dass sich eine kleine Swing Anwendung aufpoppen. Hier haben wir nun eine Art Datenbank-Explorer für die Hypersonic SQL DB. Führen wir nun im Abfragefenster die Abfrage: select * from jms_messages; aus so sehen wir in dem Ergebnis Bereich eine ganze Reihe von JMS-Nachrichten.

Eine andere Möglichkeit wäre es über die JMS-Console unter der Domain: jboss.mq.destination zu schauen. Dort sind alle innerhalb des JBoss hinterlegten Destinations aufgezeigt. Klicken wir dort auf unsere name=TutorialsQueue,service=Queue können wir zum einen über das Attribut QueueDepth die Anzahl der aktuell innerhalb dieser Queue vorhandenen Nachrichten abfragen. Wollen wir uns die Nachrichten etwas genauer ansehen, dann müssen wir das über den invoke-Button der java.util.List listMessages() Operation tun.

Wir lesen die Nachrichten aus der Queue aus:
Code:
                     package de.tutorials.jmstutorial.ptp;
                     
                     import java.util.Date;
                     
                     import javax.jms.Message;
                     import javax.jms.Queue;
                     import javax.jms.QueueConnection;
                     import javax.jms.QueueConnectionFactory;
                     import javax.jms.QueueReceiver;
                     import javax.jms.QueueSender;
                     import javax.jms.QueueSession;
                     import javax.jms.Session;
                     import javax.jms.TextMessage;
                     import javax.naming.InitialContext;
                     
                     public class PointToPointQueueRequestor {
                     
                     	/**
                     	 * @param args
                     	 */
                     	public static void main(String[] args) throws Exception{
                     		InitialContext ctx = new InitialContext();
                     		
                     		//Wir besorgen uns unsere Queue (Destination) aus dem JNDI
                     		Queue queue = (Queue) ctx.lookup("queue/TutorialsQueue");
                     
        		//Wir besorgen uns eine ConnectionFactory für den Verbindungsaufbau 
                     		//zum JBossMQ Dienst aus dem JNDI.
                     		QueueConnectionFactory qcf = (QueueConnectionFactory) ctx
 				.lookup("ConnectionFactory");
                     		
                     		QueueConnection qc = qcf.createQueueConnection();
                     		qc.setClientID("JMS_Client_Requestor");
 		QueueSession qsession = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
                     		qc.start();
                     		
 		QueueReceiver queueReceiver = qsession.createReceiver(queue);
                     		
                     		//Wir lesen Nachrichten aus der Queue
                     		TextMessage msg = null;
                     		//Maximal 1s auf neue Nachrichten warten...
 		while((msg = (TextMessage)	queueReceiver.receive(1000L))!= null){
     			System.out.println("Received: " + msg.getText());
                     		}
                     		
                     		//Wir räumen auf...
                     		qc.stop();
                     		queueReceiver.close();
                     		qsession.close();
                     		qc.close();
                     
                     		ctx.close();
                     	}
                     }

Wir Verwenden zur Abwechslung mal einen MessageConsumer, der uns einen nützlichen Listener Mechanismus bereitstellt.
Code:
                package de.tutorials.jmstutorial.ptp;
                
                import javax.jms.JMSException;
                import javax.jms.Message;
                import javax.jms.MessageConsumer;
                import javax.jms.MessageListener;
                import javax.jms.Queue;
                import javax.jms.QueueConnection;
                import javax.jms.QueueConnectionFactory;
                import javax.jms.QueueReceiver;
                import javax.jms.QueueSession;
                import javax.jms.Session;
                import javax.jms.TextMessage;
                import javax.naming.InitialContext;
                
                public class PointToPointQueueMessageConsumerExample {
                
                	/**
                	 * @param args
                	 */
                	public static void main(String[] args) throws Exception {
                		InitialContext ctx = new InitialContext();
                
                		// Wir besorgen uns unsere Queue (Destination) aus dem JNDI
                		Queue queue = (Queue) ctx.lookup("queue/TutorialsQueue");
                
   		// Wir besorgen uns eine ConnectionFactory für den Verbindungsaufbau
                		// zum JBossMQ Dienst aus dem JNDI.
                		QueueConnectionFactory qcf = (QueueConnectionFactory) ctx
    				.lookup("ConnectionFactory");
                
                		QueueConnection qc = qcf.createQueueConnection();
                		qc.setClientID("JMS_Client_MessageConsumer");
                		QueueSession qsession = qc.createQueueSession(false,
  				Session.AUTO_ACKNOWLEDGE);
                		qc.start();
                
                		QueueReceiver queueReceiver = qsession.createReceiver(queue);
                		MessageConsumer consumer = qsession.createConsumer(queue);
                		final boolean[] shouldExit = new boolean[1];
                		
                		consumer.setMessageListener(new MessageListener() {
                			public void onMessage(Message msg) {
 				TextMessage txtMsg = (TextMessage) msg;
                				try {
 		 		String textContent = txtMsg.getText();
 					System.out
 		 		 	.println("consumer received: " + textContent);
       					
 		 		if(textContent.indexOf("EXIT") >= 0){
 		 			shouldExit[0] = true;
        					}
       					
  				} catch (JMSException e) {
 					e.printStackTrace();
                				}
                			}
                		});
                		
                		//Wir lassen den Cosumer ein "wenig" Zeit zum arbeiten...
                		new Thread(){
                			{
                				start();
                			}
                			public void run(){
                				while(true){
    					try {
         				  if(shouldExit[0]){
 		 		 	break;
 						}
 						sleep(100L);
 		 		} catch (InterruptedException e) {
           				  e.printStackTrace();
        					}
                				}
                			}
                		}.join();
                
                		// Wir räumen auf...
                		qc.stop();
                		queueReceiver.close();
                		qsession.close();
                		qc.close();
                
                		ctx.close();
                	}
                }

Das beispiel für den Publish-Subscribe Modus:
Hier der Subscriber ... (diesen starten wir in unserem Beispiel vor dem Publisher)
Code:
           package de.tutorials.jmstutorial.ps;
           
           import javax.jms.JMSException;
           import javax.jms.Session;
           import javax.jms.TextMessage;
           import javax.jms.Topic;
           import javax.jms.TopicConnection;
           import javax.jms.TopicConnectionFactory;
           import javax.jms.TopicSession;
           import javax.jms.TopicSubscriber;
           import javax.naming.InitialContext;
           
           public class TopicSubscriberExample {
           
           	/**
           	 * @param args
           	 */
           	public static void main(String[] args) throws Exception {
           		InitialContext ctx = new InitialContext();
           
           		// Wir besorgen uns unser Topic (Destination) aus dem JNDI
           		final Topic topic = (Topic) ctx.lookup("topic/TutorialsTopic");
           
           		// Wir besorgen uns eine ConnectionFactory für den
           		// Verbindungsaufbau
           		// zum JBossMQ Dienst aus dem JNDI.
           		TopicConnectionFactory tcf = (TopicConnectionFactory) ctx
   				.lookup("ConnectionFactory");
           
           		final TopicConnection tc = tcf.createTopicConnection();
           
           		tc.start();
           
           		Runnable messageSubscriberAction = new Runnable() {
           			public void run() {
           				try {
 		 		TopicSession session = tc.createTopicSession(false,
 		 		 	Session.AUTO_ACKNOWLEDGE);
           
 		 		TopicSubscriber subscriber = session
 		 		 	.createSubscriber(topic);
           
 		 		TextMessage message = (TextMessage) subscriber
 		 		 	.receive(10000L);
 			 System.out.println(Thread.currentThread().getName()
 		 		 	+ " received: " + message.getText());
           
 					tc.stop();
 					subscriber.close();
 					session.close();
    				} catch (JMSException e) {
 					e.printStackTrace();
           				}
           			}
           		};
           		
           		new Thread(messageSubscriberAction).start();
           		Thread t = new Thread(messageSubscriberAction);
           		t.start();
           		t.join();
           
           		tc.close();
           		ctx.close();
           	}
           }

Hier unser Publisher:
Code:
           package de.tutorials.jmstutorial.ps;
           
           import javax.jms.Session;
           import javax.jms.Topic;
           import javax.jms.TopicConnection;
           import javax.jms.TopicConnectionFactory;
           import javax.jms.TopicPublisher;
           import javax.jms.TopicSession;
           import javax.naming.InitialContext;
           
           public class TopicPublisherExample {
           
           	/**
           	 * @param args
           	 */
           	public static void main(String[] args) throws Exception {
           
           		InitialContext ctx = new InitialContext();
           
           		// Wir besorgen uns unsere Queue (Destination) aus dem JNDI
           		Topic topic = (Topic) ctx.lookup("topic/TutorialsTopic");
           
           		// Wir besorgen uns eine ConnectionFactory für den
           		// Verbindungsaufbau
           		// zum JBossMQ Dienst aus dem JNDI.
 		TopicConnectionFactory connectionFactory = (TopicConnectionFactory) ctx
   				.lookup("ConnectionFactory");
           		
 		TopicConnection connection = connectionFactory.createTopicConnection();
           		connection.setClientID("JMS_TOPIC_ExamplePublisher");
           		connection.start();
           		
 		TopicSession session = connection.createTopicSession(false,Session.AUTO_ACKNOWLEDGE);
           		
           		TopicPublisher publisher = session.createPublisher(topic);
           
           		publisher.send(session.createTextMessage("Hallo Welt!"));
           		connection.stop();
           		
           		publisher.close();
           		session.close();
           		connection.close();
           		ctx.close();
           	}
           }

Als Beispiel für ein Request Response Szenario mit einer Queue dient uns im Folgenden ein Dienst der einen Integer Wert verdoppeln kann. Dazu senden wir von einem Client aus die Berechnungsanfrage als ObjectMessage an die Queue. Der "DoublerService" nimmt diese ObjectMessage aus der Queue führt die überaus "komplexe" Berechnung aus und sendet das Berechnungsergebnis direkt über die temporäre Queue zum Anfragenden zurück.

unser RequestResponseExample:
Code:
      package de.tutorials.jmstutorial.ptp;
      
      import javax.jms.ObjectMessage;
      import javax.jms.Queue;
      import javax.jms.QueueConnection;
      import javax.jms.QueueConnectionFactory;
      import javax.jms.QueueReceiver;
      import javax.jms.QueueSender;
      import javax.jms.QueueSession;
      import javax.jms.Session;
      import javax.jms.TemporaryQueue;
      import javax.naming.InitialContext;
      
      public class RequestResponseExample {
      
      	/**
      	 * @param args
      	 */
      	public static void main(String[] args) throws Exception {
      		InitialContext ctx = new InitialContext();
      
      		// Wir besorgen uns unsere Queue (Destination) aus dem JNDI
      		Queue queue = (Queue) ctx.lookup("queue/TutorialsQueue");
      
      		// Wir besorgen uns eine ConnectionFactory für den Verbindungsaufbau
      		// zum JBossMQ Dienst aus dem JNDI.
      		QueueConnectionFactory connectionFactory = (QueueConnectionFactory) ctx
  				.lookup("ConnectionFactory");
      
      		QueueConnection connection = connectionFactory.createQueueConnection();
      		connection.setClientID("JMS_Client_Sender");
      		QueueSession session = connection.createQueueSession(false,
      				Session.AUTO_ACKNOWLEDGE);
      		connection.start();
      
      		QueueSender sender = session.createSender(queue);
      
      		ObjectMessage msg = session.createObjectMessage(Integer.valueOf(100));
      		
 		//wir bauen uns eine temporäre Queue als Rückkanal für unsere Antwort... 	
      		TemporaryQueue responseQueue = session.createTemporaryQueue();
      		msg.setJMSReplyTo(responseQueue);
      		System.out.println("Sending: " + msg.getObject());
      		sender.send(msg);
      		
      		QueueReceiver responseReceiver = session.createReceiver(responseQueue);
      		
      		System.out.println("Waiting for answer...");
      		ObjectMessage response = (ObjectMessage)responseReceiver.receive();
      		System.out.println(response.getObject());
      		
      		// Wir räumen auf...
      		connection.stop();
      		responseReceiver.close();
      		sender.close();
      		session.close();
      		connection.close();
      
      		ctx.close();
      	}
      }

Der passende DoublerService...
Code:
      package de.tutorials.jmstutorial.ptp;
      
      import javax.jms.ObjectMessage;
      import javax.jms.Queue;
      import javax.jms.QueueConnection;
      import javax.jms.QueueConnectionFactory;
      import javax.jms.QueueReceiver;
      import javax.jms.QueueSender;
      import javax.jms.QueueSession;
      import javax.jms.Session;
      import javax.naming.InitialContext;
      
      public class JMSDoublerService {
      
      	/**
      	 * @param args
      	 */
      	public static void main(String[] args) throws Exception {
      		InitialContext ctx = new InitialContext();
      
      		// Wir besorgen uns unsere Queue (Destination) aus dem JNDI
      		Queue queue = (Queue) ctx.lookup("queue/TutorialsQueue");
      
      		// Wir besorgen uns eine ConnectionFactory für den Verbindungsaufbau
      		// zum JBossMQ Dienst aus dem JNDI.
      		QueueConnectionFactory connectionFactory = (QueueConnectionFactory) ctx
  				.lookup("ConnectionFactory");
      
      		QueueConnection connection = connectionFactory.createQueueConnection();
      		connection.setClientID("JMSDoublerService");
      		QueueSession session = connection.createQueueSession(false,
      				Session.AUTO_ACKNOWLEDGE);
      		connection.start();
      
      		QueueReceiver requestReceiver = session.createReceiver(queue);
      		ObjectMessage msg = (ObjectMessage) requestReceiver.receive();
      
      		Integer value = (Integer) msg.getObject();
      
      		//Wir besorgen uns die temporäre Queue für unsere Rückantwort...
      		QueueSender sender = session.createSender((Queue) msg.getJMSReplyTo());
      		
      		//Wir führen die hochkomplexe Berechnung durch...
      		ObjectMessage response = session.createObjectMessage(Integer
 				.valueOf(value.intValue() * 2));
      
      		sender.send(response);
      		System.out.println("Sending: " + response.getObject());
      
      		// Wir räumen auf...
      		connection.stop();
      		requestReceiver.close();
      		sender.close();
      		session.close();
      		connection.close();
      
      		ctx.close();
      	}
      
      }

//Edit:
todo:
-asynchroner vs. synchroner Aufruf.
-MessageSelector
-MessageTypen (TextMessage, ObjectMessage, MapMessage etc...)
- JMS Unterstützung von anderen Frameworks (Spring (springframework.org) / Lingo (http://lingo.codehaus.org/) beschreiben...

Gruß Tom
 

Anhänge

Hallo!

MessageDrivenBeans sind EJB Komponenten mit denen asynchrone Nachrichtengetriggerte Ablauflogik abgebildet werden kann. Dieser EJB Typ kann nur indirekt von einem Client aus aufgerufen werden (durch das versenden einer Nachricht an eine entsprechende Queue oder ein entsprechendes Topic). MessageDrivenBeans werden in der Regel vom Container gepoolt. Das bedeutet, dass der Container mehrere Instanzen dieser MessageDrivenBean-Klasse vorhält um beim eintreffen von Nachrichten auf der zugeordneten Queue eine beliebige "unbeschäftigte" MessageDrivenBean Instanz aus dem Pool zu nehmen un diese mit der Abarbeitung der eingehenden Nachricht zu beauftragen.

Hier mal ein Beispiel für eine MessageDrivenBean:
Code:
 package de.tutorials.jms.mdb;
 
 import javax.ejb.CreateException;
 import javax.ejb.EJBException;
 import javax.ejb.MessageDrivenBean;
 import javax.ejb.MessageDrivenContext;
 import javax.jms.JMSException;
 import javax.jms.Message;
 import javax.jms.MessageListener;
 import javax.jms.TextMessage;
 
 /**
  * @author Tom
  *
  * Die Eigenschaften für den Deployment Descriptor der EJB Anwendung definieren wir
  * über XDoclet Kommentare...
  * @ejb.bean acknowledge-mode="Auto-acknowledge"
  *		   description="An Message Driven Bean example"
  *		   display-name="An Message Driven Bean example"
  *		   name="ExampleMessageDriven" destination-type = "javax.jms.Queue" 
  * 
  * Hiermit verknüpfen wir unser MessageDrivenBean mit der TutorialsQueue.
  * Wann immer eine Nachricht an diese Queue gesendet wird, nimmt sich ein
  * unbeschäftigtes MDB die Nachricht aus der Queue heraus und beginnt mit der
  * Verarbeitung.
  * @jboss.destination-jndi-name name = "queue/TutorialsQueue"
  */
 public class ExampleMessageDrivenBean implements MessageDrivenBean, MessageListener{
 
 	public void ejbCreate(){ }
 	
 	public void setMessageDrivenContext(MessageDrivenContext arg0) throws EJBException { }
 
 	public void ejbRemove() throws EJBException {}
 
 	public void onMessage(Message msg) {
 		TextMessage textMessage = (TextMessage)msg;
 		try {
 			System.out.println("MDB received: " + textMessage.getText());
 		} catch (JMSException e) {
 			e.printStackTrace();
 		}		
 	}
 }

Im Anhang finden sich die Dateien als Eclipse Projekt.

Gruß Tom
 

Anhänge

Topics zur Laufzeit aus Programm anlegen oder löschen

Hi Tom,

ich verstehe das Nachrichtenkonzept noch nicht ganz und hoffe das Du mir Nachhilfe geben kannst.
Ich möchte eine Applikation schreiben die dazu dienen soll Nachrichten im Team auszutauschen.
Dazu soll auch gehören, das neue Nachrichtenkanäle angelegt werden. Die sollen so lange gültigkeit haben, bis sie wieder jemand löscht.

Das Konzept von JBoss scheint so ausgelegt zu sein, dass nur von einem Administrator, der Zugriff auf das Dateisystem des Servers hat, neue Kanäle angelegt werden können.

Um meine Aufgabe zu lösen, müßte ich ein Bean schreiben , das hier ..\server\default\deploy\jms Dateien anlegen und löschen darf.
Würde das gehen, oder gibt es eine ganz andere Lösung dafür?

Ich hoffe die Frage ist nicht allzu dämlich.
 
Kann es sein, dass du das fachliche Konzept der Nachricht mit dem technischen Konzept der Message verwechselst? Wenn ich "Nachrichten im Team austauschen" lese, klingt das eher wie das Konzept Mailingliste (auf ein Topic subscriben und dann die Nachrichten erhalten). Sowas setzt man nicht zwingendermaßen mit ner MessageDriven Architektur um. Eigentlich reicht es, eine zentrale Komponente zu schreiben, die die Registrierungen der Benutzer kenn (welcher User ist an welchem Topic interessiert) und einkommende Nachrichten an die interessierten Nutzer verteilt. Ganz einfach mithilfe einer Datenbank. Der einzige Punkt, an dem eine Message Sinn machen würde ist um die wahrscheinlich etwas länger dauernde Verteilung der Nachricht vom Absenden zu trennen.

Messages sind eher technischer Hammer für Asynchronität im Serverumfeld, wo man nicht mal eben nach belieben nen Thread aufmachen kann.

Gruß
Ollie
 
Hi Ollie,

ein ApplicationServer scheint mir schon so eine zentrale Instanz zu sein, von der Du sprichst. Wenn ich den verwende muß ich mich auch nicht selber um Protokolle oder RMI kümmern.
Warum Datenbank? Ich will keine Daten abspeichern.
ApplicationServer bedeutet: "Wir wissen nicht wie Deine Applikation ausschaut, aber wir können Dir Dienste zur Verfügung stellen mit denen Du einfach eine schreiben kannst".

Ich schreibe gerade einen ServiceMBean der mir sagen soll welche Topics angelegt sind und der auch welche Anlegen und Löschen kann.
Das scheint ein weg zu sein der funktioniert.
 
Hallo,

ich denke auch, das JMS in diesem Szenario der Overkill wäre...
wenn du zu Laufzeit Gruppen definieren und wieder auflösen willst solltest du dir mal jxta ansehen. Das ist ein Peer To Peer Messaging Framework. Auch dort kannst du einen Rechner als "quasi" Server abrichten, der dann das Gruppenmanagement übernimmt.
https://jxta.dev.java.net/

Gruß Tom
 
Ok, danke.

Wen das so ist, dann hier die nächste Frage.
Ich möchte eine Client/Server-Applikation in Java bauen.
Die Clients werden mit EclipseRCP erstellt.
Es soll eine zentrale Datenbank dabei sein.
Der Großteil der Kommunikation wird ereignisorientiert sein, d.h. die Clients werden über Callbackfunktionen angestoßen.
Ein wesentlicher Bestandteil ist eine Ressourcenverwaltung. Wenn ein Benutzer etwas reserviert, dann sollen alle anderen Benutzer die diese Ansicht auch offen haben zeitnah davon informiert werden.

Zuerst wollte ich die Kommunikation mit RMI lösen, aber dabei hätte ich viele Dinge selber entwickelt die es schon woanders gibt, z.B. welcher Benutzer darf welche Objekte verwenden und welche Daten sehen und bearbeiten.

Ich muß dazu nicht JavaEE verwenden, ich möchte aber nur eine überschaubare Menge von unterschiedlichen Komponenten benutzen.

Mit welchem Framework würdet ihr das implementieren.
 
Ich hatte einfach das Gefühl, dass du mit einem technischen Konzept auf ein fachliches Problem schießt, dass nur vom Namen her ähnlich ist. So nach dem Motto: "Ich möchte Nachrichten zwischen Usern austauschen - da gibts doch was, das heißt Messaging". So las sich das für mich in deinem ersten Post. "Nachrichten" kann ja erstmal alles sein. Hier im Forum kann ich auch anderen Usern Nachrichten schicken, und ich kann auch Threads beobachten und werde benachrichtigt, wenn es da was neues gibt. Trotzdem läuft das sicher nicht auf Basis von JMS ;).

Auch deine restlichen Posts sind sehr technisch. Client/Server, EclipseRCP, ereignisorientierte Kommunikation. Und dann halt die Frage, die immer kommt: mit welchem Framework geht das?. ;) Deine Anmerkung zum AS spiegelte das auch recht gut wieder. Ich weiß was ein AS ist, was aber viel wichtiger ist, zu wissen, unter welchen Umständen ich überhaupt einen AS brauche - welche fachlichen Anforderungen es nötig machen, einen AS einzusetzen.

Ich geb halt ungern Tipps zum Thema Technologie, wenn ich nicht weiß, was die fachliche Anforderung dahinter ist. Und mir scheint, du hast die Technologie vor der Fachlichkeit beschlossen. Einfach weil soviel Technologiebuzzies im Raum rumfliegen, die allerdings auf eigentlich alles passen könnten nur scheinbar nicht auf dies Sachen, für die du Lösungen suchst ("welcher Benutzer darf welche Objekte verwenden" - sowas erschlägt ein technisches API wie RMI einfach nicht).

So, und jetzt noch was mehr on-topic ;):

Wenn ich jetzt mal die Glaskugel ganz milchig durchschau... Client / Server, Remoting, asynchronität - das klingt schon arg nach nem Einsatzgebiet von Spring... vielleicht können wir ja noch detailerter werden.

Gruß
ollie
 
Hallo,

Wenn ich jetzt mal die Glaskugel ganz milchig durchschau... Client / Server, Remoting, asynchronität - das klingt schon arg nach nem Einsatzgebiet von Spring... vielleicht können wir ja noch detailerter werden.

*scnr*
Klingt im Moment nicht irgendwie alles was mehr als 3 Klassen involviert nach Spring?...

Gruß Tom
 
Liebe Freunde, bitte verwirrt mich nicht.

Ich arbeite mich zwar gerade in EJB3.0 ein und kenne mich damit nicht allzu sehr aus, aber ich mache schon 20 Jahre Softwareentwicklung.
Das Lochkartenzeitalter ist gerade mal so an mir vorbei gegangen und alles andere habe ich aktiv mitgemacht. Was also Konzepte und Technologien in der IT-Welt angeht gibt es nur wenig was ich nicht kenne.

Ich bin ganz begeistert das ihr mir helft, nur was ihr mir sagt passt nicht zu dem was ich sonst gelesen habe.
Laut diversen Internetquellen, wie z.B. dieser hier: http://www.onjava.com/pub/a/onjava/2005/06/29/spring-ejb3.html, ist Spring und EJB3.0 ungefähr das Gleiche.

EJB3.0 ist allerdings ein Industriestandard der von vielen Firmen getragen wird und zu dem es mehrere Implementierungen gibt. Spring hingegen wird nur von einer Firma getragen.
Ich habe schon viel schlechte Erfahrungen mit Singlevendorlösungen gemacht und darum Spring nicht in die nähere Wahl gezogen.

Ich habe mich erst sechs Wochen eingearbeitet und ich kann noch auf ein anderes Framework umsteigen. Das heißt aber auch sechs Wochen Arbeit wegwerfen.

@MSProductions, bitte sag mir wieviel Entwicklungserfahrung Du mit Spring oder EJB3.0 hast, damit ich Deine Aussage besser einschätzen kann.

@Tom, ich bin auf Deinen Beitrag aufmerksam geworden, weil ich nach Beispielen für Beans in JBoss gesucht habe. Dein Beispiel hat mir sehr geholfen. Was ist aus Deiner Sicht der Vorteil von Spring gegenüber EJB3.0?

Ich kenne nur die EJB3.0 implementierung JBoss. Da habe ich den Eindruck das man mit sehr wenigen Zeilen Code sehr viel Funktionalität programmieren kann. Die Performance kann ich nicht abschätzen. Meine geplante Applikation ist allerdings recht Oberflächenlastig und da ist der Flaschenhals sowieso immer der Mensch.
 
Zurück