Jms/Exаmple1ConnectionFactory




на основе Java JMS

 

Цель работы - получение практических навыков создания корпоративной информа­ци­онной системы (КИС) на основе Java JMS, а именно:

- изучение вариантов взаимодействия удаленных объектов Java с исполь­зованием JMS;

- изучение компонентов JMS, необходимых для функционирования распределенных при­ложений Java;

- разработка распределенного Java-приложения с использованием JMS для функцио­нирова­ния в сетевом режиме;

- анализ достоинств и недостатков JMS по сравнению с другими технологиями расп­реде­ленного взаимодействия приложений.

1 Теоретическое введение

1.1 Архитектура JMS-базированной КИС

J ava M essaging S ystem(JMS) представляет собой универсальный интерфейс обобщенного Java API для корпоративных приложений (КИС), ори­енти­рованных на работу с помощью сообщений (message-oriented application programming) с целью обеспечения их независимости от конкретных реализаций служб обработки сообщений. В настоящее время спецификация JMS - это промышленный стандарт для обработки сообщений в масштабе предприятия.

Корпоративная информационная система типа MOM (М essage O riented M iddleware) (рисунок 1), обеспечивает так называемое «слабое связывание» приложений-поставщиков (Producers) с приложениями-потребителями (Consumers) посредством передачи сообщений (Messages) c помощью фабрик соединений (Connection Factories – CF).

 


Рисунок 1 – КИС типа МОМ

Архитектура JMS -базированной КИС выглядит следующим образом (рисунок 2):

 


 

Рисунок 1

 

- JMS-клиент (JMS client) - прикладная программа Java, использующая JMS для от­правки и приёма сообщений;

- JMS - поставщи­к (message producer) - JMS -клиент, посылающий сооб­щение;

- JMS - потребитель (message consu­mer) - JMS -клиент, принимающий сообще­ние[1];

- не JMS-клиент - программа, не имеющая отношения к JMS, однако являющиеся не­отъемлемой частью JMS -проекта КИС;

- JMS-провайдер (JMS provider) - система обработки сообщений, управляющая маршрутизацией и доставкой сообщений;

- JMS-приложение (JMS application) - прикладная программная система, состоящая из нескольких JMS -клиентов, и, как правило, одного JMS -провайдера;

- JMS-сообщение (JMS message) - объект, передаваемый и принимаемый JMS- клиен­тами;

- управляемые объекты JMS (administered objects) - буферы для хранения JMS- сообщений;

- средства администрирования JMS (administrative tools) - средства управления ресурсами, которые ис­пользующимися JMS клиентами.

- JMS-сессия (JMS Session) - однопоточный контекст для отсылки и получения JMS -­сообщений. JMS сессия может быть нетранзакционной, с поддержкой локальных транзакций, или участвовать в распределенных транзакциях;

- Расположение (destination) – объект, который используется клиентом либо для определе­ния адреса доставки сообщения, либо для получения сообщений, доставленных по определенному адресу.

- Соединение (Connection) - соединение с JMS -провайдером;

- Фабрика соединения (Connection Factory - CF) - администрируемый объект, используемый для создания соединения.

- Java Naming and Directory Interface (JNDI) - Java API, организованный в виде службы каталогов и позволяющий Java-клиентам открывать и просматривать данные и объекты по их именам (рисунок 2).

 

 

Рисунок 2

 

JMS определяет инфраструктуру компонентов, позволяющую разработчикам создавать автоматизированные, интеллектуальные решения, - для сетевого управления в быстро меня­ю­щихся ситуациях. JMS определяет трехуровневую архитектуру: уровень сетевых ресурсов, уровень агентов и уровень управления (рисунок 3).

Управляющее приложение
Агент управления Java
Уровень управления
Уровень агентов
Управляемый ресурс
Управляемый ресурс
Управляемый ресурс
Уровень сетевых устройств

 


Рисунок 3

