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

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

Простые приложения JMS

В этом разделе показано, как создавать, упаковывать и запускать простые клиенты JMS, упакованных как клиентские приложения.

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

Обзор простого приложения JMS

Клиенты демонстрируют основные задачи, которые должно выполнять приложение JMS:

  • Создание JMSContext

  • Создание сообщений производителей и потребителей

  • Отправка и получение сообщений

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

Когда пишут JMS-клиент для запуска в приложении Enterprise-бина, используются многие из тех же методов в той же последовательности, что и для клиентского приложения. Тем не менее, есть некоторые существенные различия. Использование JMS API в приложениях Java EE описывает эти различия, и в этой главе приведены примеры, иллюстрирующие их.

Примеры для этого раздела находятся в каталоге tut-install/examples/jms/simple/ в следующих подкаталогах:

producer/
synchconsumer/
asynchconsumer/
messagebrowser/
clientackconsumer/

Перед запуском примеров необходимо запустить сервер GlassFish и административно создать некоторые объекты.

Запуск провайдера JMS

В GlassFish Server JMS-провайдером является сам GlassFish Server. Запустите сервер, как описано в Запуск и остановка сервера GlassFish.

Административное создание объектов JMS

В этом примере используются следующие администрируемые объекты JMS:

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

  • Два ресурса пунктов назначения: тема и очередь

Перед запуском приложений можно использовать команду asadmin add-resources для создания необходимых ресурсов JMS, указав в качестве аргумента файл glassfish-resources.xml. Этот файл может быть создан в любом проекте с использованием IDE NetBeans, хотя он также может быть создан вручную. Файл для необходимых ресурсов находится в каталоге jms/simple/seller/src/main/setup/.

В примерах JMS используется фабрика соединений с именем поиска JNDI java:comp/DefaultJMSConnectionFactory, предустановленная на сервере GlassFish.

Также может быть использована команда asadmin create-jms-resource для создания ресурсов, команда asadmin list-jms-resources для отображения их имён и команда asadmin delete-jms-resource для их удаления.

Создание ресурсов для простых примеров

Файл glassfish-resources.xml в одном из проектов Maven может создать все ресурсы, необходимые для простых примеров.

  1. Удостоверьтесь, чтобы GlassFish Server был запущен (см. Запуск и остановка сервера GlassFish).

  2. В командном окне перейдите к примеру Producer.

    cd tut-install/jms/simple/producer
  3. Создайте ресурсы командой asadmin add-resources:

    asadmin add-resources src/main/setup/glassfish-resources.xml
  4. Проверьте создание ресурсов:

    asadmin list-jms-resources

    Команда перечисляет два пункта назначения и фабрику соединений, указанные в файле glassfish-resources.xml в дополнение к фабрике соединений платформы по умолчанию:

    jms/MyQueue
    jms/MyTopic
    jms/__defaultConnectionFactory
    Command list-jms-resources executed successfully.

    На сервере GlassFish ресурсу Java EE java:comp/DefaultJMSConnectionFactory соответствует фабрика соединений jms/__defaultConnectionFactory.

Сборка всех простых примеров

Чтобы запустить простые примеры с использованием сервера GlassFish, упакуйте каждый пример в файл JAR клиентского приложения. JAR-файл клиентского приложения требует файл манифеста, расположенный в каталоге src/main/java/META-INF/ каждого примера вместе с файлом .class.

Файл pom.xml каждого примера определяет плагин, который создаёт JAR-файл приложения-клиента. Вы можете создавать примеры, используя IDE NetBeans или Maven.

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

Сборка всех простых примеров в IDE NetBeans

  1. В меню «Файл» выберите «Открыть проект».

  2. В диалоговом окне «Открыть проект» перейдите к:

    tut-install/examples/jms
  3. Разверните узел jms и выберите каталог simple.

  4. Нажмите Открыть проект, чтобы открыть все простые примеры.

  5. На вкладке «Проекты» кликните правой кнопкой мыши проект simple и выберите «Сборка», чтобы собрать все примеры.

    Эта команда помещает файлы JAR клиентских приложений в каталоги target примеров.

