簡體   English   中英

如何在代碼中創建 Apache Artemis 隊列並將它們與 JMS 一起使用?

[英]How to create Apache Artemis queues in code and use them with JMS?

我正在將JavaLite Async從 Artemis 2.3.0 遷移到 2.11.0 版本。 JavaLite Async 不使用任何文件基礎配置,而是依賴於代碼。

在 v 2.3.0 和 2.11.0 之間,JMS 管理 API 現已消失/棄用,我們鼓勵使用核心管理 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");

但是,這只能部分起作用,隊列似乎存在以發送和接收消息,而QueueControlQueueBrtowser都找不到它。

有人可以解釋我如何在代碼中做到這一點(沒有 XML 配置):

  1. 創建一個隊列並傳遞所有必要的參數(耐用等)
  2. 使用 JNDI 查找此隊列
  3. 使用 QueueControl 控制這個隊列
  4. 使用 QueueBrowser 瀏覽此隊列。

可以在此處找到帶有 GUI 版本的完整示例: https : //github.com/ipolevoy/artemis-sanbox/blob/master/src/main/java/examples/

非常感謝任何幫助!

這里似乎有一些誤解......

首先,您的CoreQueueConfiguration “無效”的原因是它無效。 它無效,因為您尚未指定隊列將綁定到的地址的名稱。 當出現指示配置無效時,代理應該記錄如下內容:

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

正如JMS 到核心映射文檔 中所述,JMS 隊列是一個核心地址和一個同名的任播核心隊列。 因此,您應該使用這樣的配置:

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

我的猜測是事情部分工作,因為默認情況下,核心 JMS 客戶端將自動創建它需要的目標,因此無論您在 JNDI 屬性中配置什么,無論您指定的CoreQueueConfiguration是什么,都會自動創建。 如果您不想自動創建 JMS 目標所需的底層地址和隊列,那么您應該使用相應的地址設置禁用它。 還有一些設置可以在不再使用時自動刪除地址和隊列(即當 message-count = 0 & coussumer-count = 0 時),您可能也想禁用它們。 下面是一個例子:

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

其次,JNDI 配置在這一部分文檔中進行了解釋:

JMS 目的地通常也通過 JNDI 查找。 與連接工廠一樣,可以使用 JNDI 上下文環境中的特殊屬性來配置目標。 屬性名稱應遵循以下模式: queue.<jndi-binding>topic.<jndi-binding> 屬性應該是 Apache ActiveMQ Artemis 服務器托管的隊列的名稱。

這解釋了為什么您需要此行:

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

該文件還指出:

還可以查找尚未在 JNDI 上下文環境中顯式配置的 JMS 目標。 這可以在查找字符串中使用dynamicQueues/dynamicTopics/ 例如,如果客戶端想要查找前面提到的“OrderQueue”,它可以通過使用字符串“dynamicQueues/OrderQueue”來實現。 請注意, dynamicQueues/dynamicTopics/ dynamicQueues/的文本必須與服務器上的目標名稱完全對應。

這意味着您可以省略上述行並使用這種查找來代替:

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

也就是說,與簡單地使用 JMS API 實例化目的地相比,您為什么要在這里使用 JNDI 尚不清楚。 您可以通過刪除所有 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 網上有很多關於這方面的教程。

最后,在我們添加了對 AMQP、MQTT 和 OpenWire 的支持之后,在 2.0.0 版發布之前就做出了棄用 JMS 配置和管理位的決定。 在這一點上,將配置和管理簡化為核心資源(即地址、隊列和路由類型)是有意義的。 擁有所有核心內容以及相應的 JMS 配置和管理肯定會給用戶帶來混亂,並且也很難維護。 我們花了相當多的時間更新文檔來解釋一切如何從各種支持的協議和 API 映射到核心資源。 本文檔提供了可能對您有所幫助的概述。

附加細節:

配置隊列:

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);

配置broker的方法:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM