370 likes | 570 Views
Enterprise Application Integration. Message oriented Middleware. Einordnung in funktionale Bestandteile einer EAI Infrastruktur. Prozessmanagement. Metadatenbank für Zusatzdienste. Nachrichtenmanagement. Middleware. Adapter. Adapter. Adapter. Adapter. Adapter. Adapter.
E N D
Enterprise Application Integration Message oriented Middleware
Einordnung in funktionale Bestandteile einer EAI Infrastruktur Prozessmanagement Metadatenbank für Zusatzdienste Nachrichtenmanagement Middleware Adapter Adapter Adapter Adapter Adapter Adapter Physisches Netzwerk
eng Kopplung lose Kommunikation zwischen IS in Unternehmen • Remote Procedure Calls • Interface-basierte Middleware • CORBA • EJB • DCOM+ • Web Services • Nachrichten
Schnittstelle int addiere(int x, int y); 17 Aufrufende Klasse int result = schnittstelle.addiere(17, 25) 25 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 42 Implementierung int addiere(int x, int y) { return x+y; }
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 Empfänger An: Empfänger Dienst: addiere x: 17 y: 25 Nachrichten- warteschlange
Kommunikationsmodelle • Synchrone Kommunikation • Sender und Empfänger in Ablauf aneinander gekoppelt • Sender blockiert, bis Empfänger antwortet • Asynchrone Kommunikation • Sender und Empfänger in Ablauf nicht gekoppelt • Während Empfänger Antwort berechnet, kann Sender weiterarbeiten Sender Empfänger Sender Empfänger
Ack Kommunikationsvarianten • Synchrone Einwegkommunikation • z.B. entfernter Methodenaufruf ohne Rückgabe • Sender sendet Anfrage an Empfänger und blockiert • Empfänger nimmt Nachricht entgegen, sendet Bestätigung ("Acknowledgement") und verarbeitet dann Nachricht • Sender erhält Bestätigung und kann direkt weiterarbeiten Sender Empfänger
Kommunikationsvarianten • Synchrones Polling • 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 ErgebnissenFalls 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 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 Empfänger 2 Sender Empfänger 3
A A Abonniere Thema B A Abonniere Thema A Abonniere Thema A 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 Empfänger 2 Sender Zusteller Empfänger 3
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
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
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)
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
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 • Grundlegende Technologie für Message-Driven Beans Sender 1 Queue Empfänger Sender 2 Sender 1 Empfänger 1 Topic Sender 2 Empfänger 2
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 • 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") Header Properties 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
erzeugt Connection erzeugt erzeugt erzeugt MessageProducer Session MessageConsumer erzeugt Nachricht sendet an erhält von Destination Java Message Service ConnectionFactory
Java Message Service • Grundsätzlicher Ablauf der Kommunikation • 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
Java Message Service • Implementierung: Grundlegendes Gerüst für Clients try{ Propertiesp=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"); InitialContextctx=newInitialContext(); // ... }catch(JMSExceptione){ e.printStackTrace(); }catch(NamingExceptione){ e.printStackTrace(); }
Java Message Service • Nachricht an Queue senden QueueConnectionFactoryqcf=(QueueConnectionFactory) ctx.lookup("ConnectionFactory"); QueueConnectionqc=qcf.createQueueConnection(); QueueSessionqs=qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); qc.start(); Queuequeue=(Queue)ctx.lookup("queue/BeispielQueue"); QueueSendersender=qs.createSender(queue); MapMessageexampleMessage=qs.createMapMessage(); // ... sender.send(exampleMessage); qc.close(); für Transaktions- unterstützung: true
Java Message Service • Nachricht an Topic senden TopicConnectionFactorytcf=(TopicConnectionFactory)ctx .lookup("ConnectionFactory"); TopicConnectiontc=tcf.createTopicConnection(); TopicSessionts=tc.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); tc.start(); Topictopic=(Topic)ctx.lookup("topic/BeispielTopic"); TopicPublisherpublisher=ts.createPublisher(topic); MapMessagemessage=ts.createMapMessage(); // ... publisher.publish(message); tc.close();
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 publicclassExampleListener implementsjavax.jms.MessageListener{ publicvoidonMessage(Messagemessage){ // Verarbeitung: Gebe Empfangshinweis aus System.out.println("Nachricht mit ID "+ message.getJMSMessageID()+" empfangen."); } }
Java Message Service Queue // Properties setzen ... // Verbindung zum Queue erzeugen InitialContextctx=newInitialContext(); QueueConnectionFactoryqcf=(QueueConnectionFactory)ctx .lookup("ConnectionFactory"); QueueConnectionqc=qcf.createQueueConnection(); QueueSessionqs=qc .createQueueSession(false,Session.AUTO_ACKNOWLEDGE); Queuequeue=(Queue)ctx.lookup(QUEUE_NAME); QueueReceiverreceiver=qs.createReceiver(queue); receiver.setMessageListener(newExampleListener()); qc.start(); // warten ... // wenn nicht mehr empfangen werden soll: Verbindung schließen qc.close();
Java Message Service Topic // Properties setzen ... // Verbindung zum Topic erzeugen InitialContextctx=newInitialContext(); TopicConnectionFactorytcf=(TopicConnectionFactory)ctx .lookup("ConnectionFactory"); TopicConnectiontc=tcf.createTopicConnection(); TopicSessionts=tc .createTopicSession(false,Session.AUTO_ACKNOWLEDGE); Topictopic=(Topic)ctx.lookup(TOPIC_NAME); TopicSubscribersubscriber=ts.createSubscriber(topic); subscriber.setMessageListener(newExampleListener()); tc.start(); // warten ... // wenn nicht mehr empfangen werden soll: Verbindung schließen tc.close();
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(); Topictopic=(Topic)ctx.lookup(TOPIC_NAME); TopicRequestortrq=newTopicRequestor(ts,topic); ObjectMessageexampleMessage=ts.createObjectMessage(); // ... Nachricht mit Inhalten füllen ... Messageanswer=trq.request(exampleMessage); // Antwort auswerten tc.close();
Java Message Service qc.start(); Queuequeue=(Queue)ctx.lookup(QUEUE_NAME); QueueRequestorqrq=newQueueRequestor(qs,queue); ObjectMessageexampleMessage=ts.createObjectMessage(); // Nachricht mit Inhalten füllen ... Messageanswer=trq.request(exampleMessage); // Antwort auswerten qc.close();
Java Message Service • Dienstenutzer: tc.start(); Topictopic=(Topic)ctx.lookup("topic/TestTopic"); TopicPublisherpublisher=ts.createPublisher(topic); TemporaryTopicreplyTopic=ts.createTemporaryTopic(); TopicSubscribersubscriber=ts.createSubscriber(replyTopic); MapMessageexampleMessage=ts.createMapMessage(); // ... Nachricht füllen ... // Rückgabekanal setzen exampleMessage.setJMSReplyTo(replyTopic); // Nachricht senden publisher.publish(exampleMessage); // Max. 15 sek. auf Antwort warten Messageanswer=subscriber.receive(15000); // ... Antwort verarbeiten ... tc.close();
Java Message Service • Diensteanbieter (hier MessageListener/MDB, auch receive/reply): publicvoidonMessage(Messagemessage){ try{ // Antwort auslesen // TopicConnection tc und Session ts erstellen tc.start(); TopicreplyTopic=(Topic)message.getJMSReplyTo(); TopicPublisherpublisher= ts.createPublisher(replyTopic); MessagereplyMessage=ts.createMessage(); // ... Nachricht mit Inhalt füllen ... publisher.publish(replyMessage); tc.close(); }catch(Exceptione){} }
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);
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
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
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
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" */ publicclassTransferBeanimplementsMessageDrivenBean,MessageListener{ }
Message-Driven Beans publicclassTransferBeanimplementsMessageDrivenBean, MessageListener{ privateMessageDrivenContextctx; publicTransferBean(){ } publicvoidsetMessageDrivenContext(MessageDrivenContextctx) throwsEJBException{ this.ctx=ctx; } publicvoidejbCreate(){ } publicvoidejbRemove()throwsEJBException{ } publicvoidonMessage(Messagemessage){ // ... Nachrichten verarbeiten } }
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 Editionhttp://www.theserverside.com/books/wiley/masteringEJB/index.tss • Java Message Service Specification 1.1http://java.sun.com/products/jms/docs.html • Kurzdokumentationen zu J2EE und EAIhttp://www.torsten-horn.de/techdocs/#JEE (einführende Beispiel in J2EE)