Уровень сетевых устройств делает объект управляемым. Уровень агентов предостав­ляет управляющие сервисы, делающие ресурсы доступными для управления. Наконец, уровень управления дает возможность управляющему приложению осуществлять доступ к уп­равляемым ресурсам и взаимодействовать с ними через JMS -агентов. Кроме того, JMS обес­печивает поддержку существующих протоколов сетевого управления, например, SNMP, так что JMS позволяет осуществлять интеграцию КИС с существующими системами сетевого управ­ления.

Модель обмена сообщениями JMS удобно использовать в том случае, если распределен­ное приложение КИС обладает следующими характеристиками:

- взаимодействие между компонентами КИС является асинхронным;

- информация (сообщение) должна передаваться нескольким или даже всем компонен­там КИС (семантика передачи «от одного ко многим »);

- передаваемая информация используется внешними системами, часть из кото­рых неизвестна на момент проектирования КИС или интерфейсы которых подвер­жены частым изменениям[2];

- обменивающиеся информацией (сообщениями) компоненты КИС выполняются в разное время, что требует наличия посредника для промежуточного хранения переданной ин­фор­мации.

Стандартные интерфейсы JMS доступны в пакете javax.jms, который входит в ком­плект jdk. Реализация JMS от корпорации Oracle находится в пакете oracle.jms. Посколь­ку JMS является лишь интерфейсной оболочкой, описывающей доступные для приложения методы, то для разработки и тестирования КИС нужна конкретная реализация ин­тер­фейсов JMS, называемая JMS-провайдером. Провайдеры JMS создаются независимы­ми производи­те­ля­ми, и в настоящее время существует несколько таких реализаций (далее рассматривается ре­а­лизация, включенная в состав Java2 Enterprise Edition и Oracle GlassFish Server).

1.2 Сообщения

Типы сообщений

Сообщение в JMS - это Java-объект, состоящий из заголовка (header) и тела (body). В заголовке находится служебная информация, а тело сообщения содержит в себе пользователь­ские данные.

JMS API определяет несколько типов сообщений:

- BytesMessage содержит массив примитивов в теле сообщения. Таким образом, может быть использован для передачи данных между двумя приложениями в их родном формате, который может быть несовместим с другими типами Message. Также, может быть полезным в тех случаях, когда JMS используется как транспорт между двумя системами. Поскольку в нем можно хранить примитивные типы данных, они могут быть неправильно интерпретированы. Например, long может быть сохранен как short. Это может вызывать ошибки. Поэтому реко­мендуется читать данные строго в одном порядке и использовать те же типы данных, которые были использованы отправителем.

- StreamMessage содержит поток java-примитивов в теле сообщения. Содержит нес­ко­лько удобных методов для чтения данных, сохраненных в сообщении. Однако, StreamMe­s­sa­ge предотвращает неправильную интерпретацию данных. Например, чтение long как short. Это достигается тем фактом, что StreamMessage записывает также информацию о типах дан­ных, а не только их значения.

- TextMessage содержит в виде сообщения объект java.lang.String. Таким образом, его полезно использовать для обмена текстовыми данными. Также, может быть использован для обмена комплексными текстовыми данными на подобии XML-документов.

- ObjectMessage содержит объекты, реализующие интерфейс Serializable. Тем самым, позволяя приложениям обмениваться друг с другом объектами Java. Получатель сообщения должен привести тип объекта сообщения к реальному типу объекта. Поэтому, перед получением объекта, получатель должен знать действительный тип отосланного объекта. Неправи­льное приведение типов может породить ClassCastException. Более того, определение класса объекта, отосланного в сообщении, должно быть доступно на обоих машинах. Если определение класса недоступно на получателе, будет порождено исключение ClassNotFound­Excep­tion. Некоторые типы MOM могут поддерживать динамическую загрузку необходимых клас­сов по сети, но спецификация JMS не определяет это как обязательный пункт.