Сборка всех простых примеров, используя Maven

  1. В окне терминала перейдите в каталог simple:

    cd tut-install/jms/simple/
  2. Введите следующую команду, чтобы собрать все проекты:

    mvn install

    Эта команда помещает файлы JAR клиентских приложений в каталоги target примеров.

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

В этом разделе описывается, как использовать клиент для отправки сообщений. Клиент Producer.java будет отправлять сообщения во всех этих примерах.

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

Основные шаги, выполненные в примере

Основные шаги, выполняемые в этом примере, следующие.

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

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

  3. Создайте JMSContext, а затем отправьте указанное количество текстовых сообщений в виде строк, как описано в Тело сообщения.

  4. Последним отправьте сообщение типа Message, чтобы указать, что потребитель не должен ожидать дальнейших сообщений.

  5. Отловите и обработайте все возникшие исключения.

Клиент Producer.java

Отправляющий клиент Producer.java выполняет следующие шаги.

  1. Инъецирует ресурсы фабрики соединений, очереди и темы:

    @Resource(lookup = "java:comp/DefaultJMSConnectionFactory")
    private static ConnectionFactory connectionFactory;
    @Resource(lookup = "jms/MyQueue")
    private static Queue queue;
    @Resource(lookup = "jms/MyTopic")
    private static Topic topic;
  2. Извлекает и проверяет аргументы командной строки, которые определяют тип назначения и количество аргументов:

    final int NUM_MSGS;
    String destType = args[0];
    System.out.println("Destination type is " + destType);
    if ( ! ( destType.equals("queue") || destType.equals("topic") ) ) {
        System.err.println("Argument must be \"queue\" or " + "\"topic\"");
        System.exit(1);
    }
    if (args.length == 2){
        NUM_MSGS = (new Integer(args[1])).intValue();
    } else {
        NUM_MSGS = 1;
    }
  3. Назначает очередь или тему пунктом назначения в зависимости от указанного типа пункта назначения:

    Destination dest = null;
    try {
        if (destType.equals("queue")) {
            dest = (Destination) queue;
        } else {
            dest = (Destination) topic;
        }
    } catch (Exception e) {
        System.err.println("Error setting destination: " + e.toString());
        System.exit(1);
    }
  4. В блоке try-with-resources создаёт JMSContext:

    try (JMSContext context = connectionFactory.createContext();) {
  5. Устанавливает счётчик сообщений равным нулю, затем создаёт JMSProducer, отправляет одно или несколько сообщений в пункт назначения и увеличивает счётчик. Сообщения в виде строк имеют тип сообщения TextMessage:

        int count = 0;
        for (int i = 0; i < NUM_MSGS; i++) {
            String message = "This is message " + (i + 1)
                    + " from producer";
            // Закомментируйте следующие строки чтобы предотвратить множественную отправку сообщений
            System.out.println("Sending message: " + message);
            context.createProducer().send(dest, message);
            count += 1;
        }
        System.out.println("Text messages sent: " + count);
  6. Посылает пустое сообщение-сигнал для обозначения завершения потока сообщений:

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

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

  7. Ловит и обрабатывает все возможные исключения. Конец блока try-with-resources автоматически закрывает JMSContext:

    } catch (Exception e) {
        System.err.println("Exception occurred: " + e.toString());
        System.exit(1);
    }
    System.exit(0);

Запуск клиента Producer

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

