Java Platform, Enterprise Edition (Java EE) 8
Учебник по Java EE

Назад Вперёд Содержание

Программная модель JMS API

Основные строительные блоки приложения JMS:

  • Администрируемые объекты: фабрики и направления связи

  • Соединения

  • Сессии

  • Объекты JMSContext, объединяющие соединение и сессию в одном объекте

  • Производители сообщений

  • Потребители сообщений

  • Сообщения

Рисунок 48-5 показывает, как все эти объекты сочетаются друг с другом в клиентском приложении JMS.

Рисунок 48-5. Программная модель JMS API

Диаграмма программной модели JMS API: фабрика соединений, JMSContext, соединение, сессия, производитель сообщений, потребитель сообщений, сообщения и пункты назначения

JMS также предоставляет браузеры очереди — объекты, которые позволяют приложению просматривать сообщения в очереди.

В этом разделе кратко описаны все эти объекты и приведены примеры команд и фрагменты кода, которые показывают, как создавать и использовать объекты. В последнем подразделе кратко описывается обработка исключений JMS API.

Примеры, которые показывают, как объединить все эти объекты в приложениях, приведены в главе 49 «Примеры JMS», начинающейся с написания простых приложений JMS. Для получения дополнительной информации см. документацию JMS API, входящей в состав документации API Java EE.

Администрируемые объекты JMS

Две части приложения JMS — пункты назначения и фабрики соединений — обычно обслуживаются административно, а не программно. Технология, лежащая в основе этих объектов, вероятно, будет сильно отличаться от одной реализации JMS API к другой. Следовательно, управление этими объектами относится к административным задачам, которые варьируются от поставщика к поставщику.

Клиенты JMS получают доступ к администрируемым объектам через переносимые интерфейсы, поэтому клиентское приложение может работать практически без изменений в нескольких реализациях JMS API. Обычно администратор настраивает администрируемые объекты в пространстве имён JNDI, а клиенты JMS затем получают к ним доступ с помощью инъецирования.

Используя GlassFish Server, вы можете использовать команду asadmin create-jms-resource или Консоль администрирования для создания администрируемых объектов JMS в форме ресурсов коннектора. Вы также можете указать ресурсы в файле с именем glassfish-resources.xml, который можно связать с приложением.

В среде IDE NetBeans имеется мастер, позволяющий создавать ресурсы JMS для сервера GlassFish. Подробности смотрите в Административное создание объектов JMS.

Спецификация платформы Java EE позволяет разработчику создавать администрируемые объекты с использованием аннотаций или элементов дескриптора развёртывания. Объекты, созданные таким образом, специфичны для приложения, для которого они созданы. Подробности смотрите в Создание ресурсов для приложений Java EE. Определения в дескрипторе развёртывания переопределяют указанные в аннотациях.

Фабрики соединений JMS

Фабрика соединений — это объект, который клиент использует для создания соединения с провайдером. Фабрика соединений содержит набор параметров конфигурации соединения, которые были определены администратором. Каждая фабрика соединений является объектом интерфейса ConnectionFactory, QueueConnectionFactory или TopicConnectionFactory. Чтобы узнать, как создавать фабрики соединений, см. Административное создание объектов JMS.

В начале клиентской программы JMS инъецируйте ресурс фабрики соединений в объект ConnectionFactory. Сервер Java EE должен предоставить фабрике соединений JMS логическое имя JNDI java:comp/DefaultJMSConnectionFactory. Фактическое имя JNDI будет зависеть от реализации.

Например, следующий фрагмент кода ищет фабрику соединений JMS по умолчанию и назначает её объекту ConnectionFactory:

@Resource(lookup = "java:comp/DefaultJMSConnectionFactory")
private static ConnectionFactory connectionFactory;

Пункты назначения JMS

Пункт назначения — это объект, который клиент использует для указания цели отправляемых сообщений и источника получаемых сообщений. При обмене сообщениями типа "точка-точка" пункты назначения называются очередями. При обмене "публикация-подписка" — темами. Приложение JMS может использовать несколько очередей или тем (или и то и другое). Чтобы узнать, как создавать ресурсы пунктов назначения, см. Административное создание объектов JMS.