- MapMessage содержит данные в формате ключ-значение. Таким образом, тело сооб­щения представляет из себя ни что иное, как объект java.util.Properties. Значениями ключей могут быть Java примитивы или их оболочки.

Отметим также, что BytesMessage хранит данные примитивных типов посредством перевода их в байтовое представление. Таким образом, сообщение становится одни сплошным куском байтов. StreamMessage умеет различать типы данных, которые хранятся в теле сооб­щения, поскольку хранит информацию о типах данных. BytesMessage позволяет читать дан­ные с использованием любого типа. Это может вызвать ошибки при неправильном считывание различных типов данных. Например, long считывается в short.

Структура сообщения

Сообщение состоит из трех частей: заголовок, раздела свойств и тело.

Заголовок сообщения содержит значения полей сообщения, которые разработчик может использовать в приложении (таблица 1).

Таблица 1

Поле Описание
JMSDestination Содержит имя расположения, в которое посылается сообщение
JMSDeliveryMode Определяет, является ли сообщение сохраняемым или нет
JMSExpiration Определяет, когда сообщение устареет и будет удалено из системы (по умолчанию сообщение не устаревает никогда)
JMSPriority Определяет приоритет сообщения от 0 до 9 (по умолчанию 4)
JMSMessageID Уникальный идентификатор сообщения
JMSTimestamp Содержит информацию, когда именно MOM приняла сообщение от поставщика
JMSCorrelationID Может быть использовано разработчиком для согласования сообще­ний: например, если нужно переслать ряд сообщений, обьединен­ных в одну логическую группу (такую как набор товаров в заказе, при этом в каждое сообщение о товаре можно добавить номер заказа)
JMSReplyTo Может быть использовано разработчиком для того, чтобы потребитель знал, кому отсылать ответ
JMSType Может быть использован разработчиком для того, чтобы дать приложению информацию, как обращаться с данным сообщением; тип здесь понимается как application-specific type
JMSRedelivered Устанавливается, если сообщение не было доставлено с первой попыт­ки, например, в случае, когда потребитель не подтвердил получение сообщения

 

JMS предоставляет методы get() и set() получения и установки значений для каждого поля заголовка.

Раздел свойств содержит пары «ключ - значение», которые могут быть использованы для пересылки определенных данных между поставщиком и потребителем. В качестве значений могут быть использованы примитивные Java-типы (boolean, byte, float, double, short, int, long), а также строки (java.lang.String). Свойства устанавливаются и читаются с помощью со­ответствующих методов set() и get(). Например, для установки integer-свойства с ключом " MyProperty " и значением равным 100 нужен код:

textMessage.setIntProperty("MyProperty", 100);

 

, а для чтения:

int value = textMessage.getIntProperty("MyProperty");

Доставка сообщений

Сообщения могут быть несохраняемыми и сохраняемыми. Если сообщение сохраня­емо, то MOM сохраняет его в БД или файле; такое сообщение переживет «гибель» MOM. Какой тип сообщения выбрать – зависит от того, что вы ожидаете от КИС: большей надежности (в случае сохраняемых сообщений), либо большей производительности (в случае несохраняемых сообщений).

Можно установить режим доставки сообщения в момент его посылки (по умолчанию режим будет таким, каким его установил администратор при создании ConnectionFactory). Например:

textMessage.setText("It's my message");
sender.send(textMessage, DeliveryMode.NON_PERSISTENT ,
messagePriority, messageTimeToLive);

Уведомления о доставке сообщений - это механизм, при котором провайдер оповеща­ется о том, было ли сообщение доставлено адресату. Тип уведомления обычно задается при создании объекта сессии. Всего типов уведомления три:

- Session.DUPS_OK_ACKNOWLEDGE - «ленивое» уведомление о доставке. При нем сводится к минимуму работа по нахождению дубликатов сообщения. Должно использоваться только в том случае, если ожидается появление дублирующих сообщений.