В этом примере клиент используется для отправки трёх сообщений в очередь.

  1. Убедитесь, что сервер GlassFish был запущен (см. Запуск и остановка сервера GlassFish) и созданы ресурсы и простые примеры JMS (см. Административное создание объектов JMS и Создание всех простых примеров).

  2. В окне терминала перейдите в каталог producer:

    cd producer
  3. Запустите программу Producer, отправив три сообщения в очередь:

    appclient -client target/producer.jar queue 3

    Вывод программы выглядит следующим образом (вместе с дополнительным выводом):

    Destination type is queue
    Sending message: This is message 1 from producer
    Sending message: This is message 2 from producer
    Sending message: This is message 3 from producer
    Text messages sent: 3

    Сообщения теперь находятся в очереди, ожидая получения.

    Замечание:

    Запуск клиентских приложений и выполнение команды может занять много времени.

Синхронное получение сообщений

В этом разделе описывается принимающий клиент, который использует метод receive для синхронного получения сообщений. Затем в этом разделе объясняется, как запускать клиенты с помощью сервера GlassFish.

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

Клиент SynchConsumer.java

Принимающий клиент SynchConsumer.java выполняет следующие шаги.

  1. Инъецирует ресурсы фабрики соединений, очереди и темы.

  2. Устанавливает очередь или тему пунктом назначения в зависимости от указанного типа пункта назначения.

  3. В блоке try-with-resources создаёт JMSContext.

  4. Создаёт JMSConsumer и начинает доставку сообщения:

    consumer = context.createConsumer(dest);
  5. Получает сообщения, отправленные в пункт назначения до тех пор, пока не будет получено управляющее сообщение конца потока сообщений:

    int count = 0;
    while (true) {
        Message m = consumer.receive(1000);
        if (m != null) {
            if (m instanceof TextMessage) {
                System.out.println(
                        "Reading message: " + m.getBody(String.class));
                count += 1;
            } else {
                break;
            }
        }
    }
    System.out.println("Messages received: " + count);

    Поскольку сообщение-сигнал не является TextMessage, принимающий клиент завершает цикл while и прекращает приём сообщений после поступления сообщения-сигнала.

  6. Ловит и обрабатывает все возможные исключения. Конец блока try-with-resources автоматически закрывает JMSContext.

Клиент SynchConsumer использует цикл while для получения сообщений, вызывая receive с аргументом timeout.

Запуск клиентов SynchConsumer и Producer

Вы можете запустить клиент с помощью команды appclient. Клиент SynchConsumer принимает один аргумент командной строки — тип пункта назначения.

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

  1. В том же окне терминала, где вы запустили Producer, перейдите в каталог synchconsumer:

    cd ../synchconsumer
  2. Запустите клиент SynchConsumer с аргументом queue:

    appclient -client target/synchconsumer.jar queue

    Вывод клиента выглядит следующим образом (вместе с дополнительным выводом):

    Destination type is queue
    Reading message: This is message 1 from producer
    Reading message: This is message 2 from producer
    Reading message: This is message 3 from producer
    Messages received: 3
  3. Теперь попробуйте запустить клиентов в обратном порядке. Запустите клиент SynchConsumer:

    appclient -client target/synchconsumer.jar queue

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

  4. Откройте новое окно терминала и запустите клиент Producer:

    cd tut-install/jms/simple/producer
    appclient -client target/producer.jar queue 3

    Когда сообщения отправлены, клиент SynchConsumer получает их и завершает работу.

  5. Теперь запустите клиент Producer, используя topic вместо queue:

    appclient -client target/producer.jar topic 3

    Вывод клиента выглядит следующим образом (вместе с дополнительным выводом):

    Destination type is topic
    Sending message: This is message 1 from producer
    Sending message: This is message 2 from producer
    Sending message: This is message 3 from producer
    Text messages sent: 3
  6. Теперь в другом окне терминала запустите клиент SynchConsumer, используя тему:

    appclient -client target/synchconsumer.jar topic

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

  7. Оставьте клиент SynchConsumer запущенным и снова запустите клиент Producer:

    appclient -client target/producer.jar topic 3

    Теперь клиент SynchConsumer получает сообщения:

    Destination type is topic
    Reading message: This is message 1 from producer
    Reading message: This is message 2 from producer
    Reading message: This is message 3 from producer
    Messages received: 3

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

