Un guide sur les Beans Message Driven dans les EJB

Un guide pour les beans Message Driven dans les EJB

1. introduction

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

Dans ce didacticiel, nous aborderons le message MDB (Message Driven Beans), 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 introduced the use of annotations, ce qui facilite la création de ces objets. Ici, nous allons nous concentrer sur les annotations.

2. Quelques antécédents

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. By using messaging, programs can exchange data even if they’re written in different program languages or reside in different operational systems.

Il offre une solution faiblement couplée; neither the producer or the consumer of the information need to know details about each other.

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 une communication synchrone, le demandeur attend que la réponse soit renvoyée. 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 prenant en charge la messagerie.

JMS fournit des modèles de messagerie poste à poste et publication / abonnement.

3. Beans pilotés par message

An MDB is a component invoked by the container every time a message arrives on the messaging system. Par conséquent, cet événement déclenche le code à l'intérieur de ce bean.

Nous pouvons effectuer de nombreuses tâches dans une méthode MDBonMessage(), 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 traitement. Tout se résume à nos règles de gestion.

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

Une BMD 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.

L'injection de dépendances et l'exécution de@javax.ejb.PostConstruct ne se produisent 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éthodeonMessage() font partie d'une seule transaction.

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

4. Travailler avec des beans piloté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éthodeonMessage() de l'interfaceMessageListener:

@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 à l'intérieur deactivationConfig, définissant la file d'attente et le type d'objet que la MDB consommera.

Dans la méthodeonMessage(), nous pouvons convertir le paramètre de message enTextMessage, BytesMessage, MapMessage StreamMessage ouObjectMessage.

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,producer and consumer services are completely independent and can even be written in different programming languages!

Nous produirons nos messages à l'aide de 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 <" + text + "> message: " + e.getMessage());
    }

    res.getWriter()
      .println("Message sent: " + text);
}

Après avoir obtenu les instancesConnectionFactory etQueue, nous devons créer unConnection etSession.

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

Le premier paramètre decreateSession est unboolean qui définit si la session fait partie d'une transaction ou non.

Le deuxième paramètre n'est utilisé que lorsque le premier estfalse. Il nous permet de décrire la méthode d'acquittement qui s'applique aux messages entrants et prend les valeurs deSession.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE etSession.DUPS_OK_ACKNOWLEDGE.

Nous pouvons maintenant établir la connexion, créer un message texte sur l'objet de session et envoyer notre message.

Un consommateur lié à la même file recevra un message et effectuera sa tâche asynchrone.

De plus, en plus de rechercher les objetsJNDI, toutes les actions de notre bloc try-with-resources s'assurent que la connexion est fermée siJMSException rencontre une erreur, telle que la tentative de connexion à une file d'attente inexistante ou en spécifiant un numéro de port incorrect pour se connecter.

5. Test du bean piloté par message

Envoyez un message via la méthodeGET surSendMessageServlet, comme dans:

De plus, le servlet envoie“Hello World” à la file d'attente si nous n'envoyons aucun paramètre, comme danshttp://127.0.0.1:8080/producer/SendMessageServlet.

6. Conclusion

Les Beans Message Driven permettent la création simple d'une application basée sur une file d'attente.

Par conséquent,MDBs allow us to decouple our applications into smaller services with localized responsibilities, permettant un système beaucoup plus modulaire et incrémental qui peut récupérer des pannes du système.

Comme toujours, le code estover on GitHub.