Как создать Apache Artemis очереди в коде и использовать их с JMS? - PullRequest
1 голос
/ 19 марта 2020

Я перевожу JavaLite Asyn c с версии Artemis 2.3.0 на 2.11.0. JavaLite Asyn c НЕ использует базовую конфигурацию файлов, а использует код.

Между версиями 2.3.0 и 2.11.0 API управления JMS больше не существует, и нам рекомендуется использовать Core Management API.

К сожалению, я не могу найти способ:

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

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

class QueueLookup {
    private static final String LOCATION = "./target/artemis";

    private static EmbeddedActiveMQ server;

    public static void main(String[] args) throws Exception {
        try{
            Configuration configuration = new ConfigurationImpl()
                    .setPersistenceEnabled(true)
                    .setBindingsDirectory(LOCATION + "/bindings")
                    .setJournalDirectory(LOCATION + "/journal")
                    .setLargeMessagesDirectory(LOCATION + "/largemessages")
                    .setPagingDirectory(LOCATION + "/paging")
                    .setSecurityEnabled(false)
                    .addAcceptorConfiguration("invm", "vm://0")
                    .setJournalBufferTimeout_AIO(100)
                    .setJournalBufferTimeout_NIO(100)
                    .setJournalType(JournalType.NIO)
                    .setMaxDiskUsage(90);


            //the following three lines have no effect
            CoreQueueConfiguration coreQueueConfiguration = new CoreQueueConfiguration();
            coreQueueConfiguration.setName("Queue123").setDurable(true);
            configuration.addQueueConfiguration(coreQueueConfiguration);


            server = new EmbeddedActiveMQ();
            server.setConfiguration(configuration);
            server.start();


            TransportConfiguration transportConfiguration = new TransportConfiguration(InVMConnectorFactory.class.getName());
            ConnectionFactory connectionFactory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, transportConfiguration);

            Hashtable<String, String> jndi = new Hashtable<>();
            jndi.put("java.naming.factory.initial", "org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory");
            jndi.put("connectionFactory.ConnectionFactory", "vm://0");
            //# queue.[jndiName] = [physicalName]
            jndi.put("queue.queue/Queue123", "Queue123");

            InitialContext initialContext = new InitialContext(jndi);
            Queue jmsQueue = (Queue) initialContext.lookup("queue/Queue123");

            try (Connection connection = connectionFactory.createConnection()) {
                try(Session jmsSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)){
                    MessageProducer producer = jmsSession.createProducer(jmsQueue);
                    connection.start();
                    TextMessage message = jmsSession.createTextMessage("Hello, Artemis!");
                    producer.send(message);
                    System.out.println("Message sent: " + message.getText());
                }
            } catch (Exception ex){
                ex.printStackTrace();
            }

        }finally {
            server.stop();
        }
    }
}

Эти строки не действуют:

CoreQueueConfiguration coreQueueConfiguration = new CoreQueueConfiguration();
coreQueueConfiguration.setName("Queue123").setDurable(true);
configuration.addQueueConfiguration(coreQueueConfiguration);

Однако, если я удалю эту строку:

jndi.put("queue.queue/Queue123", "Queue123");

, тогда JNDI не может найти очередь.

На первый взгляд кажется, что я мог бы "создавать" очереди, добавляя их имена в JNDI:

jndi.put("queue.queue/Queue123", "Queue123");

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

Может кто-нибудь объяснить, как я могу сделать это в коде ( нет XML конфигурация ):

  1. Создать очередь и передать все необходимые параметры (длительный , et c)
  2. Найти эту очередь с помощью JNDI
  3. Управлять этой очередью с помощью QueueControl
  4. Просматривать эту очередь с помощью QueueBrowser.

Полный пример с версией GUI можно найти здесь: https://github.com/ipolevoy/artemis-sanbox/blob/master/src/main/java/examples/

Большое спасибо за любую помощь!

Ответы [ 2 ]

2 голосов
/ 19 марта 2020

Здесь, кажется, есть пара недоразумений ...

Во-первых, причина, по которой ваш CoreQueueConfiguration не имеет "эффекта", заключается в том, что он недействителен. Он недействителен, потому что вы не указали имя адреса, к которому будет привязана очередь. Посредник должен регистрировать что-то вроде этого, когда появляется, указав, что конфигурация недействительна:

WARN  [org.apache.activemq.artemis.core.server] AMQ222275: Failed to deploy queue <queue name>: null

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

coreQueueConfiguration.setAddress("Queue123").setName("Queue123").setDurable(true).setRoutingType(org.apache.activemq.artemis.api.core.RoutingType.ANYCAST);