- Session.AUTO_ACKNOWLEDGE - автоматическое уведомление об отправке при получении сообщения адресатом.

- Session.CLIENT_ACKNOWLEDGE - уведомление об отправке устанавливается вручную вызовом метода acknowledge() объектов Message.

Какой тип подтверждения сообщения выбрать – опять-таки нужно решать на основе анализа требований к КИС.

Отсеивание сообщений

JMS предоставляет механизм под названием селектор сообщений (message selector), позволяющий приложению фильтровать и классифицировать принимаемые сообщения. Селектор сообщений — это строка, содержащая выражение, основанное на спецификации SQL92. Селектор вызывается каждый раз при получении очередного сообщения. Сообщения, прошедшие отбор по критерию, становятся доступными приложению, остальные отбрасыва­ются. Выборка основана на сравнении полей заголовка и свойств сообщения.

Транзакции

Очень часто возникает необходимость посылать сообщения в контексте транзакции. JMS - транзакции группируют набор отправляемых сообщений в атомарную единицу обработки данных (рисунок 4).

 

 

Рисунок 4 - Использование механизма транзакций в КИС

 

Если в процессе передачи данных в пределах транзакции возникла хоть одна ошибка, всю транзакцию можно откатить (rollback).

Например, получив сообщение из очереди queue1, потребитель посылает это сообщение в другую очередь queue2. Если в этот момент происходит исключительная ситуация, то желательно, чтобы КИС вернулась в первоначальное состояние, т.е. сообщение вновь оказалось в очереди queue1.

Одно из главных преимуществ JMS в том, что посылка сообщения может быть частью транзакции. За создание и контроль транзакций отвечает объект Session. Распределенные транзакции могут поддерживаться посредством использования Java Transaction API (JTA).

Существует два подхода в использовании транзакций совместно с JMS. Один применим только внутри JMS, другой может быть использован для включения не только JMS но и, на­пример, JDBC -запроса к БД, в состав той же транзакции.

Первый подход заключается в использовании transacted sessions. Для этого достаточно при создании session выставить флаг transacted в значение true:

Session session = con nection .createQueueSession( true , Session.AUTO_ACKNOWLEDGE);

 

Важно отменить, что в случае transacted session второй аргумент – тип подтверждения полу­чения – хоть и присутствует, но игнорируется JMS. И подтверждение получения будет произведено, когда транзакция будет завершена методом commit() обьекта session, который дол­жен быть вызван клиентом, получающим сообщение. Интерфейс javax.jms.Sessi­on вклю­чает два метода: commit() - для подтверждения транзакции и rollback() - для отката к первоначальному состоянию.

И поставщик, и потребитель могут использовать transacted session.

Когда поставщик использует transacted session, посланные сообщения накапливаются в буфере до тех пор, пока он не вызовет либо метод commit(), либо метод rollback(). В случае вызова commit(), сообщения будут доступны для доставки, в случае вызова rollback(), JMS очистит буфер сообщений.

В случае, когда потребитель использует transacted session, объект session контролиру­ет подтверждение доставки сообщения. В случае вызова метода commit() производится под­тверж­де­ние получения сообщений в контексте данной транзакции, а в случае вызова метода rollback() JMS вернет все сообщения в соответствующее исходное расположение.

Второй подход заключается в использовании JTA [3] -транзакций совместно с JMS. Этот подход позволяет разработчику включать в единую транзакцию как посылку сообщений, так и запрос к БД.

Достигается это стандартным способом – использованием javax.transaction.UserTran­sac­ti­on. Например:

UserTransaction myTransaction = (UserTransaction)ctx.lookup("MyUserTransaction");
myTransaction.begin();
sender.send(textMessage);
myStatement.executeUpdate("INSERT INTO testTable VALUES (100,'BILL')");
myTransaction.commit();

 

