@Entity
public class SetupOffice implements Serializable {
Java Platform, Enterprise Edition (Java EE) 8 Учебник по Java EE |
Назад | Вперёд | Содержание |
В этом разделе объясняется, как написать, скомпилировать, упаковать, развернуть и запустить приложение, которое использует JMS API с сущностью. Приложение использует следующие компоненты:
Клиентское приложение, которое отправляет и получает сообщения
Два управляемых сообщениями бина
Класс сущности
Вы найдете исходные файлы для этого раздела в каталоге tut-install/examples/jms/clientmdbentity/
. Пути в этом разделе относятся к этому каталогу.
Здесь рассматриваются следующие темы:
Это приложение упрощённо моделирует рабочий процесс отдела кадров компании (HR) при найме нового сотрудника. Это приложение также демонстрирует, как использовать платформу Java EE для выполнения типовой для приложений JMS задачи.
Клиент обмена сообщениями часто должен ждать несколько сообщений из разных источников. Он использует содержимое всех этих сообщений для формирования нового сообщения, которое затем отправляет другому пункту назначения. Этот шаблон проектирования (который не является специфичным для JMS) называется объединением сообщений. Такая задача должна быть транзакционной, со всеми получениями и отправками в рамках одной транзакции. Если часть сообщений не были успешно получены, транзакцию можно откатить. Пример клиентского приложения, который иллюстрирует эту задачу, см. в разделе Использование локальных транзакций.
Компонент, управляемый сообщениями, может обрабатывать за раз только одно сообщение в транзакции. Чтобы обеспечить возможность объединения сообщений, приложение может иметь управляемый сообщениями компонент, хранящий промежуточную информацию в сущности Java Persistence API. Затем сущность может определить, была ли получена вся информация. Если это так, сущность может сообщить об этом обратно одному из управляемых сообщениями компонентов, который создаст и отправит сообщение в другой пункт назначения. После выполнения задачи сущность может быть удалена.
Основные этапы применения следующие.
Клиентское приложение отдела кадров генерирует идентификатор каждого нового сотрудника, а затем публикует сообщение (M1), содержащее имя нового сотрудника, идентификатор и должность. Он публикует сообщение в теме, потому что сообщение должно быть использовано двумя компонентами, управляемыми сообщениями. Затем клиент создаёт врéменную очередь ReplyQueue
со слушателем сообщений, который ожидает ответа на сообщение. (См. Создание вре́менных пунктов назначения для получения дополнительной информации.)
Два управляемых сообщениями бина обрабатывают каждое сообщение: один бин, OfficeMDB
, назначает номер офиса новому сотруднику, а другой бин, EquipmentMDB
, назначает ему оборудование. Первый компонент, обрабатывающий сообщение, создаёт и сохраняет объект с именем SetupOffice
, а затем вызывает бизнес-метод объекта для сохранения созданной им информации. Второй компонент находит существующую сущность и вызывает другой бизнес-метод для изменения её информации.
Когда и офис, и оборудование были назначены, бизнес-метод объекта возвращает значение true
бину, управляемому сообщениями, который вызвал метод. Затем управляемый сообщениями компонент отправляет в очередь ответов сообщение (M2), описывающее назначения. Затем он удаляет сущность. Слушатель сообщений клиентского приложения получает информацию.
Рисунок 49-5 иллюстрирует структуру этого приложения. Конечно, реальное приложение HR будет иметь больше компонентов. Другие компоненты могут настраивать учёт заработной платы и премий, расписание и т. д.
Рисунок 49-5 предполагает, что OfficeMDB
является первым управляемым сообщениями компонентом, который принимает сообщение от клиента. ЗатемOfficeMDB
создаёт и сохраняет объект SetupOffice
и устанавливает информацию об офисе. ЗатемEquipmentMDB
извлекает объект, устанавливает информацию об оборудовании и определяет, что объект закончил сбор информации. ЗатемEquipmentMDB
отправляет сообщение в очередь ответов и удаляет объект.
Пример включает в себя клиентское приложение, управляемые сообщениями компоненты и класс сущности.
Здесь рассматриваются следующие темы:
Для создания клиентского приложения HumanResourceClient.java
из clientmdbentity-app-client
необходимо выполнить следующие шаги:
Определить тему для приложения, используя пространство имён java:app
, поскольку тема используется как в клиентском приложении, так и в модуле EJB
Инъецировать ресурсы ConnectionFactory
и Topic
Создать TemporaryQueue
для получения уведомления о происходящей обработке на основе опубликованных им событий нового найма.
Создать JMSConsumer
для TemporaryQueue
, установить слушатель сообщений JMSConsumer-а и запустить соединение
Создать MapMessage
Создать пять новых сотрудников со случайно сгенерированными именами, должностями и идентификационными номерами (последовательно) и опубликовать пять сообщений с информацией об этих сотрудниках
Слушатель сообщений HRListener
ожидает сообщений, которые содержат назначенные офис и оборудование для каждого сотрудника. Когда приходит сообщение, слушатель сообщений отображает полученную информацию и определяет, все ли пять сообщений поступили. Если да, слушатель сообщения уведомляет метод main
и тот завершается.
В этом примере используются два управляемых сообщениями бина, оба в clientmdbentity-ejb
:
EquipmentMDB.java
OfficeMDB.java
Бины предпринимают следующие шаги.
Они инъецируют ресурсы MessageDrivenContext
, EntityManager
и JMSContext
.
Метод onMessage
извлекает информацию из сообщения. Метод EquipmentMDB.onMessage
выбирает оборудование для новой должности. Метод OfficeMDB.onMessage
случайным образом генерирует номер офиса.
После небольшой задержки (для моделирования реальных проблем обработки) метод onMessage
вызывает вспомогательный метод compose
.
Метод compose
выполняет следующие шаги.
Создаёт и сохраняет объект сущности SetupOffice
, либо выбирает его по первичному ключу.
Использует объект для хранения оборудования или служебной информации в базе данных, вызывая либо бизнес-метод doEquipmentList
, либо doOfficeNumber
.
Если бизнес-метод возвращает true
, что означает, что вся информация была сохранена, он извлекает информацию о пункте назначения для ответа из сообщения, создаёт JMSProducer
и отправляет ответное сообщение с информацией, которая содержится в объекте.
Удаляет сущность.
Класс сущности SetupOffice.java
находится также в clientmdbentity-ejb
. Сущность и управляемые сообщениями компоненты упакованы вместе в файл JAR EJB. Класс сущности объявлен следующим образом:
@Entity
public class SetupOffice implements Serializable {
Класс содержит конструктор без аргументов и конструктор, который принимает два аргумента: идентификатор сотрудника и его имя. Он также содержит get- и set- методы для идентификатора сотрудника, его имени, номера офиса и списка оборудования. Метод получения идентификатора сотрудника имеет аннотацию @Id
для указания, что это поле является первичным ключом:
@Id
public String getEmployeeId() {
return id;
}
Класс также реализует два бизнес-метода doEquipmentList
и doOfficeNumber
и их вспомогательный метод checkIfSetupComplete
.
Бины, управляемые сообщениями, вызывают бизнес-методы и методы получения.
В файле persistence.xml
для сущности указаны основные настройки:
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="clientmdbentity-ejbPU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>java:comp/DefaultDataSource</jta-data-source>
<properties>
<property name="eclipselink.ddl-generation"
value="drop-and-create-tables"/>
</properties>
</persistence-unit>
</persistence>
Вы можете использовать IDE NetBeans или Maven для сборки, развёртывания и запуска примера clientmdbentity
.
Поскольку в примере определяется собственная тема приложения и используется предустановленная фабрика соединений по умолчанию java:comp/DefaultJMSConnectionFactory
и предустановленный ресурс JDBC по умолчанию java:comp/DefaultDataSource
, не нужно создавать дополнительных ресурсов.
Здесь рассматриваются следующие темы:
Убедитесь, что сервер GlassFish (см. Запуск и остановка сервера GlassFish), а также сервер базы данных (см. Запуск и остановка Apache Derby) запущены.
В меню «Файл» выберите «Открыть проект».
В диалоговом окне «Открыть проект» перейдите к:
tut-install/examples/jms/clientmdbentity
Выберите каталог clientmdbentity
.
Нажмите Открыть проект.
На вкладке «Проекты» кликните правой кнопкой мыши проект clientmdbentity
и выберите «Сборка».
Эта команда создаёт следующее:
JAR-файл приложения-клиента, содержащий файлы класса клиента и класса слушателя, а также файл манифеста, в котором указан основной класс
JAR-файл EJB, содержащий управляемые сообщениями бины и класс сущностей, а также файл persistence.xml
Файл EAR приложения, который содержит два JAR-файла вместе с файлом application.xml
Файл clientmdbentity.ear
создаётся в каталоге clientmdbentity-ear/target/
.
Затем команда развёртывает файл EAR, извлекает клиентские заглушки и запускает клиентское приложение.
Убедитесь, что сервер GlassFish (см. Запуск и остановка сервера GlassFish), а также сервер базы данных (см. Запуск и остановка Apache Derby) запущены.
Перейдите в следующий каталог:
tut-install/examples/jms/clientmdbentity/
Чтобы скомпилировать исходные файлы и пакет, развернуть и запустить приложение, введите следующую команду:
mvn install
Эта команда создаёт следующее:
JAR-файл приложения-клиента, содержащий файлы класса клиента и класса слушателя, а также файл манифеста, в котором указан основной класс
JAR-файл EJB, содержащий управляемые сообщениями бины и класс сущностей, а также файл persistence.xml
Файл EAR приложения, который содержит два JAR-файла вместе с файлом application.xml
Затем команда развёртывает приложение, получает клиентские заглушки и запускает клиентское приложение.
Вывод в окне вывода IDE NetBeans или в окне терминала выглядит примерно так (ему предшествует вывод контейнера клиентского приложения и вывод Maven):
SENDER: Setting hire ID to 50, name Bill Tudor, position Programmer
SENDER: Setting hire ID to 51, name Carol Jones, position Senior Programmer
SENDER: Setting hire ID to 52, name Mark Wilson, position Manager
SENDER: Setting hire ID to 53, name Polly Wren, position Senior Programmer
SENDER: Setting hire ID to 54, name Joe Lawrence, position Director
Waiting for 5 message(s)
New hire event processed:
Employee ID: 52
Name: Mark Wilson
Equipment: Tablet
Office number: 294
Waiting for 4 message(s)
New hire event processed:
Employee ID: 53
Name: Polly Wren
Equipment: Laptop
Office number: 186
Waiting for 3 message(s)
New hire event processed:
Employee ID: 54
Name: Joe Lawrence
Equipment: Mobile Phone
Office number: 135
Waiting for 2 message(s)
New hire event processed:
Employee ID: 50
Name: Bill Tudor
Equipment: Desktop System
Office number: 200
Waiting for 1 message(s)
New hire event processed:
Employee ID: 51
Name: Carol Jones
Equipment: Laptop
Office number: 262
Вывод из бинов, управляемых сообщениями, и класса сущностей появляется в журнале сервера.
Для каждого сотрудника приложение сначала создаёт объект сущности, а затем извлекает его из хранилища. Вы можете увидеть ошибки времени выполнения в журнале сервера и произошедшие откаты соответствующих транзакций. Ошибки возникают, если оба управляемых сообщениями бина одновременно обнаруживают, что сущность ещё не существует, поэтому они оба пытаются его создать. Первая попытка успешна, но вторая — неудачна, потому что сущность уже существует. После отката и на последующей повторной попытке второй управляемый сообщениями компонент успешно извлекает сущность из хранилища. Управляемые контейнером транзакции позволяют приложению работать корректно, несмотря на эти ошибки, без специального программирования.
Чтобы удалить приложение после его завершения, перейдите на вкладку «Службы» или введите команду mvn cargo:undeploy
.
Назад | Вперёд | Содержание |