Использование слушателя сообщений для асинхронной доставки сообщений

В этом разделе описываются принимающие клиенты в примере, который использует слушатель сообщений для асинхронной доставки сообщений. Затем в этом разделе объясняется, как скомпилировать и запустить клиенты с помощью GlassFish Server.

Замечание:

В платформе Java EE слушатели сообщений могут использоваться только в клиентских приложениях, как в этом примере. Чтобы разрешить асинхронную доставку сообщений в веб-приложении или приложении Enterprise-бина, нужно использовать компонент, управляемый сообщениями, как показано в следующих примерах этой главы.

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

Написание клиентов AsynchConsumer.java и TextListener.java

Отправляющим клиентом является Producer.java — тот же клиент, который использовался в Отправке сообщений и Синхронном получении сообщений.

Асинхронный потребитель обычно работает бесконечно. В этом примере клиент выполняется до тех пор, пока пользователь не введет символ q или Q, чтобы остановить его.

  1. Клиент AsynchConsumer.java выполняет следующие шаги.

  2. Инъецирует ресурсы фабрики соединений, очереди и темы.

  3. Устанавливает очередь или тему пунктом назначения в зависимости от указанного типа пункта назначения.

  4. В блоке try-with-resources создаёт JMSContext.

  5. Создаёт JMSConsumer.

  6. Создаёт объект класса TextListener и регистрирует его в качестве слушателя сообщений для JMSConsumer:

    listener = new TextListener();
    consumer.setMessageListener(listener);
  7. Слушает сообщения, отправленные пункту назначения, и завершает работу, когда пользователь вводит символ q или Q (для этого он использует java.io.InputStreamReader).

  8. Ловит и обрабатывает все возможные исключения. Конец блока try-with-resources автоматически закрывает JMSContext, что останавливает доставку сообщений слушателю сообщений.

  9. Слушатель сообщений TextListener.java выполняет следующие действия:

  10. Когда приходит сообщение, метод onMessage вызывается автоматически.

  11. Если сообщение имеет тип TextMessage, метод onMessage отображает его содержимое в виде строкового значения. Если сообщение не является текстовым сообщением, он сообщает об этом:

    public void onMessage(Message m) {
        try {
            if (m instanceof TextMessage) {
                System.out.println(
                        "Reading message: " + m.getBody(String.class));
            } else {
                 System.out.println("Message is not a TextMessage");
            }
        } catch (JMSException | JMSRuntimeException e) {
            System.err.println("JMSException in onMessage(): " + e.toString());
        }
    }

В этом примере будут использоваться те же фабрика соединений и пункт назначения, которые были созданы в Создание ресурсов для простых примеров.

В этих шагах предполагается, что все примеры уже собраны и упакованы, используя IDE NetBeans или Maven.