Чтобы создать пункт назначения с помощью сервера GlassFish, создайте ресурс пункта назначения JMS и укажите для него имя JNDI.

В реализации Jakarta Messaging сервера GlassFish каждый пункт назначения ссылается на физическое назначение. Физический пункт назначения может быть создан явным образом. Если это не сделано, сервер приложений создаст его, когда это необходимо, и удалит его вместе с соответствующим ресурсом.

Помимо инъецирования ресурса фабрики соединений в клиентскую программу, обычно инъецируется и пункт назначения. В отличие от фабрик соединений, пункты назначения отличаются для способов обмена сообщениями "точка-точка" и "публикация-подписка". Чтобы создать приложение, позволяющее использовать один и тот же код как для тем, так и для очередей, вы назначаете пункт назначения для объекта Destination.

Следующий код указывает два ресурса: очередь и тему. Имена ресурсов отображаются на целевые ресурсы, созданные в пространстве имён JNDI:

@Resource(lookup = "jms/MyQueue")
private static Queue queue;

@Resource(lookup = "jms/MyTopic")
private static Topic topic;

В приложении Java EE администрируемые объекты JMS обычно помещаются в субконтекст именования jms.

С помощью общих интерфейсов вы можете смешивать или сопоставлять фабрики соединений и пункты назначения. То есть, в дополнение к использованию интерфейса ConnectionFactory, вы можете инъецировать ресурс QueueConnectionFactory и использовать его с Topic, а также можете добавить TopicConnectionFactory и использовать его с Queue. Поведение приложения будет зависеть от типа используемого пункта назначения, а не от типа используемой фабрики соединений.

Соединения

Соединение инкапсулирует виртуальное соединение с провайдером JMS. Например, соединение может представлять собой открытый сокет TCP/IP между клиентом и демоном службы провайдера. Соединение используется для создания одной или нескольких сессий.

Замечание:

В платформе Java EE возможность создания нескольких сессий из одного подключения ограничена клиентскими приложениями. В веб-компонентах и ​​компонентах Enterprise-бина соединение может создавать не более одной сессии.

Обычно соедиинение создаётся при создании объекта JMSContext. Смотрите Объекты JMSContext для подробностей.

Сессии

Сессия — это однопоточный контекст для отправки и получения сообщений.

Обычно сессия (а также соединение) создаётся вместе с созданием объекта JMSContext. Смотрите Объекты JMSContext для подробностей. Сессии используются для создания производителей сообщений, потребителей сообщений, собственно сообщений, браузеров очередей и вре́менных пунктов назначения.

Сессии сериализуют выполнение слушателей сообщений. Подробности см. в разделе Слушатели сообщений JMS.

Сессия обеспечивает транзакционный контекст, с помощью которого можно сгруппировать набор отправлений и приёмов сообщений в атомарную операцию. Подробнее см. Использование локальных транзакций JMS.

Объекты JMSContext

Объект JMSContext содержит в себе соединение и сессию. То есть он обеспечивает как активное соединение с провайдером JMS, так и однопоточный контекст для отправки и получения сообщений.

JMSContext используется для создания следующих объектов:

Можно создать JMSContext в блоке try-with-resources.

Чтобы создать JMSContext, вызовите метод createContext фабрики соединений:

JMSContext context = connectionFactory.createContext();

При вызове без аргументов из клиентского приложения или клиента Java SE или из веб-контейнера Java EE или контейнера EJB, когда не выполняется активная транзакция JTA, метод createContext создаёт нетранзакционную сессию с режимом подтверждения JMSContext.AUTO_ACKNOWLEDGE. При вызове без аргументов из веб-контейнера или контейнера EJB, когда выполняется активная транзакция JTA, метод createContext создаёт транзакционную сессию. Для получения информации о том, как транзакции JMS работают в приложениях Java EE, см. Использование JMS API в приложениях Java EE.

