«1. Введение
Проще говоря, Enterprise JavaBean (EJB) — это компонент JEE, работающий на сервере приложений.
В этом руководстве мы обсудим компоненты, управляемые сообщениями (MDB), отвечающие за обработку сообщений в асинхронном контексте.
MDB являются частью JEE, начиная со спецификации EJB 2.0; В EJB 3.0 введено использование аннотаций, упрощающих создание таких объектов. Здесь мы сосредоточимся на аннотациях.
2. Немного предыстории
Прежде чем мы углубимся в детали компонентов, управляемых сообщениями, давайте рассмотрим некоторые концепции, связанные с обменом сообщениями.
2.1. Обмен сообщениями
Обмен сообщениями — это механизм связи. Используя обмен сообщениями, программы могут обмениваться данными, даже если они написаны на разных языках программирования или находятся в разных операционных системах.
Он предлагает слабосвязанное решение; ни производитель, ни потребитель информации не должны знать подробности друг о друге.
Поэтому им даже не нужно одновременно подключаться к системе обмена сообщениями (асинхронная связь).
2.2. Синхронная и асинхронная связь
Во время синхронной связи инициатор запроса ожидает ответа. Тем временем запрашивающий процесс остается заблокированным.
С другой стороны, при асинхронном обмене запросчик инициирует операцию, но не блокируется ею; запросчик может перейти к другим задачам и получить ответ позже.
2.3. JMS
Java Message Services («JMS») — это Java API, поддерживающий обмен сообщениями.
JMS предоставляет одноранговые модели обмена сообщениями и модели публикации/подписки.
3. Компоненты, управляемые сообщениями
MDB — это компонент, вызываемый контейнером каждый раз, когда сообщение поступает в систему обмена сообщениями. В результате это событие запускает код внутри этого компонента.
Мы можем выполнять множество задач внутри метода MDB onMessage(), начиная с отображения полученных данных в браузере или парсинга и сохранения их в базе данных.
Другой пример — отправка данных в другую очередь после некоторой обработки. Все сводится к нашим бизнес-правилам.
3.1. Жизненный цикл компонентов, управляемых сообщениями
MDB имеет только два состояния:
- It doesn’t exist on the container
- created and ready to receive messages
Зависимости, если они есть, внедряются сразу после создания MDB.
Чтобы выполнить инструкции перед получением сообщений, нам нужно аннотировать метод с помощью @javax.ejb.PostConstruct.
И внедрение зависимостей, и выполнение @javax.ejb.PostConstruct происходят только один раз.
После этого MDB готов к приему сообщений.
3.2. Транзакция
Сообщение может быть доставлено в MDB внутри контекста транзакции.
Это означает, что все операции в методе onMessage() являются частью одной транзакции.
Поэтому, если происходит откат, система сообщений повторно доставляет данные.
4. Работа с компонентами, управляемыми сообщениями
4.1. Создание потребителя
Чтобы создать компонент, управляемый сообщениями, мы используем аннотацию @javax.ejb.MessageDriven перед объявлением имени класса.
Для обработки входящего сообщения мы должны реализовать метод onMessage() интерфейса 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());
}
}
}
Поскольку в этой статье основное внимание уделяется аннотациям, а не дескрипторам .xml, мы будем использовать @ActivationConfigProperty, а не \u003cactivation- конфигурационное свойство\u003e.
@ActivationConfigProperty — это свойство типа \»ключ-значение\», представляющее эту конфигурацию. Мы будем использовать два свойства внутри activityConfig, устанавливая очередь и тип объекта, который будет потреблять MDB.
Внутри метода onMessage() мы можем привести параметр сообщения к TextMessage, BytesMessage, MapMessage StreamMessage или ObjectMessage.
Однако в этой статье мы рассмотрим только содержимое сообщения в стандартном выводе.
4.2. Создание производителя
Как описано в разделе 2.1, сервисы производителя и потребителя полностью независимы и даже могут быть написаны на разных языках программирования!
Мы будем создавать наши сообщения, используя сервлеты 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);
}
После получения экземпляров ConnectionFactory и Queue мы должны создать Connection и Session.
Чтобы создать сеанс, мы вызываем метод createSession.
«Первый параметр в createSession — это логическое значение, которое определяет, является ли сеанс частью транзакции или нет.
Второй параметр используется только тогда, когда первый имеет значение false. Это позволяет нам описать метод подтверждения, который применяется к входящим сообщениям и принимает значения Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE и Session.DUPS_OK_ACKNOWLEDGE.
Теперь мы можем начать соединение, создать текстовое сообщение в объекте сеанса и отправить наше сообщение.
Потребитель, привязанный к той же очереди, получит сообщение и выполнит свою асинхронную задачу.
Кроме того, помимо поиска объектов JNDI, все действия в нашем блоке try-with-resources гарантируют, что соединение будет закрыто, если JMSException обнаружит ошибку, такую как попытка подключения к несуществующей очереди или указание неправильного порта. номер для подключения.
5. Тестирование компонента, управляемого сообщениями
Отправьте сообщение с помощью метода GET в SendMessageServlet, например:
http://127.0.0.1:8080/producer/SendMessageServlet?text=Отправляемый текст ~~ ~ Кроме того, сервлет отправляет «Hello World» в очередь, если мы не отправляем никаких параметров, как в http://127.0.0.1:8080/producer/SendMessageServlet.
6. Заключение
Компоненты, управляемые сообщениями, позволяют просто создавать приложения на основе очередей.
Таким образом, MDB позволяют нам разделить наши приложения на более мелкие службы с локализованными обязанностями, что позволяет создать гораздо более модульную и инкрементальную систему, которая может восстанавливаться после системных сбоев.
Как всегда код закончился на GitHub.
«