Запуск клиентов AsynchConsumer и Producer

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

  1. В окне терминала, где вы запустили клиент SynchConsumer, перейдите в каталог примера asynchconsumer:

    cd tut-install/jms/simple/asynchconsumer
  2. Запустите клиент AsynchConsumer, указав тип пункта назначения topic:

    appclient -client target/asynchconsumer.jar topic

    Клиент отображает следующие строки (вместе с дополнительным выводом), а затем ожидает сообщения:

    Destination type is topic
    To end program, enter Q or q, then <return>
  3. В окне терминала, где ранее запускался клиент Producer, снова запустите клиент, отправив три сообщения:

    appclient -client target/producer.jar topic 3

    Вывод клиента выглядит следующим образом (вместе с дополнительным выводом):

    Destination type is topic
    Sending message: This is message 1 from producer
    Sending message: This is message 2 from producer
    Sending message: This is message 3 from producer
    Text messages sent: 3

    В другом окне клиент AsynchConsumer отображает следующее (вместе с некоторыми дополнительными выходными данными):

    Destination type is topic
    To end program, enter Q or q, then <return>
    Reading message: This is message 1 from producer
    Reading message: This is message 2 from producer
    Reading message: This is message 3 from producer
    Message is not a TextMessage

    Последняя строка появляется, потому что клиент получил нетекстовое управляющее сообщение, отправленное клиентом Producer.

  4. Введите Q или q и нажмите Return, чтобы остановить клиент AsynchConsumer.

  5. Теперь запустите клиенты, используя очередь.

    В этом случае, как и в синхронном примере, вы можете сначала запустить клиент Producer, потому что между отправителем и получателем нет временнóй зависимости:

    appclient -client target/producer.jar queue 3

    Вывод клиента выглядят так:

    Destination type is queue
    Sending message: This is message 1 from producer
    Sending message: This is message 2 from producer
    Sending message: This is message 3 from producer
    Text messages sent: 3
  6. В другом окне запустите клиент AsynchConsumer:

    appclient -client target/asynchconsumer.jar queue

    Вывод клиента выглядит следующим образом (вместе с дополнительным выводом):

    Destination type is queue
    To end program, enter Q or q, then <return>
    Reading message: This is message 1 from producer
    Reading message: This is message 2 from producer
    Reading message: This is message 3 from producer
    Message is not a TextMessage
  7. Введите Q или q и нажмите Return, чтобы остановить клиента.

Просмотр сообщений в очереди

В этом разделе описывается пример создания объекта QueueBrowser для проверки сообщений в очереди, как описано в разделе Браузеры очередей JMS. Затем в этом разделе объясняется, как скомпилировать, упаковать и запустить пример с использованием сервера GlassFish.

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

Клиент MessageBrowser.java

Чтобы создать QueueBrowser для очереди, вызывается метод JMSContext.createBrowser с очередью в качестве аргумента. Затем получаются сообщения в очереди как объект Enumeration. Затем можно перебирать объект Enumeration и отображать содержимое каждого сообщения.

Клиент MessageBrowser.java выполняет следующие шаги.

  1. Инъецирует ресурсы для фабрики соединений и очереди.

  2. В блоке try-with-resources создаёт JMSContext.

  3. Создаёт QueueBrowser:

    QueueBrowser browser = context.createBrowser(queue);
  4. Получает Enumeration, содержащий сообщения:

    Enumeration msgs = browser.getEnumeration();
  5. Проверяет, что Enumeration содержит сообщения, а затем отображает содержимое сообщений:

    if ( !msgs.hasMoreElements() ) {
        System.out.println("No messages in queue");
    } else {
        while (msgs.hasMoreElements()) {
            Message tempMsg = (Message)msgs.nextElement();
            System.out.println("Message: " + tempMsg);
        }
    }
  6. Ловит и обрабатывает все возможные исключения. Конец блока try-with-resources автоматически закрывает JMSContext.

Вывод содержимого сообщения в стандартный вывод позволяет получить тело и свойства сообщения в формате, который зависит от реализации метода toString. На сервере GlassFish формат сообщения выглядит примерно так:

Text:   This is message 3 from producer
Class:                  com.sun.messaging.jmq.jmsclient.TextMessageImpl
getJMSMessageID():      ID:8-10.152.23.26(bf:27:4:e:e7:ec)-55645-1363100335526
getJMSTimestamp():      1129061034355
getJMSCorrelationID():  null
JMSReplyTo:             null
JMSDestination:         PhysicalQueue
getJMSDeliveryMode():   PERSISTENT
getJMSRedelivered():    false
getJMSType():           null
getJMSExpiration():     0
getJMSPriority():       4
Properties:             {JMSXDeliveryCount=0}

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

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

Запуск клиента QueueBrowser

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

Вам также нужен пример Producer, чтобы отправить сообщение в очередь, и один из клиентов-потребителей, чтобы получить сообщения после их проверки.

