Guide des beans gérés par message dans EJB

1. Introduction

En termes simples, un Enterprise JavaBean (EJB) est un composant JEE qui s'exécute sur un serveur d'applications.

Dans ce didacticiel, nous aborderons le message Driven Beans (MDB), responsable de la gestion du traitement des messages dans un contexte asynchrone.

Les MDB font partie de JEE depuis la spécification EJB 2.0; EJB 3.0 a introduit l'utilisation d'annotations , facilitant la création de ces objets. Ici, nous allons nous concentrer sur les annotations.

2. Quelques informations générales

Avant de plonger dans les détails de Message Driven Beans, passons en revue quelques concepts liés à la messagerie.

2.1. Messagerie

La messagerie est un mécanisme de communication. En utilisant la messagerie, les programmes peuvent échanger des données même s'ils sont écrits dans des langages de programme différents ou résident dans différents systèmes opérationnels.

Il offre une solution faiblement couplée; ni le producteur ni le consommateur des informations n'ont besoin de se connaître mutuellement .

Par conséquent, ils n'ont même pas besoin d'être connectés au système de messagerie en même temps (communication asynchrone).

2.2. Communication synchrone et asynchrone

Pendant la communication synchrone, le demandeur attend le retour de la réponse. En attendant, le processus du demandeur reste bloqué.

Dans une communication asynchrone, en revanche, le demandeur lance l'opération mais n'est pas bloqué par celle-ci; le demandeur peut passer à d'autres tâches et recevoir la réponse ultérieurement.

2.3. JMS

Java Message Services («JMS») est une API Java qui prend en charge la messagerie.

JMS fournit des modèles de messagerie d'égal à égal et de publication / abonnement.

3. Beans pilotés par message

Un MDB est un composant appelé par le conteneur à chaque fois qu'un message arrive sur le système de messagerie. En conséquence, cet événement déclenche le code à l'intérieur de ce bean.

Nous pouvons effectuer de nombreuses tâches dans une méthode MDB onMessage () , depuis l'affichage des données reçues sur un navigateur ou leur analyse et leur enregistrement dans une base de données.

Un autre exemple est la soumission de données à une autre file d'attente après un certain traitement. Tout dépend de nos règles commerciales.

3.1. Cycle de vie des beans gérés par message

Une MDB n'a que deux états:

  1. Il n'existe pas sur le conteneur
  2. créé et prêt à recevoir des messages

Les dépendances, si présentes, sont injectées juste après la création de la MDB.

Pour exécuter des instructions avant de recevoir des messages, nous devons annoter une méthode avec @ javax.ejb. PostConstruct .

Injection de dépendances et @ javax.ejb. L' exécution PostConstruct n'a lieu qu'une seule fois.

Après cela, la MDB est prête à recevoir des messages.

3.2. Transaction

Un message peut être remis à une MDB dans un contexte de transaction.

Cela signifie que toutes les opérations de la méthode onMessage () font partie d'une seule transaction.

Par conséquent, si une annulation se produit, le système de messagerie renvoie les données.

4. Utilisation des beans gérés par message

4.1. Créer le consommateur

Pour créer un Message Driven Bean, nous utilisons l' annotation @ javax.ejb.MessageDriven avant la déclaration du nom de classe.

Pour gérer le message entrant, nous devons implémenter la méthode onMessage () de l' interface MessageListener :

@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()); } } }

Étant donné que cet article se concentre sur les annotations au lieu des descripteurs .xml, nous utiliserons @ActivationConfigProperty plutôt que .

@ActivationConfigProperty est une propriété clé-valeur qui représente cette configuration. Nous utiliserons deux propriétés dans activationConfig , définissant la file d'attente et le type d'objet que la MDB consommera.

A l' intérieur onMessage () méthode que nous pouvons jeter paramètre de message à TextMessage, BytesMessage, MapMessage StreamMessage ou ObjectMessage .

Cependant, pour cet article, nous examinerons uniquement le contenu du message sur la sortie standard.

4.2. Création du producteur

Comme indiqué dans la section 2.1, les services aux producteurs et aux consommateurs sont totalement indépendants et peuvent même être écrits dans différents langages de programmation !

Nous produirons nos messages en utilisant des servlets Java:

@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); }

Après avoir obtenu les instances ConnectionFactory et Queue , nous devons créer une connexion et une session .

Pour créer une session, nous appelons la méthode createSession .

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.

Par conséquent, les MDB nous permettent de découpler nos applications en services plus petits avec des responsabilités localisées , ce qui permet un système beaucoup plus modulaire et incrémental qui peut récupérer des pannes système.

Comme toujours, le code est terminé sur GitHub.