Чтобы создать транзакционную сессию в клиентском приложении или клиенте Java SE, также можно вызвать метод createContext с аргументом JMSContext.SESSION_TRANSACTED:

JMSContext context =
        connectionFactory.createContext(JMSContext.SESSION_TRANSACTED);

Сессия использует локальные транзакции. Подробнее смотрите Использование локальных транзакций JMS.

Кроме того, можно указать режим подтверждения не по умолчанию. Смотрите Управление подтверждением сообщения для получения дополнительной информации.

При использовании JMSContext доставка сообщений начинается при создании потребителя. Смотрите Потребители сообщений JMS для получения дополнительной информации.

Если JMSContext создаётся в блоке try-with-resources, не требуется закрывать его явно. Он будет закрыт, когда закончится блок try. Убедитесь, что приложение выполняет все действия JMS в блоке try-with-resources. Если блок try-with-resources не используется, нужно вызвать метод close в JMSContext, чтобы закрыть соединение, когда приложение закончит свою работу.

Производители сообщений JMS

Источник сообщений — это объект, который создаётся JMSContext-ом или сессией и используется для отправки сообщений в пункт назначения. Источник сообщений, созданный JMSContext, реализует интерфейс JMSProducer. Вы можете создать его следующим образом:

try (JMSContext context = connectionFactory.createContext();) {
    JMSProducer producer = context.createProducer();
    ...

Однако JMSProducer — это легковесный объект, который не потребляет значительных ресурсов. По этой причине не нужно сохранять JMSProducer в переменной. Его можно создавать новый каждый раз, когда возникает необходимость отправить сообщение. Отправляйте сообщения в определённый пункт назначения с помощью метода send. Например:

context.createProducer().send(dest, message);

Вы можете создать сообщение в переменной перед отправкой, как показано здесь, или создать его с помощью вызова send. Дополнительная информация приведена в разделе Сообщения JMS .

Потребители сообщений JMS

Потребитель сообщений — это объект, который создаётся с помощью JMSContext или сессией и используется для получения сообщений, отправленных в пункт назначения. Источник сообщений, созданный JMSContext, реализует интерфейс JMSConsumer. Самый простой способ создать получателя сообщения — использовать метод JMSContext.createConsumer:

try (JMSContext context = connectionFactory.createContext();) {
    JMSConsumer consumer = context.createConsumer(dest);
    ...

Потребитель сообщений позволяет клиенту JMS регистрироваться в пункте назначения у провайдера JMS. Провайдер JMS управляет доставкой сообщений из пункта назначения зарегистрированным в этом пункте пользователям.

Когда для создания получателя сообщения используется JMSContext, доставка сообщения начинается сразу после его создания. Это поведение может быть отключено вызовом setAutoStart(false) при создании JMSContext, а затем явным вызовом метода start для начала доставки сообщений. Если нужно временно остановить доставку сообщений без закрытия соединения, можно вызвать метод stop. Для возобновления доставки сообщений вызовите start.

Метод receive используется для синхронного получения сообщения. Этот метод может быть использован в любое время после создания потребителя.

Если не указать аргументов или указать аргумент 0, метод блокируется на неопределённый срок до прибытия сообщения:

Message m = consumer.receive();
Message m = consumer.receive(0);

Для простого клиента это может не иметь значения. Но если возможно, что сообщение может быть недоступно, используйте синхронный приём с тайм-аутом: вызовите метод receive с аргументом тайм-аута, большим, чем 0. Одна секунда является рекомендуемым значением времени ожидания:

Message m = consumer.receive(1000); // тайм-аут 1 секунда

Чтобы включить асинхронную доставку сообщений от клиентского приложения или клиента Java SE, используйте слушатель сообщений, как описано в следующем разделе.

Для создания долговременной подписки на темы может использоваться метод JMSContext.createDurableConsumer. Этот метод применим только к темам. Для получения дополнительной информации см. Создание долговременных подписок. Для тем также могут создаваться общие потребители. См. Создание общих подписок.

Слушатели сообщений JMS

Слушатель сообщений — это объект, который действует как асинхронный обработчик событий для сообщений. Этот объект реализует интерфейс MessageListener, содержащий метод onMessage. В методе onMessage определяются действия, которые должны быть выполнены при получении сообщения.

Используя метод setMessageListener, в клиентском приложении или клиенте Java SE регистрируется слушатель сообщений с определённым потребителем сообщений. Например, класс с именем Listener, реализующий интерфейс MessageListener, может быть зарегистрирован как слушатель сообщений следующим образом:

Listener myListener = new Listener();
consumer.setMessageListener(myListener);

Когда начинается доставка сообщения, провайдер JMS автоматически вызывает метод слушателя сообщения onMessage при каждой доставке сообщения. Метод onMessage принимает один аргумент типа Message, который ваша реализация метода может при необходимости привести к другому подтипу сообщения (см. Тело сообщения) ,

В веб-контейнере Java EE или контейнере EJB управляемые сообщениями компоненты используются для асинхронной доставки сообщений. Управляемый сообщениями компонент также реализует интерфейс MessageListener и содержит метод onMessage. Для получения дополнительной информации см. Использование управляемых сообщениями бинов для асинхронного получения сообщений.

Ваш метод onMessage должен обрабатывать все исключения. Выбрасывание RuntimeException считается ошибкой программирования.

Простой пример использования слушателя сообщений см. в разделе Использование слушателя сообщений для асинхронной доставки сообщений. Глава 49 «Примеры JMS», содержит ещё несколько примеров слушателей сообщений и управляемых сообщениями бинов.

Селекторы сообщений JMS

Если приложению для обмена сообщениями необходимо фильтровать полученные сообщения, может использоваться селектор сообщений JMS, позволяющий получателю сообщений указать интересующий его пункт назначения. Селекторы сообщений передают работу по фильтрации сообщений провайдеру JMS, а не приложению. Приложение, использующее селектор сообщений, см. в разделе Отправка сообщений из сессионного компонента в MDB.

Селектор сообщений — выражение типа String. Синтаксис этого выражения основан на подмножестве синтаксиса условного выражения SQL92. Селектор сообщений в этом примере выбирает любое сообщение со свойством NewsType, для которого установлено значение 'Sports' или 'Opinion':

NewsType = 'Sports' OR NewsType = 'Opinion'

Методы createConsumer и createDurableConsumer, а также методы для создания общих потребителей позволяют указывать селектор сообщений в качестве аргумента при создании получателя сообщения.

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

Получение сообщений из тем

Семантика получения сообщений из тем более сложна, чем из очередей.

Приложение получает сообщения из темы, создавая подписку на эту тему и получателя на эту подписку. Подписки могут быть или не быть долговременными (durable), быть или не быть общими (shared).

Подписка может рассматриваться как объект внутри самого провайдера JMS, тогда как потребитель является объектом JMS в приложении.

Подписка будет получать копию каждого сообщения, отправляемого в тему после создания подписки, если не указан селектор сообщений. Если селектор сообщений указан, в подписку будут добавлены только те сообщения, свойства которых соответствуют селектору сообщений.

Подписки, не являющиеся общими, ограничены одним потребителем. В этом случае все сообщения в подписке доставляются этому потребителю. Общие подписки позволяют доставку нескольким потребителям. В этом случае каждое сообщение в подписке доставляется только одному потребителю. JMS не определяет, как сообщения распределяются между несколькими пользователями по одной и той же подписке.

Подписки могут быть или не быть долговременными.

Подписка, не являющаяся долговременной, существует только до тех пор, пока в ней есть активный потребитель. Это означает, что любые сообщения, отправленные в тему, будут добавлены в подписку, только если потребитель существует и не закрыт.

Подписка, не являющаяся долговременной, может быть как быть общей, так и не быть ею.

  • Подписки, не являющиеся долговременными и общими, не имеют имени и с ними может быть связан только один объект-потребитель. Они создаются автоматически при создании объекта-потребителя. Они не сохраняются и автоматически удаляются при закрытии объекта-потребителя.

    Метод JMSContext.createConsumer создаёт получателя для подписки, не являющейся долговременной общей, если в качестве пункта назначения указана тема.

  • Общая подписка, не являющаяся долговременной, идентифицируется по имени и необязательному идентификатору клиента и может иметь несколько объектов-потребителей, получающих от неё сообщения. Она создаётся автоматически при создании первого объекта-потребителя. Она не сохраняется и удаляется автоматически при закрытии последнего объекта-потребителя. Смотрите Создание общих подписок для получения дополнительной информации.

За счёт более высоких накладных расходов подписка может быть долговременной. Долговременная подписка сохраняется и продолжает накапливать сообщения до тех пор, пока не будет явно удалена, даже если нет объектов-потребителей, получающих сообщения от неё. Подробности смотрите в Создание долговременных подписок.

Создание долговременных подписок

Чтобы гарантировать, что приложение "публикация-подписка" получает все отправленные сообщения, используйте долговременные подписки для потребителей этой темы.

Как и подписка, не являющаяся долговременной, долговременная подписка может быть или не быть общей.

  • Долговременная подписка, не являющаяся общей, идентифицируется по имени и идентификатору клиента (который должен быть установлен) и может иметь только один объект-потребитель, связанный с ней.

  • Общая долговременная подписка идентифицируется по имени и необязательному идентификатору клиента и может иметь несколько объектов-потребителей, получающих от неё сообщения.

Долговременная подписка будет называться неактивной, если она существует, но с ней в настоящее время не связан ни один незакрытый потребитель.

Вы можете использовать метод JMSContext.createDurableConsumer, чтобы создать получателя для долговременной подписки, не являющейся общей. У такой подписки одновременно может быть только один активный потребитель.

Потребитель идентифицирует долговременную подписку, из которой он получает сообщения, указав уникальный идентификатор, хранимый провайдером JMS. Последующие объекты-потребители, имеющие одинаковые идентификационные данные, возобновляют подписку в том состоянии, в котором она была оставлена ​​предыдущим потребителем. Если у долговременной подписки нет активного потребителя, провайдер JMS сохраняет сообщения подписки до тех пор, пока они не будут получены подпиской или пока не истечёт срок их действия.

Уникальность долговременной подписки, не являющейся общей, достигается сочетанием следующих частей:

  • Идентификатор клиента для соединения

  • Тема и название подписки

Вы можете установить идентификатор клиента административно для конкретной фабрики соединений, используя либо командную строку, либо Консоль администрирования. (В клиентском приложении или клиенте Java SE вместо этого вы можете вызвать JMSContext.setClientID.)

После использования этой фабрики соединений для создания JMSContext вызывается метод createDurableConsumer с двумя аргументами: темой и именем подписки:

String subName = "MySub";
JMSConsumer consumer = context.createDurableConsumer(myTopic, subName);

Подписка становится активной после создания потребителя. Позже потребитель может быть закрыт:

consumer.close();

Провайдер JMS хранит сообщения, отправленные в тему, так же, как и сообщения, отправленные в очередь. Если программа или другое приложение вызывает createDurableConsumer с использованием той же фабрики соединений и её идентификатора клиента, той же темой и тем же именем подписки, тогда подписка повторно активируется, и провайдер JMS доставляет сообщения, отправленные за период неактивности подписки.

Для удаления долговременной подписки, сначала закройте получателя, затем вызовите метод unsubscribe с именем подписки в качестве аргумента:

consumer.close();
context.unsubscribe(subName);

Метод unsubscribe удаляет состояние, которое провайдер поддерживает для подписки.

Рисунок 48-6 и рисунок 48-7 показывают разницу между долговременной подпиской и подпиской, не являющейся долговременной. При обычной (не долговременной) подписке потребитель и подписка начинаются и заканчиваются в одной точке и фактически идентичны. Когда потребитель закрыт, подписка также заканчивается. Здесь create обозначает вызов JMSContext.createConsumer с аргументом Topic, а close обозначает вызов JMSConsumer.close. Любые сообщения, отправленные в тему между временем первого close и временем второго create, не добавляются ни в одну подписку. На рисунке 48-6 потребители получают сообщения M1, M2, M5 и M6, но не получают M3 и M4.

Рис. 48-6. Подписки, не являющиеся длительными, и их потребители

Диаграмма, показывающая сообщения, потерянные при использовании подписок, не являющихся долговременными

При наличии долговременной подписки потребитель может быть закрыт и повторно создан, но подписка продолжает существовать и хранить сообщения до тех пор, пока приложение не вызовет метод unsubscribe. На рис. 48-7 create обозначает вызов JMSContext.createDurableConsumer, close обозначает вызов JMSConsumer.close и unsubscribe означает вызов JMSContext.unsubscribe. Сообщения, отправленные после закрытия первого потребителя, принимаются при создании второго потребителя (по той же долговременной подписке), поэтому даже если сообщения M2, M4 и M5 поступают, когда нет потребителя, они не теряются.

Рис. 48-7. Потребители долговременной подписки

Диаграмма, показывающая сообщения, сохраняемые при использовании долговременных подписок

Общая долговременная подписка позволяет использовать несколько потребителей для получения сообщений из долговременной подписки. Если вы используете общую долговременную подписку, используемой фабрике соединений не требуется идентификатор клиента. Для создания общей долговременной подписки вызовите метод JMSContext.createSharedDurableConsumer, указав тему и имя подписки:

JMSConsumer consumer =
        context.createSharedDurableConsumer(topic, "MakeItLast");

Создание общих подписок

Подписка на тему, созданная методом createConsumer или createDurableConsumer, может иметь только одного потребителя (хотя тема может иметь много). Несколько клиентов, использующих одну и ту же тему, по определению имеют несколько подписок на эту тему, и все клиенты получают все сообщения, отправленные в тему (если только они не фильтруют их с помощью селекторов сообщений).

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

consumer = context.createSharedConsumer(topicName, "SubName");

При общей подписке сообщения будут распределяться между несколькими клиентами, использующими одни и те же тему и имя подписки. Каждое сообщение, отправленное в тему, будет добавлено в каждую подписку (с учётом любых селекторов сообщений), но каждое сообщение, добавленное в подписку, будет доставлено только одному из потребителей этой подписки, поэтому оно будет получено только одним из клиентов. Общая подписка может быть полезна, если вы хотите разделить загрузку сообщений между несколькими потребителями в подписке, а не для того, чтобы только один потребитель в подписке получал каждое сообщение. Эта функция может улучшить масштабируемость клиентских приложений приложений Java EE и Java SE. (Бины, управляемые сообщениями, разделяют работу по обработке сообщений из темы среди нескольких потоков.)

См. Использование общих подписок, не являющихся долговременными для простого примера использования потребителей общих подписок, не являющихся долговременными.

Вы также можете создавать общие долговременные подписки с помощью метода JMSContext.createSharedDurableConsumer. Для получения дополнительной информации см. Создание долговременных подписок.

Сообщения JMS

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

Сообщение JMS может состоять из трёх частей: заголовка, свойств и тела. Обязательным является только заголовок. В следующих разделах описываются эти части.

Полную документацию по заголовку, свойствам и телу сообщений, см. документацию по API интерфейса Message. Список возможных типов сообщений см. в разделе Тело сообщения.

Здесь рассматриваются следующие темы:

Заголовок сообщения

Заголовок сообщения JMS включает несколько предопределённых полей, которые содержат значения, используемые как клиентами, так и поставщиками для идентификации и маршрутизации сообщений. Таблица 48-1 перечисляет и описывает поля заголовка сообщения JMS и значения этих полей. Например, каждое сообщение имеет уникальный идентификатор, который представлен в поле заголовка JMSMessageID. Значение другого поля заголовка, JMSDestination, представляет очередь или тему, в которую отправляется сообщение. Другие поля включают отметку времени и приоритет.

Каждое поле заголовка имеет get- и set- методы, которые описаны в интерфейсе Message. Некоторые поля заголовка предназначены для установки клиентом, но многие устанавливаются автоматически с помощью метода send, который переопределяет значения, установленные клиентом.

Таблица 48-1 Как устанавливаются значения полей заголовка сообщения JMS

Поле заголовка

Описание

Установлен

JMSDestination

Пункт назначения, на который отправляется сообщение

Метод send провайдера JMS

JMSDeliveryMode

Режим доставки, указанный при отправке сообщения (см. Указание персистентности сообщения)

Метод send провайдера JMS

JMSDeliveryTime

Время отправки сообщения плюс задержка доставки, указанная при отправке сообщения (см. Указание задержки доставки

Метод send провайдера JMS

JMSExpiration

Время истечения срока действия сообщения (см. Установка срока действия сообщения)

Метод send провайдера JMS

JMSPriority

Приоритет сообщения (см. Установка приоритета сообщений)

Метод send провайдера JMS

JMSMessageID

Значение, которое однозначно идентифицирует каждое сообщение, отправленное провайдером

Метод send провайдера JMS

JMSTimestamp

Время передачи сообщения провайдеру для отправки

Метод send провайдера JMS

JMSCorrelationID

Значение, которое связывает одно сообщение с другим. Обычно используется значение JMSMessageID

Клиентское приложение

JMSReplyTo

Пункт назначения, куда следует отправлять ответы на сообщение

Клиентское приложение

JMSType

Идентификатор типа, предоставленный клиентским приложением

Клиентское приложение

JMSRedelivered

Является ли сообщение повторно доставленным

JMS-провайдер перед доставкой

Свойства сообщения

Вы можете создавать и устанавливать свойства для сообщений, если вам нужны значения в дополнение к тем, которые указаны в полях заголовка. Вы можете использовать свойства для обеспечения совместимости с другими системами обмена сообщениями или использовать их для создания селекторов сообщений (см. Селекторы сообщений JMS). Пример установки свойства, которое будет использоваться в качестве селектора сообщений, см. в разделе Отправка сообщений из сессионного компонента в MDB.

JMS API предоставляет некоторые предопределённые имена свойств, которые начинаются с JMSX. Провайдер JMS должен реализовать только одно из них — JMSXDeliveryCount (которое указывает количество доставок сообщения). Остальные свойства не обязательны. Использование этих предопределённых свойств, как и кастомных свойств в приложениях не обязательно.

Тело сообщения

JMS API определяет шесть различных типов сообщений. Каждый тип сообщения имеет свойственное ему тело сообщения. Эти типы сообщений позволяют отправлять и получать данные в различных формах. Таблица 48-2 описывает эти типы сообщений.

Таблица 48-2 Типы сообщений JMS

Тип сообщения

Тело содержит

TextMessage

Объект java.lang.String (например, содержимое файла XML).

MapMessage

Набор пар имя-значение с ключами в виде объектов String и значениями в виде примитивных типов Java. Доступ к записям может осуществляться последовательным обходом или произвольно по имени. Порядок записей не определён.

BytesMessage

Поток неинтерпретируемых байтов. Этот тип сообщения предназначен для кодирования тела в соответствии с существующим форматом сообщения.

StreamMessage

Поток примитивных значений Java, заполняемый и читаемый последовательно.

ObjectMessage

Объект Serializable Java.

Message

Отсутствует. Состоит только из заголовка и свойств. Этот тип сообщения полезен, когда тело сообщения не требуется.

JMS API предоставляет методы для создания сообщений каждого типа и для заполнения их содержимого. Например, для создания и отправки TextMessage могут использоваться следующие операторы:

TextMessage message = context.createTextMessage();
message.setText(msg_text);     // msg_text — объект типа String
context.createProducer().send(message);

На стороне потребителя сообщение приходит как обобщённый (generic) объект Message. Затем можно привести объект к соответствующему типу сообщения и использовать специфичные методы для доступа к телу и извлечения содержимого сообщения (а также его заголовков и свойств, если необходимо). Например, могут быть использованы потоковые методы чтения BytesMessage. Для получения тела StreamMessage всегда нужно приводить сообщение к соответствующему типу.

Вместо приведения сообщения к конкретному типу может быть вызван метод getBody у Message с указанием типа сообщения в качестве аргумента. Например, можно извлечь TextMessage как String. В следующем фрагменте кода используется метод getBody:

Message m = consumer.receive();
if (m instanceof TextMessage) {
    String message = m.getBody(String.class);
    System.out.println("Reading message: " + message);
} else {
    // Обработка ошибки или сообщения другого типа
}

JMS API предоставляет удобные методы для создания и получения TextMessage, BytesMessage, MapMessage или ObjectMessage. Например, не нужно переносить строку в TextMessage. Вместо этого можно отправить и получить строку напрямую. Например, можно отправить строку следующим образом:

String message = "This is a message";
context.createProducer().send(dest, message);

Можно получить сообщение, используя метод receiveBody:

String message = receiver.receiveBody(String.class);

Можно использовать метод receiveBody для получения сообщений любого типа, кроме StreamMessage и Message, при условии, что телу сообщения может быть назначен определённый тип.

Пустой Message может быть полезен, если нужно отправить сообщение, которое является сигналом для приложения. Некоторые из примеров в главе 49 «Примеры JMS» отправляют пустое сообщение после отправки серии текстовых сообщений. Например:

context.createProducer().send(dest, context.createMessage());

Затем код потребителя может интерпретировать нетекстовое сообщение как сигнал о том, что все отправленные сообщения уже получены.

В примерах в главе 49 «Примеры JMS» используются сообщения типа TextMessage, MapMessage и Message.

Браузеры очереди JMS

Сообщения, отправленные в очередь, остаются в очереди до их получения получателем сообщений для этой очереди. JMS API предоставляет объект QueueBrowser, который позволяет просматривать сообщения в очереди и отображать значения заголовков для каждого сообщения. Чтобы создать объект QueueBrowser, используйте метод JMSContext.createBrowser. Например:

QueueBrowser browser = context.createBrowser(queue);

См. Просмотр сообщений в очереди для примера использования объекта QueueBrowser.

Метод createBrowser позволяет указать селектор сообщений вторым аргументом при создании QueueBrowser. Для получения информации о селекторах сообщений см. Селекторы сообщений JMS.

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

Обработка исключений JMS

Родительским классом всех проверяемых исключений в JMS API является JMSException. Родительским классом всех непроверяемых исключений в JMS API является JMSRuntimeException.

Общим способом обработки всех исключений, связанных с JMS API, является перехват JMSException и JMSRuntimeException.

Классы JMSException и JMSRuntimeException включают следующие дочерние классы, описанные в документации API:

  • IllegalStateException, IllegalStateRuntimeException

  • InvalidClientIDException, InvalidClientIDRuntimeException

  • InvalidDestinationException, InvalidDestinationRuntimeException

  • InvalidSelectorException, InvalidSelectorRuntimeException

  • JMSSecurityException, JMSSecurityRuntimeException

  • MessageEOFException

  • MessageFormatException, MessageFormatRuntimeException

  • MessageNotReadableException

  • MessageNotWriteableException, MessageNotWriteableRuntimeException

  • ResourceAllocationException, ResourceAllocationRuntimeException

  • TransactionInProgressException, TransactionInProgressRuntimeException

  • TransactionRolledBackException, TransactionRolledBackRuntimeException

Все примеры учебника перехватывают и обрабатывают JMSException или JMSRuntimeException, когда это уместно.


Назад Вперёд Содержание
Логотип Oracle  Copyright © 2017, Oracle и/или её дочерних компаний. Все права защищены. Версия перевода 1.0.5 (Java EE Tutorial — русскоязычная версия)