При этом важно отметить, что механизм JTA не может быть использован совместно с tran­sacted session. Если попытаться совместить несовместимое, то transacted session будет иг­но­рировать вызовы commit() или rollback() интерфейса UserTransaction.

1.3 Модели передачи сообщений

JMS предоставляет две модели передачи сообщений (т.н. зоны сообщений (messa­ging domains)): «изда­ние - подписка » (publish an subscribe) и «точка - точка » (point to point).

Модель передачи сообщений «изда­ние - подписка»

 

Модель передачи сообщений «изда­ние - подписка » (рисунки 5…6) определена в пакете javax.jms.Topic и используется в том случае, ес­ли сообщение, отправленное одним клиентом, должно быть получено несколькими другими клиентами.

 

 

Рисунок 5 - Модель взаимодействия клиентов по некоторой теме

 

Рисунок 6 – Буферизация сообщений в модели взаимодействия «издание - подписка»

 

При использовании модели взаимодействия «издание - подписка» один поставщик может посылать сообщения многим потребителям через виртуальный канал, называе­мый темой (topic).

Потребители могут выбрать подписку (subscribe) на любую тему. Все сообщения, на­правляемые в тему, передаются всем потребителям данной темы. Каждый потребитель при­нимает копию каждого сообщения. В JMS эта концепция реализуется с помощью спе­циаль­ных слушателей (listeners), регистрируемых в системе. При возникновении но­вого со­бытия слушатель, закрепленный за данной темой, возбуждается.

Следует отметить, что при испо­льзовании модели «издание - подписка» клиенты JMS могут устанавливать долговременные подписки, позволяющие потребителям отсоединяться и позже снова подключяться и получать сообщения, поступившие во время отключения связи.

 

TopicConnectionFactory

TopicConnectionFactory - управляемый ресурс, получаемый с помощью обращения к JNDI для получения доступа к провайдеру. С помощью его метода createTopicConnection() мы можем получить объект TopicConnection.

 

TopicConnection

TopicConnection – создает подключение к провайдеру. Методы TopicConnection приведены в таблице 2.

 

Таблица 2

Название метода Описание
createTopicSession (boolean, int) Метод возвращает объект TopicSession. Первый логический параметр указывает на то, будет ли сессия помечена как «transacted», второй целочисельный параметр — тип уведомления о доставке
start() Активирует получение сообщений от провайдера
stop() Временно приостанавливает получение сообщений, возобновить которое можно повторным вызовом метода start()
close() Закрывает соединение с провайдером и высвобождает все задействованные ранее ресурсы.

 

TopicSession

TopicSession – однопоточный контекст для получения сообщений. Методы TopicSession приведены в таблице 3.

 

Таблица 3

Название метода Описание
createPublisher(Topic) Возвращает объект TopicPublisher для отправки сообщений в определенную тему
createSubscriber(Topic) Возвращает TopicSubscriber, объект для получения сообщений из определенной темы. Сообщения будут приходить до тех пор, пока существует сам объект.
createDurableSubscriber (Topic, String) Возвращает TopicSubscriber, одновременно именуя подписку с помощью переданного второго параметра. Даже если подписчик неактивен, JMS сохранит их и доставит при первой же активации объекта или создании нового с таким же именем.
unsubscribe(String) Отписывает от темы с заданным именем
commit() Подтверждает все входящие или исходящие сообщения
rollback() Откатывает все входящие или исходящие сообщения
create<тип сообщения> Message(...) Набор методов для создания сообщений определенного типа

 

Topic

Topic представляет собой хранилище сообщений и так же, как и TopicConnectionFac­to­ry, является управляемым объектом.

 

TopicPublisher

TopicPublisher — объект, использующийся для отправки сообщений. Некоторые из основных методов TopicPublisher приведены в таблице 4.

 

 

Таблица 4

