Что такое mdb java
This section explains how to write, compile, package, deploy, and run an application that uses the JMS API in conjunction with a session bean. The application contains the following components:
- An application client that invokes a session bean
- A session bean that publishes several messages to a topic
- A message-driven bean that receives and processes the messages using a durable topic subscription and a message selector
You will find the source files for this section in the tut-install`/examples/jms/clientsessionmdb/` directory. Path names in this section are relative to this directory.
The following topics are addressed here:
- Writing the Application Components for the clientsessionmdb Example
- Running the clientsessionmdb Example
Writing the Application Components for the clientsessionmdb Example
This application demonstrates how to send messages from an enterprise bean (in this case, a session bean) rather than from an application client, as in the example in Receiving Messages Asynchronously Using a Message-Driven Bean. Figure 49-4 illustrates the structure of this application. Sending messages from an enterprise bean is very similar to sending messages from a managed bean, which was shown in Sending and Receiving Messages Using a Simple Web Application.
Figure 49-4 An Enterprise Bean Application: Client to Session Bean to Message-Driven Bean
The Publisher enterprise bean in this example is the enterprise-application equivalent of a wire-service news feed that categorizes news events into six news categories. The message-driven bean could represent a newsroom, where the sports desk, for example, would set up a subscription for all news events pertaining to sports.
The application client in the example injects the Publisher enterprise bean’s remote home interface and then calls the bean’s business method. The enterprise bean creates 18 text messages. For each message, it sets a String property randomly to one of six values representing the news categories and then publishes the message to a topic. The message-driven bean uses a message selector for the property to limit which of the published messages will be delivered to it.
Coding the Application Client: MyAppClient.java
The application client, MyAppClient.java , found under clientsessionmdb-app-client , performs no JMS API operations and so is simpler than the client in Receiving Messages Asynchronously Using a Message-Driven Bean. The client uses dependency injection to obtain the Publisher enterprise bean’s business interface:
@EJB(name="PublisherRemote") private static PublisherRemote publisher;
The client then calls the bean’s business method twice.
Coding the Publisher Session Bean
The Publisher bean is a stateless session bean that has one business method. The Publisher bean uses a remote interface rather than a local interface because it is accessed from the application client.
The remote interface, PublisherRemote.java , found under clientsessionmdb-ejb , declares a single business method, publishNews .
The bean class, PublisherBean.java , also found under clientsessionmdb-ejb , implements the publishNews method and its helper method chooseType . The bean class injects SessionContext and Topic resources (the topic is defined in the message-driven bean). It then injects a JMSContext , which uses the preconfigured default connection factory unless you specify otherwise. The bean class begins as follows:
@Stateless @Remote(< PublisherRemote.class >) public class PublisherBean implements PublisherRemote < @Resource private SessionContext sc; @Resource(lookup = "java:module/jms/newsTopic") private Topic topic; @Inject private JMSContext context; .
The business method publishNews creates a JMSProducer and publishes the messages.
Coding the Message-Driven Bean: MessageBean.java
The message-driven bean class, MessageBean.java , found under clientsessionmdb-ejb , is almost identical to the one in Receiving Messages Asynchronously Using a Message-Driven Bean. However, the @MessageDriven annotation is different, because instead of a queue, the bean is using a topic, a durable subscription, and a message selector. The bean defines a topic for the use of the application; the definition uses the java:module scope because both the session bean and the message-driven bean are in the same module. Because the destination is defined in the message-driven bean, the @MessageDriven annotation uses the destinationLookup activation config property. (See Creating Resources for Java EE Applications for more information.) The annotation also sets the activation config properties messageSelector , subscriptionDurability , clientId , and subscriptionName , as follows:
@JMSDestinationDefinition( name = "java:module/jms/newsTopic", interfaceName = "javax.jms.Topic", destinationName = "PhysicalNewsTopic") @MessageDriven(activationConfig = < @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "java:module/jms/newsTopic"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"), @ActivationConfigProperty(propertyName = "messageSelector", propertyValue = "NewsType = 'Sports' OR NewsType = 'Opinion'"), @ActivationConfigProperty(propertyName = "subscriptionDurability", propertyValue = "Durable"), @ActivationConfigProperty(propertyName = "clientId", propertyValue = "MyID"), @ActivationConfigProperty(propertyName = "subscriptionName", propertyValue = "MySub") >)
The topic is the one defined in the PublisherBean . The message selector in this case represents both the sports and opinion desks, just to demonstrate the syntax of message selectors.
The JMS resource adapter uses these properties to create a connection factory for the message-driven bean that allows the bean to use a durable subscription.
Running the clientsessionmdb Example
You can use either NetBeans IDE or Maven to build, deploy, and run the simplemessage example.
This example uses an annotation-defined topic and the preconfigured default connection factory java:comp/DefaultJMSConnectionFactory , so you do not have to create resources for it.
The following topics are addressed here:
- To Run clientsessionmdb Using NetBeans IDE
- To Run clientsessionmdb Using Maven
To Run clientsessionmdb Using NetBeans IDE
- Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server).
- From the File menu, choose Open Project.
- In the Open Project dialog box, navigate to:
tut-install/examples/jms/clientsessionmdb
This command creates the following:
- An application client JAR file that contains the client class file and the session bean’s remote interface, along with a manifest file that specifies the main class and places the EJB JAR file in its classpath
- An EJB JAR file that contains both the session bean and the message-driven bean
- An application EAR file that contains the two JAR files
The clientsessionmdb.ear file is created in the clientsessionmdb-ear/target/ directory.
The command then deploys the EAR file, retrieves the client stubs, and runs the client.
The client displays these lines:
To view the bean output, check /domains/domain1/logs/server.log.
The output from the enterprise beans appears in the server log file. The Publisher session bean sends two sets of 18 messages numbered 0 through
To Run clientsessionmdb Using Maven
- Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server).
- Go to the following directory:
tut-install/examples/jms/clientsessionmdb/
mvn install
This command creates the following:
- An application client JAR file that contains the client class file and the session bean’s remote interface, along with a manifest file that specifies the main class and places the EJB JAR file in its classpath
- An EJB JAR file that contains both the session bean and the message-driven bean
- An application EAR file that contains the two JAR files
The clientsessionmdb.ear file is created in the clientsessionmdb-ear/target/ directory.
The command then deploys the EAR file, retrieves the client stubs, and runs the client.
The client displays these lines:
To view the bean output, check /domains/domain1/logs/server.log.
The output from the enterprise beans appears in the server log file. The Publisher session bean sends two sets of 18 messages numbered 0 through
mvn cargo:undeploy
Что такое mdb java
The Java EE 6 Tutorial
What Is a Message-Driven Bean?
A message-driven bean is an enterprise bean that allows Java EE applications to process messages asynchronously. This type of bean normally acts as a JMS message listener, which is similar to an event listener but receives JMS messages instead of events. The messages can be sent by any Java EE component (an application client, another enterprise bean, or a web component) or by a JMS application or system that does not use Java EE technology. Message-driven beans can process JMS messages or other kinds of messages.
What Makes Message-Driven Beans Different from Session Beans?
The most visible difference between message-driven beans and session beans is that clients do not access message-driven beans through interfaces. Interfaces are described in the section Accessing Enterprise Beans. Unlike a session bean, a message-driven bean has only a bean class.
In several respects, a message-driven bean resembles a stateless session bean.
- A message-driven bean’s instances retain no data or conversational state for a specific client.
- All instances of a message-driven bean are equivalent, allowing the EJB container to assign a message to any message-driven bean instance. The container can pool these instances to allow streams of messages to be processed concurrently.
- A single message-driven bean can process messages from multiple clients.
The instance variables of the message-driven bean instance can contain some state across the handling of client messages, such as a JMS API connection, an open database connection, or an object reference to an enterprise bean object.
Client components do not locate message-driven beans and invoke methods directly on them. Instead, a client accesses a message-driven bean through, for example, JMS by sending messages to the message destination for which the message-driven bean class is the MessageListener. You assign a message-driven bean’s destination during deployment by using GlassFish Server resources.
Message-driven beans have the following characteristics.
- They execute upon receipt of a single client message.
- They are invoked asynchronously.
- They are relatively short-lived.
- They do not represent directly shared data in the database, but they can access and update this data.
- They can be transaction-aware.
- They are stateless.
When a message arrives, the container calls the message-driven bean’s onMessage method to process the message. The onMessage method normally casts the message to one of the five JMS message types and handles it in accordance with the application’s business logic. The onMessage method can call helper methods or can invoke a session bean to process the information in the message or to store it in a database.
A message can be delivered to a message-driven bean within a transaction context, so all operations within the onMessage method are part of a single transaction. If message processing is rolled back, the message will be redelivered. For more information, see Chapter 25, A Message-Driven Bean Example and Chapter 44, Transactions.
When to Use Message-Driven Beans
Session beans allow you to send JMS messages and to receive them synchronously but not asynchronously. To avoid tying up server resources, do not to use blocking synchronous receives in a server-side component; in general, JMS messages should not be sent or received synchronously. To receive messages asynchronously, use a message-driven bean.
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. Legal Notices
25. Message Driven Beans (mdb), жизненный цикл компонентов. Особенности разработки, применения и функционирования mdb, реализующие методы (примеры разработки клиента и серверной части). Настя
Бин, управляемый сообщениями (MDB), - это бин, который позволяет приложениям J2EE асинхронно обрабатывать сообщения. Он действует, как слушатель сообщений JMS, который подобен слушателю событий, за исключением того, что вместо событий, он принимает сообщения. MDB может обрабатывать JMS сообщения или другие виды сообщений.
Отличия mdb:
· MDB не сохраняют состояния клиента;
· Все MDB равноправны, т.е. EJB контейнер может присвоить сообщение любому бину, управляемому сообщениями;
· Один MDB может обрабатывать сообщения от множества клиентов;
Сообщения могут отправляться любым компонентом J2EE - клиентским приложением, другим корпоративным бином или Web-компонентом - или при помощи приложения JMS или системы, которая не использует технологию J2EE.
Компонент, управляемый сообщениями, отвечает за обработку сообщений, а его контейнер заботится об автоматическом управлении всем окружением компонента, включающим в себя транзакции, безопасность, ресурсы, совместный откат и подтверждения получения сообщений.
MDB – это просто MessageListener: класс реализует javax.ejb.MessageDrivenBean и javax.jms.MessageListener.
Первый интерфейс имеет два метода: setMessageDrivenContext и ejbRemove.
Второй интерфейс имеет один метод onMessage. Именно в методе onMessage() выполняется вся прикладная логика. Спецификация требует также создания метода ejbCreate без параметров.
Клиент не создает объектов MDB. Контейнер сам решит, когда и сколько ему требуется MDB для обработки сообщений из данного destination (в данном случае это: либо queue, либо topic – в зависимости от используемой модели: javax.jms.Queue или javax.jms.Topic).
Метод setMessageDrivenContext() класса ReservationProcessorBean устанавливает поле экземпляра ejbContext в значение MessageDrivenContext, которое было передано в метод. Кроме этого он получает ссылку на JNDI ENC, которую сохраняет в jndiContext. MDB может иметь поля экземпляра, похожие на поля экземпляра сеансового компонента без состояния. Значения этих полей сохраняются в экземпляре MDB в течение всей его жизни и могут многократно использоваться каждый раз, когда он обрабатывает новое сообщение. В отличие от сеансовых компонентов с состоянием, у MDB нет состояния диалога, и они не предназначаются для одного клиента JMS. Экземпляры MDB применяются для обработки сообщений от нескольких разных клиентов JMS и связаны не с клиентом, а с определенной темой или очередью, от которых они принимают сообщения.
Жизненный цикл экземпляра MDB имеет два состояния: «не существует» и «пул готовых методов». Пул готовых методов похож на пул экземпляров, используемый для сеансовых компонентов без состояния. Некоторые производители могут не использовать пул для MDB экземпляров, а вместо этого создавать и уничтожать экземпляры для каждого нового сообщения. Когда сообщение направлено экземпляру контейнером, MessageDrivenContext экземпляра MDB изменяется, чтобы отразить новый контекст транзакции. Экземпляр, закончивший обработку, сразу же становится доступным для обработки нового сообщения. Экземпляры компонентов переводятся из пула готовых методов в состояние «не существует», когда они становятся ненужными серверу. Это происходит, когда сервер принимает решение уменьшить общий размер пула готовых методов, удаляя из памяти один или несколько экземпляров. Этот процесс начинается с вызова метода ejbRemove() экземпляра.
//имя topic, на который подписан бин
public class MDBExample implements MessageListener
//метод, вызываемый при получении нового сообщения
public void onMessage(Message msg)
TextMessage message = (TextMessage)msg;
//считываем свойство из соответствующего поля, заданное вручную в consumer
System.out.println("FROM MDB - client type IS " + message.getStringProperty("clientType"));
//считываем само сообщение
System.out.println("FROM MDB - payload IS" + message.getText());
> catch (JMSException ex)
26. EJB-сервер и EJB-контейнер. Роль и использование в приложениях интерфейсов EJBHome и EJBObject. Упрощения модели программирования EJB 3Х. Особенности реализации EJB версии 3Х. ПОЛИНА
Существуют также интерфейсы EJBHome и EJBObject, который вы используете как базовый интерфейс, когда определяете собственное представление компонента (если оно вам нужно) - по этой причине EJBHome и EJBObject наследуются от интерфейса Remote RMI. Оставшиеся два интерфейса, EJBLocalHome и EJBLocalObject, вы используете для предоставления локального представления вашего компонента (опять таки, предполагается, что вам нужно это локальное представление)
Home-интерфейс и Home-объект
Когда у клиента EJB возникает потребность воспользоваться услугами EJB, он с помощью home-интерфейса создаёт EJB. Клиент использует один из методов create(), которые определяет home-интерфейс. Реализация home-интерфейса осуществляется с помощью объекта, называющегося home-объектом. Экземпляр такого home-объекта создаётся на сервере и в качестве factory (построителя) предоставляется клиенту для создания бина.
Интерфейс Time Home (реализация интерфейса Home)
public interface TimeHome extends EJBHome
public static final String COMP_NAME= «java:comp/env/ejb/Time»;
public static final String JNDI_NAME= «Time»;
public Time create () throws CreateException,RemoteException;>
Home interface
У каждой EJB-компоненты есть то, что называют ``родной интерфейс'' (home interface), который определяет методы создания, инициализации, удаления и (в случае entity beans) поиска экземпляров EJB-компонент на стороне сервера. ``Родной интерфейс'', по сути, описывает возможные взаимодействия между компонентой и контейнером, а конкретно -- описанные выше.
``Родной интерфейс'' для EJB-компоненты наследуется от интерфейса javax.ejb.EJBHome, который представляет базовую функциональность для взаимодействия между контейнером и компонентой. Все методы этого интерфейса должны быть RMI-совместимы. Интерфейс также описывает один или более create() методов, которые все называются ключевым словом create, но тело которых различно. Все create методы возвращают объект с ``внешним'' (remote) для данной компоненты интерфейсом.
EJBObject
EJBObject - это видимый в сети объект с собственной структурой и наполнением, действующий как proxy бина. Имеющийся у бина remote-интерфейс расширяет интерфейс javax.ejb.EJBObject, делая таким образом класс EJBObject специфическим для данного класса бина. Для каждого бина EJB существует стандартный класс EJBObject.
Корпоративные компоненты, записанные EJB 3.0 и более поздним API, не требуют удаленного интерфейса, который расширяет интерфейс EJBObject. Удаленный деловой интерфейс может использоваться вместо этого.
Единственное требование такое: этот интерфейс наследуется от javax.ejb.EJBObject и все его методы выбрасывают RemoteException.
public interface Movie extends EJBObject
public Integer getId () throws RemoteException;
Работа с JMS сообщениями и MDB в JEE
Работа с сообщениями подразумевает взаимодействие между компонентами системы посредством передачи сообщений. JMS позволяет реализовать это взаимодействие в java приложении, а MDB бины позволяют асинхронно обрабатывать получаемые сообщения на сервере приложений без дополнительных усилий по асинхронной обработке.
Ниже представлен простой пример обработки JMS сообщения с помощью MDB.
Немного теории
Для работы с сообщениями используется вспомогательное программное обеспечение, обычно входящее в поставку сервера приложений.
Компоненты системы могут посылать сообщения (producer) и получать их (consumer). Сообщение
отправляет producer на пункт назначения (destination), являющимся на сервере queue или topic, после чего consumer может забрать оттуда сообщение
В зависимости от того, какой тип имеет destination, разделяют две модели работы с сообщениями.
Первая модель — Point-to-Point
В случае если на сервере destination имеет тип queue, то сообщение, которое отправил producer, получает единственный consumer. Если на эту очередь сообщений подписано несколько получателей, то сообщение получит только один из них.
Вторая модель — Publish-subscribe
В случае если на сервере destination имеет тип topic, то одно сообщение может быть прочитано неограниченным количеством consumer, подписанных на этот на этот destination.
Структура JMS сообщения
Сообщение состоит из заголовка, поля свойств и тела.
Заголовок хранит мета информацию сообщения, заполняемую автоматически.
Поле свойств схоже с заголовком, но оно заполняется программно, и позже получатель сможет прочитать эту информацию.
Тело содержит полезную нагрузку сообщения. Тип нагрузки определяется при создании сообщения. Конкретные типы унаследованы от интерфейса javax.jms.Message
Создание очереди на сервере.
Для примера создадим topic на сервере. Использовать я буду glassfish 3.1.
Для начала создадим Connection Factory. Возможны несколько типов в зависимости от того, какой тип очереди сообщений будет использоваться.

