Ein Leitfaden für Message Driven Beans in EJB

1. Einleitung

Einfach ausgedrückt ist eine Enterprise JavaBean (EJB) eine JEE-Komponente, die auf einem Anwendungsserver ausgeführt wird.

In diesem Tutorial werden wir uns mit Message Driven Beans (MDB) befassen, die für die Verarbeitung von Nachrichten in einem asynchronen Kontext verantwortlich sind.

MDBs sind seit der EJB 2.0-Spezifikation Teil von JEE. In EJB 3.0 wurde die Verwendung von Anmerkungen eingeführt , um das Erstellen dieser Objekte zu vereinfachen. Hier konzentrieren wir uns auf Anmerkungen.

2. Hintergrund

Bevor wir uns mit den Details zu Message Driven Beans befassen, wollen wir einige Konzepte im Zusammenhang mit Messaging überprüfen.

2.1. Messaging

Messaging ist ein Kommunikationsmechanismus. Durch die Verwendung von Messaging können Programme Daten austauschen, selbst wenn sie in verschiedenen Programmiersprachen geschrieben sind oder sich in verschiedenen Betriebssystemen befinden.

Es bietet eine lose gekoppelte Lösung; Weder der Hersteller noch der Verbraucher der Informationen müssen Einzelheiten voneinander wissen .

Daher müssen sie nicht einmal gleichzeitig mit dem Nachrichtensystem verbunden sein (asynchrone Kommunikation).

2.2. Synchrone und asynchrone Kommunikation

Während der synchronen Kommunikation wartet der Anforderer, bis die Antwort zurück ist. In der Zwischenzeit bleibt der Anforderungsprozess blockiert.

Bei der asynchronen Kommunikation hingegen initiiert der Anforderer die Operation, wird jedoch nicht von ihr blockiert. Der Anforderer kann mit anderen Aufgaben fortfahren und die Antwort später erhalten.

2.3. JMS

Java Message Services („JMS“) ist eine Java-API, die Messaging unterstützt.

JMS bietet Peer-to-Peer- und Publish / Subscribe-Messaging-Modelle.

3. Message Driven Beans

Eine MDB ist eine Komponente, die vom Container jedes Mal aufgerufen wird, wenn eine Nachricht auf dem Nachrichtensystem eintrifft. Infolgedessen löst dieses Ereignis den Code in dieser Bean aus.

Wir können viele Aufgaben innerhalb einer MDB onMessage () -Methode ausführen , da die empfangenen Daten in einem Browser angezeigt oder analysiert und in einer Datenbank gespeichert werden.

Ein anderes Beispiel ist das Senden von Daten an eine andere Warteschlange nach einer gewissen Verarbeitung. Alles hängt von unseren Geschäftsregeln ab.

3.1. Message Driven Beans Lifecycle

Eine MDB hat nur zwei Zustände:

  1. Es existiert nicht auf dem Container
  2. erstellt und bereit, Nachrichten zu empfangen

Die Abhängigkeiten, falls vorhanden, werden direkt nach dem Erstellen der MDB eingefügt.

Um Anweisungen auszuführen, bevor Nachrichten empfangen werden, müssen wir eine Methode mit @ javax.ejb kommentieren. PostConstruct .

Sowohl Abhängigkeitsinjektion als auch @ javax.ejb. Die Ausführung von PostConstruct erfolgt nur einmal.

Danach ist die MDB bereit, Nachrichten zu empfangen.

3.2. Transaktion

Eine Nachricht kann innerhalb eines Transaktionskontexts an eine MDB übermittelt werden.

Dies bedeutet, dass alle Operationen innerhalb der onMessage () -Methode Teil einer einzelnen Transaktion sind.

Wenn daher ein Rollback auftritt, liefert das Nachrichtensystem die Daten erneut.

4. Arbeiten mit nachrichtengesteuerten Bohnen

4.1. Creating the Consumer

To create a Message Driven Bean, we use @javax.ejb.MessageDriven annotation before the class name declaration.

To handle the incoming message, we must implement the onMessage() method of the MessageListener interface:

@MessageDriven(activationConfig = { @ActivationConfigProperty( propertyName = "destination", propertyValue = "tutorialQueue"), @ActivationConfigProperty( propertyName = "destinationType", propertyValue = "javax.jms.Queue") }) public class ReadMessageMDB implements MessageListener { public void onMessage(Message message) { TextMessage textMessage = (TextMessage) message; try { System.out.println("Message received: " + textMessage.getText()); } catch (JMSException e) { System.out.println( "Error while trying to consume messages: " + e.getMessage()); } } }

Since this article focus on annotations instead of .xml descriptors we'll use @ActivationConfigProperty rather than .

@ActivationConfigProperty is a key-value property that represents that configuration. We'll use two properties inside activationConfig, setting the queue and the type of object the MDB will consume.

Innerhalb der onMessage () -Methode können wir Nachrichtenparameter in TextMessage, BytesMessage, MapMessage StreamMessage oder ObjectMessage umwandeln .

In diesem Artikel wird jedoch nur der Nachrichteninhalt in der Standardausgabe betrachtet.

4.2. Produzenten erstellen

Wie in Abschnitt 2.1 beschrieben, sind Hersteller- und Verbraucherdienste völlig unabhängig und können sogar in verschiedenen Programmiersprachen geschrieben werden !

Wir werden unsere Nachrichten mit Java-Servlets erstellen:

@Override protected void doGet( HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String text = req.getParameter("text") != null ? req.getParameter("text") : "Hello World"; try ( Context ic = new InitialContext(); ConnectionFactory cf = (ConnectionFactory) ic.lookup("/ConnectionFactory"); Queue queue = (Queue) ic.lookup("queue/tutorialQueue"); Connection connection = cf.createConnection(); ) { Session session = connection.createSession( false, Session.AUTO_ACKNOWLEDGE); MessageProducer publisher = session .createProducer(queue); connection.start(); TextMessage message = session.createTextMessage(text); publisher.send(message); } catch (NamingException | JMSException e) { res.getWriter() .println("Error while trying to send  message: " + e.getMessage()); } res.getWriter() .println("Message sent: " + text); }

Nach dem Abrufen der Instanzen ConnectionFactory und Queue müssen wir eine Verbindung und eine Sitzung erstellen .

Um eine Sitzung zu erstellen, rufen wir die Methode createSession auf .

The first parameter in createSession is a boolean which defines whether the session is part of a transaction or not.

The second parameter is only used when the first is false. It allows us to describe the acknowledgment method that applies to incoming messages and takes the values of Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE and Session.DUPS_OK_ACKNOWLEDGE.

We can now start the connection, create a text message on the session object and send our message.

A consumer, bound to the same queue will receive a message and perform its asynchronous task.

Also, apart from looking up JNDI objects, all actions in our try-with-resources block make sure the connection is closed if JMSException encounters an error, such as trying to connect to a non-existing queue or specifying a wrong port number to connect.

5. Testing the Message Driven Bean

Send a message through the GET method on SendMessageServlet, as in:

//127.0.0.1:8080/producer/SendMessageServlet?text=Text to send

Also, the servlet sends “Hello World” to the queue if we don't send any parameters, as in //127.0.0.1:8080/producer/SendMessageServlet.

6. Conclusion

Message Driven Beans allow simple creation of a queue based application.

Mit MDBs können wir unsere Anwendungen daher in kleinere Dienste mit lokalisierten Verantwortlichkeiten entkoppeln , wodurch ein viel modulareres und inkrementelleres System ermöglicht wird, das sich von Systemfehlern erholen kann.

Wie immer ist der Code auf GitHub vorbei.