Название метода Описание
publish(Message) Публикует указанное сообщение
setDeliveryMode(int) Устанавливает тип доставки сообщения: · DeliveryMode.PERSISTENT — сообщение будет храниться до тех пор, пока не будет принято адресатом · DeliveryMode.NON_PERSISTENT — сообщение будет автомати­чески удалено, если адресат недоступен в момент доставки.
setPriority(int) Устанавливает приоритет отправленного сообщения. В качестве параметра можно передать целое число в диапазоне от 0…9.
setTimeToLive(long) Устанавливает время жизни отправляемого сообщения.

TopicSubscriber

TopicSubscriber используется для получения сообщений. Некоторые из основных методов TopicSubscriber приведены в таблице 5.

Таблица 5

Название метода Описание
receive() Получает очередное сообщение. Метод блокируется до тех пор, пока сообщение не будет получено.
receive(long) Получает очередное сообщение. При этом указывается интервал вре­мени ожидания. Если сообщение не приходит в течение указанного количества миллисекунд, метод возвращает null.
receiveNoWait() Получает очередное сообщение. Если оно сразу же не было доступно, то метод просто завершает работу, ничего не возвращая.
setMessageListener (MessageListener) Устанавливает слушателя (MessageListener), который получает сообщения асинхронно.

 

Отметим также, что существуют прочная (durable) и непрочная (non-durable) подпис­ки. Прочная подписка (рисунок 7) гарантирует, что подписчик получит все сообщения, по­сланные в теме, а непрочная подписка не дает никаких гарантий насчет тех сообщений, которые были отосланы в момент, когда клиент был отключен от темы (рисунок 8).

 

 

Рисунок 7 - Прочная подписка. Все сообщения будут обработаны

Рисунок 8 - Непрочная подписка (сообщения M3 и M4 не будут обработаны)

Модель передаче сообщений «точка - точка»

Модель передаче сообщений «точка - точка » (point to point) (рисунок 9) определена в пакете javax.jms.Queue и служит для реализации обмена сообщени­я­ми между двумя компонентами.

Модель передачи сообщений «точка - точка» предоставляет возможность JMS- клиентам по­сы­лать и принимать сообщения (как синхронно, так и асинхронно) через виртуальные каналы, называемые очередями (queues). Модель основывается на методе опроса, при котором сооб­ще­ния явно запрашиваются (считываются) JMS- клиентом из очереди. Несмотря на то, что чтение из очереди могут осуществлять несколько JMS- клиентов, каждое сообщение будет прочи­тано то­лько единожды – JMS- провайдер JMS это гарантирует.

 

 

Рисунок 9 - Модель взаимодействия «точка - точка»

 

QueueConnectionFactory

QueueConnectionFactory – управляемый объект, получаемый из JNDI для создания подключения к провайдеру. QueueConnectionFactory содержит метод генерации createQue­ue­Connection(), возвращающий объект QueueConnection.

 

QueueConnection

QueueConnection представляет активное подключение к провайдеру. Некоторые из ме­тодов, присущих QueueConnection, перечислены в таблице 6.

Таблица 6

Название метода Описание
createQueueSession (boolean, int) Метод возвращает объект QueueSession. Первый логический параметр указывает на то, будет ли сессия помечана как «transacted», второй целочисельный параметр — тип уведомления о доставке сообщения
start() Активирует получение сообщений от провайдера
stop() Временно приостанавливает получение сообщений, возобновить которое можно повторным вызовом метода start()
close() Закрывает соединение с провайдером и высвобождает все задейство­ванные ранее ресурсы.

 

QueueSession

QueueSession — однопоточный контекст для отсылки и приема сообщений. Методы QueueSession приведены в таблице 7.

Таблица 7