Для запуска клиентов вам нужны два окна терминала.

  1. В окне терминала перейдите в каталог producer:

    cd tut-install/examples/jms/simple/producer/
  2. Запустите клиент Producer, отправив одно сообщение в очередь вместе с нетекстовым сигнальным сообщением:

    appclient -client target/producer.jar queue

    Вывод клиента выглядит следующим образом (вместе с дополнительным выводом):

    Destination type is queue
    Sending message: This is message 1 from producer
    Text messages sent: 1
  3. В другом окне терминала перейдите в каталог messagebrowser:

    cd tut-install/jms/simple/messagebrowser
  4. Запустите клиент MessageBrowser следующей командой:

    appclient -client target/messagebrowser.jar

    Вывод клиента выглядит примерно так (вместе с дополнительным выводом):

    Message:
    Text:   This is message 1 from producer
    Class:                  com.sun.messaging.jmq.jmsclient.TextMessageImpl
    getJMSMessageID():      ID:9-10.152.23.26(bf:27:4:e:e7:ec)-55645-1363100335526
    getJMSTimestamp():      1363100335526
    getJMSCorrelationID():  null
    JMSReplyTo:             null
    JMSDestination:         PhysicalQueue
    getJMSDeliveryMode():   PERSISTENT
    getJMSRedelivered():    false
    getJMSType():           null
    getJMSExpiration():     0
    getJMSPriority():       4
    Properties:             {JMSXDeliveryCount=0}
    
    Message:
    Class:                  com.sun.messaging.jmq.jmsclient.MessageImpl
    getJMSMessageID():      ID:10-10.152.23.26(bf:27:4:e:e7:ec)-55645-1363100335526
    getJMSTimestamp():      1363100335526
    getJMSCorrelationID():  null
    JMSReplyTo:             null
    JMSDestination:         PhysicalQueue
    getJMSDeliveryMode():   PERSISTENT
    getJMSRedelivered():    false
    getJMSType():           null
    getJMSExpiration():     0
    getJMSPriority():       4
    Properties:             {JMSXDeliveryCount=0}

    Первое сообщение — это TextMessage, а второе — нетекстовое сообщение-сигнал.

  5. Перейдите в каталог synchconsumer.

  6. Запустите клиент SynchConsumer, чтобы получить сообщения:

    appclient -client target/synchconsumer.jar queue

    Вывод клиента выглядит следующим образом (вместе с дополнительным выводом):

    Destination type is queue
    Reading message: This is message 1 from producer
    Messages received: 1

Запуск нескольких потребителей для одного пункта назначения

Чтобы дополнительно проиллюстрировать, как работает обмен сообщениями типа «точка-точка» и «публикация-подписка», вы можете использовать примеры Producer и SynchConsumer для отправки сообщений, которые затем используются двумя клиентами, работающими одновременно.

  1. Откройте три командных окна. В одном перейдите в каталог producer. В двух других перейдите в каталог synchconsumer.

  2. В каждом из окон synchconsumer запустите клиент, получающий сообщения из очереди:

    appclient -client target/synchconsumer.jar queue

    Подождите, пока в обоих окнах не появится сообщение «Destination type is queue».

  3. В окне provider запустите клиент, отправив в очередь 20 сообщений:

    appclient -client target/producer.jar queue 20
  4. Посмотрите на вывод в окнах synchconsumer. В обмене сообщениями точка-точка каждое сообщение может иметь только одного потребителя. Следовательно, каждый из клиентов получает только часть сообщений. Один из клиентов получает нетекстовое сигнальное сообщение, сообщает количество полученных сообщений и завершает работу.

  5. В окне клиента, который не получил нетекстовое сигнальное сообщение, введите Control-C для выхода из программы.

  6. Затем запустите клиенты synchconsumer, используя тему. В каждом окне выполните следующую команду:

    appclient -client target/synchconsumer.jar topic

    Подождите, пока в обоих окнах не появится сообщение «Destination type is topic».

  7. В окне producer запустите клиент, отправив 20 сообщений в тему:

    appclient -client target/producer.jar topic 20
  8. Снова посмотрите на вывод в окнах synchconsumer. В сообщениях "публикация-подписка" копия каждого сообщения отправляется каждой подписке по теме. Следовательно, каждый из клиентов получает все 20 текстовых сообщений, а также нетекстовое сигнальное сообщение.

