Руководство по бинам, управляемым сообщениями в EJB
1. Вступление
Проще говоря, Enterprise JavaBean (EJB) - это компонент JEE, который работает на сервере приложений.
В этом руководстве мы обсудим компоненты, управляемые сообщениями (MDB), отвечающие за обработку сообщений в асинхронном контексте.
MDB являются частью JEE, начиная со спецификации EJB 2.0; EJB 3.0 introduced the use of annotations, что упрощает создание этих объектов. Здесь мы сосредоточимся на аннотациях.
2. Некоторый Фон
Прежде чем мы углубимся в детали компонентов, управляемых сообщениями, давайте рассмотрим некоторые концепции, связанные с обменом сообщениями.
2.1. обмен сообщениями
Обмен сообщениями - это механизм общения. By using messaging, programs can exchange data even if they’re written in different program languages or reside in different operational systems.с
Он предлагает слабосвязанное решение; neither the producer or the consumer of the information need to know details about each other.
Поэтому их даже не нужно одновременно подключать к системе обмена сообщениями (асинхронная связь).
2.2. Синхронная и асинхронная связь
Во время синхронной связи запрашивающая сторона ждет, пока ответ не вернется. В то же время процесс запроса остается заблокированным.
С другой стороны, при асинхронном взаимодействии запрашивающая сторона инициирует операцию, но не блокируется ею; запрашивающий может перейти к другим задачам и получить ответ позже.
2.3. JMS
Java Message Services («JMS») - это Java API, поддерживающий обмен сообщениями.
JMS предоставляет одноранговые и публиковать / подписывать модели обмена сообщениями.
3. Бобы, управляемые сообщениями
An MDB is a component invoked by the container every time a message arrives on the messaging system. В результате это событие запускает код внутри этого bean-компонента.
Мы можем выполнять множество задач внутри метода MDBonMessage(), начиная с отображения полученных данных в браузере или анализа и сохранения их в базе данных.
Другой пример - отправка данных в другую очередь после некоторой обработки. Все сводится к нашим бизнес-правилам.
3.1. Жизненный цикл компонентов, управляемых сообщениями
MDB имеет только два состояния:
-
Его нет в контейнере
-
создан и готов к приему сообщений
Зависимости, если они есть, вводятся сразу после создания 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, а не
@ActivationConfigProperty - это свойство типа "ключ-значение", представляющее эту конфигурацию. Мы будем использовать два свойства внутриactivationConfig, устанавливая очередь и тип объекта, который будет использовать MDB.
Внутри методаonMessage() мы можем привести параметр сообщения кTextMessage, BytesMessage, MapMessage StreamMessage илиObjectMessage.
Однако в этой статье мы рассмотрим только содержание сообщения в стандартном выводе.
4.2. Создание продюсера
Как описано в разделе 2.1,producer and consumer services are completely independent and can even be written in different programming languages!
Мы будем создавать наши сообщения с помощью сервлетов 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 - этоboolean, который определяет, является ли сеанс частью транзакции или нет.
Второй параметр используется только тогда, когда первый равенfalse. Он позволяет нам описать метод подтверждения, который применяется к входящим сообщениям и принимает значенияSession.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE иSession.DUPS_OK_ACKNOWLEDGE.
Теперь мы можем запустить соединение, создать текстовое сообщение на объекте сеанса и отправить наше сообщение.
Потребитель, привязанный к той же очереди, получит сообщение и выполнит свою асинхронную задачу.
Кроме того, помимо поиска объектовJNDI, все действия в нашем блоке try-with-resources гарантируют, что соединение будет закрыто, еслиJMSException обнаруживает ошибку, например, пытается подключиться к несуществующей очереди или указав неправильный номер порта для подключения.
5. Тестирование компонента, управляемого сообщениями
Отправьте сообщение через методGET наSendMessageServlet, как в:
Кроме того, сервлет отправляет“Hello World” в очередь, если мы не отправляем никаких параметров, как вhttp://127.0.0.1:8080/producer/SendMessageServlet.
6. Заключение
Бины, управляемые сообщениями, позволяют легко создавать приложения на основе очередей.
Следовательно,MDBs allow us to decouple our applications into smaller services with localized responsibilities, что позволяет создать гораздо более модульную и инкрементную систему, которая может восстанавливаться после сбоев системы.
Как всегда, кодover on GitHub.