Название метода Описание
createSender(Queue) Возвращает объект QueueSender, служащий для передачи сообщений в определенное хранилище (в данном случае, представленное в виде очереди)
createReceiver(Queue) Возвращает объект QueueReceiver, служащий для приема сообщений из определенного хранилища (в данном случае, представ­ленного в виде очереди)
createBrowser(Queue) Возвращает объект QueueBrowser, служащий для тех же целей, что и QueueReceiver
commit() Подтверждает все входящие или исходящие сообщения
rollback() Откатывает все входящие или исходящие сообщения
create<тип сообщения> Message(...) Набор методов для создания сообщений определенного типа

Queue

Queue инкапсулирует хранилище сообщений. Это управляемый объект, доступ к которому можно получить посредством JNDI.

 

QueueSender

QueueSender – объект, используемый для посылки сообщений. Методы QueueSender приведены в таблице 8.

Таблица 8

Название метода Описание
send(Message) Отсылает указанное сообщение
setDeliveryMode(int) Устанавливает тип доставки сообщения: · DeliveryMode.PERSISTENT — сообщение будет храниться до тех пор, пока не будет принято адресатом · DeliveryMode.NON_PERSISTENT — сообщение будет автоматически удалено, если адресат недоступен в момент доставки.
setPriority(int) Устанавливает приоритет отправленного сообщения. В качестве параметра можно передать целое число в диапазоне от 0…9
setTimeToLive(long) Устанавливает время жизни отправляемого сообщения.

 

 

QueueReceiver

QueueReceiver служит для получения сообщений из очереди. Методы QueueReceiver приведены в таблице 9.

Таблица 9

Название метода Описание
receive() Получает очередное доставленное сообщение. Метод блокируется до тех пор, пока сообщение не будет получено.
receive(long) Получает очередное сообщение. При этом указывается интервал вре­мени ожидания. Если сообщение не приходит в течение указанного количества миллисекунд, метод возвращает null.
receiveNoWait() Получает очередное сообщение. Если оно сразу же не было доступно, то метод просто завершает работу, ничего не возвращая.
setMessageListener (MessageListener) Устанавливает слушателя (MessageListener), который получает сооб­щения асинхронно.

 

QueueBrowser

При использовании QueueReceiver для получения сообщений, сообщения удаляются по мере своей обработки. В отличие от QueueReceiver, QueueBrowser просматривает сообщения в очереди, однако не удаляет их. Для этого существует метод getEnumeration(), который возвращает перечисление java.util.Enumeration, которое может быть использовано для про­смотра сообщений в очереди.

 

MessageListener

MessageListener — интерфейс с единственным методом – onMessage(Message), - кото­рый обеспечивает асинхронный прием и обработку сообщений. Интерфейс должен быть реа­лизован клиентским классом, объекты которого могут передаваться в метод setMessageListe­ner(MessageListener) объектов QueueReceiver. Как только сообщение приходит в очередь, вызывается метод onMessage(Message).

Объекты MessageListener используются в обеих моделях передачи сообщений.

 

1.4 Схема применения JMS

 

Схема применения JMS API предполагает выполнение разработчиком последовательности шагов, описанной далее.

Любой компонент, использующий JMS, прежде всего, должен создать соединение с JMS -провайдером - собственно системой, обеспечивающей всю функциональности управле­ния сообщениями. Для этого используется специальная фабрика объектов ConnectionFac­tory. ConnectionFactory на самом деле является интерфейсом, который наследуют другие интерфейсы: QueueConnectionFactory, TopicConnectionFactory, XAQueueConnectionFactory и XATopicConnectionFactory; разработчик имеет дело именно с ними.

Провайдеры MOM значительно отличаются в своих механизмах и техниках обработки сообщений. Чтобы сохранять переносимость (портируемость) JMS- приложений, объекты, реализующие JMS- интерфейсы, могут быть изолированы от конкретной реализации провайдера с помощью технологии JNDI. Забегая наперед, следует сказать, что для получения доступа к тому самому буферу сообщений необходимы два основных объекта: менеджер подключения к «хранилищу» сообщений и хранилище сообщений. Это управляемые объекты, ссылки на которые поме­щаются в область имен JNDI.