Подтверждение сообщений

JMS предоставляет два альтернативных способа для получающего клиента, чтобы гарантировать, что сообщение не будет подтверждено, пока приложение не закончит обработку сообщения:

  • Использование синхронного потребителя в JMSContext, который был настроен с использованием параметра CLIENT_ACKNOWLEDGE

  • Использование слушателя сообщений для асинхронной доставки сообщений в JMSContext, который был настроен с использованием параметра AUTO_ACKNOWLEDGE по умолчанию

Замечание:

В платформе Java EE сессии CLIENT_ACKNOWLEDGE могут использоваться только в клиентских приложениях, как в этом примере.

Пример clientackconsumer демонстрирует первый вариант, в котором синхронный потребитель использует подтверждение клиента. Пример asynchconsumer, описанный в Использование слушателя сообщений для асинхронной доставки сообщений, демонстрирует второй вариант.

Для получения информации о подтверждении сообщения см. Управление подтверждением сообщения.

В следующей таблице описаны четыре возможных соотношения между типами потребителей и типами подтверждения.

Таблица 49-3. Подтверждение сообщения с синхронными и асинхронными потребителями

Тип потребителя

Тип подтверждения

Поведение

Синхронный

Client

Клиент подтверждает сообщение после завершения обработки

Асинхронный

Client

Клиент подтверждает сообщение после завершения обработки

Синхронный

Auto

Подтверждение происходит сразу после вызова receive. Сообщение не может быть доставлено в случае сбоя на последующих этапах обработки

Асинхронный

Auto

Сообщение автоматически подтверждается, когда возвращается метод onMessage

Пример находится в каталоге tut-install/examples/jms/simple/clientackconsumer/.

Пример клиента ClientAckConsumer.java создаёт JMSContext, который указывает тип подтверждение Client:

try (JMSContext context =
      connectionFactory.createContext(JMSContext.CLIENT_ACKNOWLEDGE);) {
    ...

Клиент использует цикл while, практически идентичный циклу SynchConsumer.java за тем исключением, что после обработки каждого сообщения он вызывает метод accept в JMSContext:

context.acknowledge();

В примере используются следующие объекты:

  • Ресурс jms/MyQueue, который был создан для Синхронного получения сообщений.

  • java:comp/DefaultJMSConnectionFactory — фабрика соединений платформы по умолчанию, предустановленная на GlassFish Server

Запуск клиента ClientAckConsumer

  1. В окне терминала перейдите в следующий каталог:

    tut-install/examples/jms/simple/producer/
  2. Запустите клиент Producer, отправив несколько сообщений в очередь:

    appclient -client target/producer.jar queue 3
  3. В другом окне терминала перейдите в следующий каталог:

    tut-install/examples/jms/simple/clientackconsumer/
  4. Чтобы запустить клиент, используйте следующую команду:

    appclient -client target/clientackconsumer.jar

    Вывод клиента выглядят следующим образом (наряду с некоторыми дополнительными выходными данными):

    Created client-acknowledge JMSContext
    Reading message: This is message 1 from producer
    Acknowledging TextMessage
    Reading message: This is message 2 from producer
    Acknowledging TextMessage
    Reading message: This is message 3 from producer
    Acknowledging TextMessage
    Acknowledging non-text control message

    Клиент подтверждает каждое сообщение явным образом после его обработки, так же как JMSContext, настроенный на использование AUTO_ACKNOWLEDGE, выполняет это автоматически после успешного завершения MessageListener после обработки асинхронно полученного сообщения.


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