Я предполагаю, что все работает частично, потому что по умолчанию основной клиент JMS автоматически создает необходимые пункты назначения, поэтому все, что вы настраиваете в Ваши свойства JNDI будут созданы автоматически независимо от указанного вами CoreQueueConfiguration. Если вы не хотите автоматически создавать базовые адреса и очереди, необходимые для JMS-адресов, вы должны отключить это, используя соответствующие настройки адреса. Существуют также настройки автоматического удаления адресов и очередей, когда они больше не используются (например, когда счетчик сообщений = 0 и счетчик счетчиков = 0), которые вы, вероятно, также захотите отключить. Вот пример:

server.getAddressSettingsRepository().addMatch("#", new AddressSettings()
   .setAutoCreateQueues(false)
   .setAutoDeleteQueues(false)
   .setAutoCreateAddresses(false)
   .setAutoDeleteAddresses(false));

Во-вторых, конфигурация JNDI объясняется в этом бите документации :

Направления JMS также обычно ищутся через JNDI. Как и в случае с фабриками соединений, места назначения можно настроить с помощью специальных свойств в контекстной среде JNDI. Свойство name должно следовать шаблону: queue.<jndi-binding> или topic.<jndi-binding>. Свойство value должно быть именем очереди, размещенной на сервере Apache ActiveMQ Artemis.

Это объясняет, почему вам нужна эта строка:

jndi.put("queue.queue/Queue123", "Queue123");

В документации также указывается:

Также можно искать JMS-адресаты, которые не были явно настроены в контекстной среде JNDI. Это возможно, используя dynamicQueues/ или dynamicTopics/ в строке поиска. Например, если клиент хочет найти вышеупомянутый «OrderQueue», он может сделать это просто с помощью строки «dynamicQueues / OrderQueue». Обратите внимание, что текст, следующий за dynamicQueues/ или dynamicTopics/, должен точно соответствовать названию пункта назначения на сервере.

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

Queue jmsQueue = (Queue) initialContext.lookup("dynamicQueues/Queue123");

Тем не менее, непонятно, зачем вам вообще использовать JNDI, а не просто создавать экземпляр назначения с помощью JMS API. Вы можете существенно упростить этот код, удалив весь код JNDI, например:

ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://0");

try (Connection connection = connectionFactory.createConnection(); 
     Session jmsSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) {
   MessageProducer producer = jmsSession.createProducer(jmsSession.createQueue("Queue123"));
   connection.start();
   TextMessage message = jmsSession.createTextMessage("Hello, Artemis!");
   producer.send(message);
   System.out.println("Message sent: " + message.getText());
} catch (Exception ex) {
   ex.printStackTrace();
}

Чтобы получить элемент управления для очереди, используйте что-то вроде этого:

QueueControl coreQueueControl = (QueueControl) server.getManagementService().getResource(org.apache.activemq.artemis.api.core.management.ResourceNames.QUEUE + "Queue123");

Для просмотра очереди вы можно использовать javax.jms.QueueBrowser. Для этого в Интернете есть множество учебников.

Наконец, решение об устаревании битов конфигурации и управления JMS было принято до выпуска версии 2.0.0 после того, как мы добавили поддержку AMQP, MQTT и OpenWire. На этом этапе имело смысл упростить настройку и управление вплоть до основных ресурсов (т. Е. Адресов, очередей и типов маршрутизации). Наличие всех основных компонентов плюс соответствующей конфигурации и управления для JMS, безусловно, вызвало бы замешательство у пользователей, а также было бы трудно поддерживать. Мы потратили немало времени на обновление документации, чтобы объяснить, как все отображается от различных поддерживаемых протоколов и API до основных ресурсов. Этот документ содержит обзор, который может оказаться полезным.

0 голосов
/ 20 марта 2020

дополнительная информация:

Настройка очереди:

CoreQueueConfiguration coreQueueConfiguration = new CoreQueueConfiguration();
coreQueueConfiguration.setAddress(QUEUE_NAME).setName(QUEUE_NAME).setDurable(true).setRoutingType(RoutingType.ANYCAST);
configuration.addQueueConfiguration(coreQueueConfiguration);

способ регистрации имени очереди:

jndi.put("queue.queue/" + QUEUE_NAME, QUEUE_NAME);

Способ настройки посредника:

server.getActiveMQServer().getAddressSettingsRepository().addMatch("#", new AddressSettings()
                .setAutoCreateQueues(false)
                .setAutoCreateAddresses(false)
                .setAutoDeleteQueues(false)
                .setAutoDeleteAddresses(false));

Полный рабочий пример: https://github.com/ipolevoy/artemis-sanbox/blob/7e2194788ec4e825d4219f06ebbaa9b9195e2b30/src/main/java/examples/JMSExampleJNDI_GUI.java#L23

...