Основные интерфейсы для работы с JMS:

- ConnectionFactory - менеджер подключения, использующийся для установки соеди­нения с хранилищем сообщений и с системой обмена сообщениями в целом;

- Destination - ссылка на хранилище; используется JMS - клиентом для определения ресурса для отправки и приема сообщений; это либо очередь, либо тема в зависимости от используемой модели передачи сообщений. Как и ConnectionFactory, Destination связывается с деревом JNDI.

JMS определяет набор высокоуровневых интерфейсов, инкапсулирующих различные концепции работы с сообщениями:

- ConnectionFactory - управляемый объект, служащий для получения Connection;

- Connection – соединение с системой управления сообщениями;

- Destination - буфер для отправки и получения сообщений;

- Session - однопоточный контекст для посылки и приема сообщений;

- MessageProducer - объект, используемый для посылки сообщения;

- MessageConsumer - объект, используемый для приема сообщения.

Таблица 10 описывает базовые интерфейсы и их реализации для модели «издание - подписка» и «точка - точка».

Для того чтобы получить доступ к ConnectionFactory, Java-программа должна извлечь соответствующую ссылку из JNDI.

Таблица 10

Базовый интерфейс Реализация для модели «издание - подписка» Реализация для модели «точка – точка»
ConnectionFactory TopicConnectionFactory QueueConnectionFactory
Connection TopicConnection QueueConnection
Destination Topic Queue
MessageProducer TopicPublisher QueueSender
MessageConsumer TopicSubscriber QueueReceiver, QueueBrowser

 

С использованием механизма аннотаций соответст­вующий код будет иметь следующий вид:

@>Resource(mappedName="jms/ConnectionFactory") private static ConnectionFactory connectionFactory;

 

Указанный фрагмент кода извлекает ресурс с JNDI-именем jms/ConnectionFactory и связывает его с переменной connectionFactory.

Естественно, что перед первым применением фабрика объектов ConnectionFactory должна быть создана командой:

asadmin.bat create-jms-resource --user admin --passwordfile admin-password.txt --host localhost --port 4848 --restype javax.jms.ConnectionFactory --enabled=true jms/ConnectionFactory

 

, которая создает ресурс типа javax.jms.ConnectionFactory с именем jms/Connection­Fac­to­ry.

 

Следующим шагом является создание соединения с JMS -провайдером. Соответствую­щий код будет выглядеть следующим образом:

Connection connection = connectionFactory.createConnection();

 

Следует отметить, что соединение должно быть закрыто методом connection.close() после того, как оно перестает испо­льзо­ваться.

После того как соединение создано, могут быть созданы виртуальные каналы, в рамках кото­рых будет осуществляться передача сообщений. Существуют два типа таких каналов: очередь (queue) и тема (topic). Создание виртуального канала требует нали­чия соответству­ющего пункта назначения (destination), созданного в JNDI. Таким образом, прежде чем программа сможет задействовать очередь или тему, соответствующий объект должен быть создан в JMS - провайдере. Для Sun Application Server соответствующая команда будет иметь вид:

 

asadmin.bat create-jms-resource --user admin --passwordfile admin-password.txt --host localhost --port 4848 --restype javax.jms.Queue --enabled=true --property Name=PhysicalQueue jms/Queue

 

, где restype указывает тип объекта (в данном случае это javax.jms.Queue),а параметр pro­perty задает JNDI-имя объекта (jms/Queue).

Для того, чтобы в программе получить ссылку на соответствующий объект, можно использо­вать код вида:

 

@>Resource(mappedName="jms/Queue") private static Queue queue;

 

для очереди, или, если нужно получить ссылку на объект типа тема:

@>Resource(mappedName="jms/Topic") private static Topic topic;

 

Еще раз обратим внимание на то, что объекты с именами jms/Queue или jms/Topic должны быть предварительно созданы.

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: