Enterprise Application Integration Message oriented Middleware Enterprise Application Integration Björn Eilers Prozessmanagement Nachrichtenmanagement Physisches Netzwerk Enterprise Application Integration 2 Björn Eilers Adapter Adapter Adapter Adapter Adapter Adapter Middleware Metadatenbank für Zusatzdienste Einordnung in funktionale Bestandteile einer EAI Infrastruktur Kommunikation zwischen IS in Unternehmen eng Remote Procedure Calls Kopplung Interface-basierte Middleware CORBA EJB DCOM+ Web Services Nachrichten lose Enterprise Application Integration 3 Björn Eilers Schnittstellen vs. Nachrichten Schnittstellen Für Intraprogramm- bis Intraserver-Kommunikation Enge Kopplung der Systeme Ermöglicht Typprüfung während Kompilierung und Laufzeit I.d.R. schnelle Aufrufe Anpassung umfangreicher Systeme aufwändig bis wirtschaftlich unmöglich Schnittstellen alter und neuer Systeme oft inkompatibel Schnittstelle int addiere(int x, int y); Implementierung int addiere(int x, int y) { return x+y; } Enterprise Application Integration 4 Björn Eilers 17 25 Aufrufende Klasse 42 int result = schnittstelle.addiere(17, 25) Schnittstellen vs. Nachrichten Nachrichten Für Intraserver bis Intersystem-Kommunikation Lose Kopplung der Systeme bietet Zustellungsgarantie (Nachricht bei Systemausfall später zugestellt) keine Typprüfung langsam (Overhead durch Ver- und Entpacken der Nachricht) Einfache Anpassung auch bei größeren Systemen Für Kompatibilität mit Altsystemen: alte Nachrichteninhalte beibehalten, neue Ergänzen) Sender An: Empfänger Dienst: addiere x: 17 y: 25 Nachrichtenwarteschlange Enterprise Application Integration 5 Björn Eilers Empfänger Kommunikationsmodelle Synchrone Kommunikation Sender und Empfänger in Ablauf aneinander gekoppelt Sender blockiert, bis Empfänger antwortet Sender Empfänger Asynchrone Kommunikation Sender und Empfänger in Ablauf nicht gekoppelt Während Empfänger Antwort berechnet, kann Sender weiterarbeiten Sender Enterprise Application Integration 6 Björn Eilers Empfänger Kommunikationsvarianten Synchrone Einwegkommunikation z.B. entfernter Methodenaufruf ohne Rückgabe 1. Sender sendet Anfrage an Empfänger und blockiert 2. Empfänger nimmt Nachricht entgegen, sendet Bestätigung ("Acknowledgement") und verarbeitet dann Nachricht 3. Sender erhält Bestätigung und kann direkt weiterarbeiten Sender Empfänger Ack Enterprise Application Integration 7 Björn Eilers Kommunikationsvarianten Synchrones Polling 1. 2. 3. 4. 5. Sender fragt periodisch bei Empfänger an, ob Resultate vorliegen Antwort entweder als Nachricht oder in gemeinsamem Speicher Sender schickt Anfrage an Empfänger und arbeitet weiter Empfänger startet Verarbeitung Sender fragt regelmäßig nach Ergebnissen Falls keine vorhanden, wird weitergearbeitet und später erneut nachgefragt Ergebnis liegt vor: Ergebnis wird geliefert, Empfänger kann weiterarbeiten Sender arbeitet mit Ergebnis weiter Sender Enterprise Application Integration 8 Björn Eilers Empfänger Kommunikationsvarianten Asynchrones Broadcasting Sender sendet Nachricht an mehrere Empfänger gleichzeitig, arbeitet weiter Jeder Empfänger erhält Nachricht und kann reagieren Empfänger 1 Sender Empfänger 2 Empfänger 3 Enterprise Application Integration 9 Björn Eilers Kommunikationsvarianten Asynchrones Publish/Subscribe Ähnlich zum Broadcast, aber Empfänger müssen bei "Zusteller" Themen abonnieren Nur registrierte Empfänger erhalten Nachricht Empfänger 1 Sender A Zusteller A Abonniere Thema A Empfänger 2 Empfänger 3 Enterprise Application Integration 10 Björn Eilers Message oriented Middleware Middleware, die über die Weitergabe von Nachrichten kommuniziert Dienste zentriert auf Nachrichten Anlegen Weitergabe Auslieferung Speicherung (Persistierung) Transaktionssicherheit MoM als Vermittler zwischen Sender und Empfänger Message-Server / Message-Broker Enterprise Application Integration 11 Björn Eilers Message oriented Middleware Vorteile Asynchrone Kommunikation sehr allgemein, ermöglicht Emulation anderer Modelle Aufgrund allgemeinen Charakters hohes Maß an Interoperabilität zwischen heterogenen Systemen Für lose gekoppelte Systeme sehr gut geeignet; XML-Dokumente in Nachrichten einbetten Nachteile Fehlende Typsicherheit Overhead durch Ver-/Entpacken und Übermittlung der Nachrichten Enterprise Application Integration 12 Björn Eilers Message oriented Middleware Entweder Standalone… IBM MQSeries Sun ONE Middleware MS Message Queue Server ObjectWeb JORAM BEA MessageQ EldoS MsgConnect CSS NetZyme Enterprise TIBCO ActiveEnterprise …oder als Bestandteil anderer Middleware-Systeme z. B. Java 2 Enterprise Edition (JMS und Message-Driven Beans) Enterprise Application Integration 13 Björn Eilers Java Message Service Spezifikation, definiert Schnittstellen und Protokolle für Kommunikation durch Nachrichtenaustausch Kommunikationsvarianten asynchrones Senden (normale asynchrone Kommunikation) asynchrones Publish/Subscribe asynchrones Request/Reply synchrones Request/Reply (normale blockierende, synchrone Kommunikation) synchrone Einwegkommunikation Ermöglicht bei entsprechender Programmierung auch weitere Kommunikationsvarianten Enterprise Application Integration 14 Björn Eilers Java Message Service Zwei Arten von Nachrichtenkanälen Queues: Einfache Warteschlangen für n:1-Kommunikation Topics: Publish/Subscribe-Kanäle für n:m-Kommunikation Queues und Topics sind zueinander inkompatibel Sender 1 Queue Empfänger Sender 2 Sender 1 Empfänger 1 Topic Sender 2 Empfänger 2 Grundlegende Technologie für Message-Driven Beans Enterprise Application Integration 15 Björn Eilers Java Message Service Nachrichten Bestehen aus Header, Properties und Body Header enthält Meta-Angaben (Empfänger, Lebensdauer, ...) Properties enthalten zusätzliche, frei definierbare Angaben (primitive Datentypen und Strings) Body enthält den eigentlichen Inhalt Header Properties Nachrichtenarten (implementieren javax.jms.Message) TextMessage: Zum Übermitteln eines Strings MapMessage: Für Namen-Werte-Paare primitiver Datentypen ObjectMessage: Zum Übermitteln eines serialisierbaren Objektes BytesMessage: Liefert einen beschreibbaren Byte-Stream StreamMessage: Für einen Stream primitiver Datentypen SpyMessage (JBoss-spezifisch): Nachricht ohne Inhalt ("Ping") Enterprise Application Integration 16 Björn Eilers Body Java Message Service Für Versand und Empfang existiert Interface-Hierarchie javax.jms.ConnectionFactory: Baut Verbindungen zwischen JMS Client und JMS Provider auf; wird von J2EE bereitgestellt javax.jms.Connection: Kapselt Verbindungen javax.jms.Session: Sitzung, innerhalb der Nachrichten gesendet und empfangen werden können javax.jms.Destination: Ziel einer Nachricht (z.B. Queue oder Topic), muss im J2EE-Kontext bereitliegen javax.jms.MessageProducer/MessageConsumer: Sender/Empfänger einer Nachricht, kommunizieren mit Destination Jeweils mit Subklassen für Queues und Topics (QueueConnectionFactory, TopicConnectionFactory, etc.) Destinations können auch temporär sein Enterprise Application Integration 17 Björn Eilers Java Message Service ConnectionFactory erzeugt Connection erzeugt MessageProducer erzeugt Session erzeugt MessageConsumer erzeugt sendet an Nachricht Destination Enterprise Application Integration 18 Björn Eilers erhält von Java Message Service Grundsätzlicher Ablauf der Kommunikation 1. 2. 3. 4. 5. 6. 7. 8. ConnectionFactory im JNDI-Kontext auffinden und referenzieren Mithilfe der Factory Connection erzeugen Destination auffinden Session erzeugen Verbindung starten MessageProducer und/oder MessageConsumer erzeugen Nachrichten austauschen Verbindung schließen Enterprise Application Integration 19 Björn Eilers Java Message Service Implementierung: Grundlegendes Gerüst für Clients try { Properties p = System.getProperties(); p.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory"); p.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces"); p.setProperty("java.naming.provider.url", "localhost"); InitialContext ctx = new InitialContext(); // ... } catch (JMSException e) { e.printStackTrace(); } catch (NamingException e) { e.printStackTrace(); } Enterprise Application Integration 20 Björn Eilers Java Message Service Nachricht an Queue senden QueueConnectionFactory qcf = (QueueConnectionFactory) ctx .lookup("ConnectionFactory"); QueueConnection qc = qcf.createQueueConnection(); QueueSession qs = qc.createQueueSession(false, für TransaktionsSession.AUTO_ACKNOWLEDGE); unterstützung: true qc.start(); Queue queue = (Queue) ctx.lookup("queue/BeispielQueue"); QueueSender sender = qs.createSender(queue); MapMessage exampleMessage = qs.createMapMessage(); // ... sender.send(exampleMessage); qc.close(); Enterprise Application Integration 21 Björn Eilers Java Message Service Nachricht an Topic senden TopicConnectionFactory tcf = (TopicConnectionFactory) ctx .lookup("ConnectionFactory"); TopicConnection tc = tcf.createTopicConnection(); TopicSession ts = tc.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); tc.start(); Topic topic = (Topic) ctx.lookup("topic/BeispielTopic"); TopicPublisher publisher = ts.createPublisher(topic); MapMessage message = ts.createMapMessage(); // ... publisher.publish(message); tc.close(); Enterprise Application Integration 22 Björn Eilers Java Message Service Asynchrones Empfangen einer Nachricht: Implementieren des Interfaces javax.jms.MessageListener und der Methode public void onMessage Registrieren des MessageListeners an einem Receiver bzw. Subscriber public class ExampleListener implements javax.jms.MessageListener { public void onMessage(Message message) { // Verarbeitung: Gebe Empfangshinweis aus System.out.println("Nachricht mit ID "+ message.getJMSMessageID()+" empfangen."); } } Enterprise Application Integration 23 Björn Eilers Java Message Service Queue // Properties setzen ... // Verbindung zum Queue erzeugen InitialContext ctx = new InitialContext(); QueueConnectionFactory qcf = (QueueConnectionFactory) ctx .lookup("ConnectionFactory"); QueueConnection qc = qcf.createQueueConnection(); QueueSession qs = qc .createQueueSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue = (Queue) ctx.lookup(QUEUE_NAME); QueueReceiver receiver = qs.createReceiver(queue); receiver.setMessageListener(new ExampleListener()); qc.start(); // warten ... // wenn nicht mehr empfangen werden soll: Verbindung schließen qc.close(); Enterprise Application Integration 24 Björn Eilers Java Message Service Topic // Properties setzen ... // Verbindung zum Topic erzeugen InitialContext ctx = new InitialContext(); TopicConnectionFactory tcf = (TopicConnectionFactory) ctx .lookup("ConnectionFactory"); TopicConnection tc = tcf.createTopicConnection(); TopicSession ts = tc .createTopicSession(false, Session.AUTO_ACKNOWLEDGE); Topic topic = (Topic) ctx.lookup(TOPIC_NAME); TopicSubscriber subscriber = ts.createSubscriber(topic); subscriber.setMessageListener(new ExampleListener()); tc.start(); // warten ... // wenn nicht mehr empfangen werden soll: Verbindung schließen tc.close(); Enterprise Application Integration 25 Björn Eilers Java Message Service Synchrones Empfangen einer Nachricht Zwei Möglichkeiten: QueueRequestor bzw. TopicRequestor-Objekt (Vorteil: einfach implementiert, Nachteil: kein Timeout) QueueReceiver bzw. TopicSubscriber (Vorteil: flexibler, Nachteil: höherer Implementierungsaufwand) tc.start(); Topic topic = (Topic) ctx.lookup(TOPIC_NAME); TopicRequestor trq = new TopicRequestor(ts, topic); ObjectMessage exampleMessage = ts.createObjectMessage(); // ... Nachricht mit Inhalten füllen ... Message answer = trq.request(exampleMessage); // Antwort auswerten tc.close(); Enterprise Application Integration 26 Björn Eilers Java Message Service qc.start(); Queue queue = (Queue) ctx.lookup(QUEUE_NAME); QueueRequestor qrq = new QueueRequestor(qs, queue); ObjectMessage exampleMessage = ts.createObjectMessage(); // Nachricht mit Inhalten füllen ... Message answer = trq.request(exampleMessage); // Antwort auswerten qc.close(); Enterprise Application Integration 27 Björn Eilers Java Message Service Dienstenutzer: tc.start(); Topic topic = (Topic) ctx.lookup("topic/TestTopic"); TopicPublisher publisher = ts.createPublisher(topic); TemporaryTopic replyTopic = ts.createTemporaryTopic(); TopicSubscriber subscriber = ts.createSubscriber(replyTopic); MapMessage exampleMessage = ts.createMapMessage(); // ... Nachricht füllen ... // Rückgabekanal setzen exampleMessage.setJMSReplyTo(replyTopic); // Nachricht senden publisher.publish(exampleMessage); // Max. 15 sek. auf Antwort warten Message answer = subscriber.receive(15000); // ... Antwort verarbeiten ... tc.close(); Enterprise Application Integration 28 Björn Eilers Java Message Service Diensteanbieter (hier MessageListener/MDB, auch receive/reply): public void onMessage(Message message) { try { // Antwort auslesen // TopicConnection tc und Session ts erstellen tc.start(); Topic replyTopic = (Topic)message.getJMSReplyTo(); TopicPublisher publisher = ts.createPublisher(replyTopic); Message replyMessage = ts.createMessage(); // ... Nachricht mit Inhalt füllen ... publisher.publish(replyMessage); tc.close(); } catch (Exception e) {} } Enterprise Application Integration 29 Björn Eilers Java Message Service Message Selektoren: Nur für Topics Nachrichten können anhand ihrer Properties selektiert werden Beispiel: Wetterinformationen nur für eine bestimmte Stadt aus Topic selektieren Angabe eines Selektors bei Erzeugung eines TopicSubscribers: topicSession.createSubscriber(topic, messageSelector, true); Selektorstring: Bezeichner, Werte, Vergleichs- und logische Operatoren "Stadt = 'Münster' AND Temperatur BETWEEN 15 AND 25 AND Sicht NOT IN ('neblig', 'dunkel') AND Absender LIKE 'B%n E%rs'" Setzen der Properties in der Nachricht: message.setStringProperty("Stadt", "Münster"); message.setIntProperty("Temperatur", 18); Enterprise Application Integration 30 Björn Eilers Java Message Service Mehrere Nachrichten synchron empfangen Voraussetzung: Maximale Anzahl an Empfängern bekannt Ausgehende Nachricht senden In Schleife mit queueReceiver.receive() bzw. topicSubscriber.subscribe() Nachrichten empfangen, dabei Timeout mit jeder Nachricht reduzieren Schleife verlassen, wenn Timeout oder maximale Anzahl an Nachrichten erhalten Enterprise Application Integration 31 Björn Eilers Message-Driven Beans Message-Driven Beans Stellen JMS-Nachrichtenempfänger dar Können Queues oder Topics abfragen kapseln das Empfangen von Nachricht, nur Verarbeitung muss implementiert werden Interface MessageDrivenBean und MessageListener müssen implementiert werden Verarbeitung dann über onMessage()-Methode Wichtig: ohne zusätzlichen Implementierungsaufwand kein Senden von Nachrichten Enterprise Application Integration 32 Björn Eilers Message-Driven Beans Definition der Eigenschaften einer Message-Driven Bean über XDoclet @ejb.bean destination-type = "javax.jms.(Topic|Queue)": Setzt die Art der Destination destination-jndi-name = "destinationJNDIName": Setzt den JNDI-Namen der Destination acknowledge-mode = "Auto-acknowledge": Nachrichten-Empfang automatisch bestätigen message-selector = "Selektorstring": Definieren eines Message Selektors für Topics @jboss.destination-jndi-name name = "destinationJNDIName": JNDI-Namen der Destination im JBoss bekanntgeben Enterprise Application Integration 33 Björn Eilers Message-Driven Beans Beispiel: /** @ejb.bean name="ExampleMDB" * display-name="Example Message Driven Bean" * destination-type="javax.jms.Topic" * destination-jndi-name = "topic/ExampleTopic" * acknowledge-mode="Auto-acknowledge" * message-selector="ExampleString = 'example'" * @jboss.destination-jndi-name * name = "topic/ExampleTopic" */ public class TransferBean implements MessageDrivenBean, MessageListener { } Enterprise Application Integration 34 Björn Eilers Message-Driven Beans public class TransferBean implements MessageDrivenBean, MessageListener { private MessageDrivenContext ctx; public TransferBean() { } public void setMessageDrivenContext(MessageDrivenContext ctx) throws EJBException { this.ctx = ctx; } public void ejbCreate() { } public void ejbRemove() throws EJBException { } public void onMessage(Message message) { // ... Nachrichten verarbeiten } } Enterprise Application Integration 35 Björn Eilers Beispiel <<EntityBean>> AccountBean <<SessionBean>> AccountManagem entBean -unbenannt1 : AccountBean +makeTransfer( sourceAccNo : String, destAccNo : String, amount : float ) -accountNumber : String -balance : float -name : String -forename : String <<MessageDrivenBean>> TransferBean TransferInform ation #makeTransfer( transferInformation : TransferInformation ) +onMessage( message : Message ) -amount : float -receiverName : String -receiverAccount : String -receiverInstituteID : String -receiverInstituteName : String -referenceText : String -senderName : String -senderAccount : String <<Sw ing Component>> TransferPanel +getTransferInformation() : TransferInformation 1 -transferPanel <<GUI>> ClerkClient <<GUI>> AbstractClient #makeTransfer( transferInformation : TransferInformation ) Enterprise Application Integration 36 Björn Eilers <<Sw ing Component>> TransferReplyDialog 1 -replyDialog <<GUI>> Custom erClient Literatur Keller, W.: Enterprise Application Integration, dpunkt-Verlag 2002. Guter Überblick über sowohl technische als auch wirtschaftliche Aspekte der EAI Roman, E., et. al.: Mastering Enterprise JavaBeans, Third Edition http://www.theserverside.com/books/wiley/masteringEJB/index.tss Java Message Service Specification 1.1 http://java.sun.com/products/jms/docs.html Kurzdokumentationen zu J2EE und EAI http://www.torsten-horn.de/techdocs/#JEE (einführende Beispiel in J2EE) Enterprise Application Integration 37 Björn Eilers