Затем создаем destination с указание типа.

Создание отправителя сообщений
В данном случае producer будет находиться на сервере приложений. В случае если вам необходимо отправлять сообщения из отдельного клиента, то необходимо будет стандартным образом получить доступ к объектам по их JNDI имени из контекста.
//получаем ресурсы сервера для отправки сообщений @Resource(name="jms/TutorialPool") private ConnectionFactory connectionFactory; @Resource(name="jms/TutorialTopic") private Destination destination; public String getEnterString() < return enterString; >public void sendString(String enterString) < try < //создаем подключение Connection connection = connectionFactory.createConnection(); Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE); MessageProducer producer = session.createProducer(destination); TextMessage message = session.createTextMessage(); //добавим в JMS сообщение собственное свойство в поле сообщения со свойствами message.setStringProperty("clientType", "web clien"); //добавляем payload в сообщение message.setText(enterString); //отправляем сообщение producer.send(message); System.out.println("message sent"); //закрываем соединения session.close(); connection.close(); >catch (JMSException ex) < System.err.println("Sending message error"); ex.printStackTrace(); >>
Message-Driven Bean
Для обработки приходящих сообщений на сервере мы будем использовать MDB.
Сообщения можно было бы получать и обрабатывать и с помошью pojo, выступающего как consumer. Но использование MDB позволит параллельно обрабатывать сообщения, не заботясь о сложности асинхронной обработки и дополнительного кода для подписки на очередь сообщений.
Асинхронная обработка реализуется через пул объектов, из которых на обработку сообщения сервер выделят объекты при необходимости.
Для реализации MBD достаточно унаследовать бин от интерфейса javax.jms.MessageListener, реализуя метод onMessage(), и аннотировать соответствующим образом класс.
Сделаем пример MDB, который выводит в консоль сервера информацию о поступившем сообщении.
@MessageDriven( //имя topic, на который подписан бин mappedName="jms/TutorialTopic", name = "ExampleMDB") public class MDBExample implements MessageListener < //метод, вызываемый при получении нового сообщения @Override public void onMessage(Message msg) < try < TextMessage message = (TextMessage)msg; //считываем свойство из соответствующего поля, заданное вручную в consumer System.out.println("FROM MDB - client type IS " + message.getStringProperty("clientType")); //считываем само сообщение System.out.println("FROM MDB - payload IS" + message.getText()); >catch (JMSException ex) < ex.printStackTrace(); >> >
В onMessage метод добавляется необходимая бизнес логика, в зависимости от типа сообщения, его содержания и тд.
При необходимости, для ручной обработки сообщений можно самостоятельно создать обработчика.
Например так:
@Resource(name="jms/TutorialPool") private ConnectionFactory connectionFactory; @Resource(name="jms/TutorialTopic") private Destination destination; void onMessage() < try < Connection connection = connectionFactory.createConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer consumer = session.createConsumer(destination); connection.start(); while(true)< Message msg = consumer.receive(); //обработка сообщения >//закрыть connection > catch (JMSException ex) < ex.printStackTrace(); >>
Для более подробного изучения JMS и EJB в целом, могу рекомендовать книги:
EJB 3 in Action — Debu Panda, Reza Rahman, Derek Lane
Пару книг от Adam Bien
