如何在代码中创建Apache Artemis队列并将其与JMS一起使用?

问题描述 投票:1回答:1

我正在将JavaLite Async从Artemis 2.3.0迁移到2.11.0版本。 JavaLite Async不使用任何文件基础配置,而是依靠代码。

在2.3.0和2.11.0版之间,JMS管理API现在已不可用/已弃用,我们建议使用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");

但是,这仅部分起作用,队列似乎已经存在,发送和接收消息,而QueueControlQueueBrtowser都找不到。

有人可以在代码中解释我如何做到这一点(无XML配置

  1. 创建队列并传递所有必要的参数(耐用等)
  2. 使用JNDI查找此队列
  3. 使用QueueControl控制此队列
  4. 使用QueueBrowser浏览此队列。

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

非常感谢您的帮助!

java jms activemq-artemis
1个回答
2
投票

这里似乎有一些误会...

首先,当您说添加CoreQueueConfiguration无效时,您的意思不清楚。 ActiveMQ Artemis测试套件使用相同的模式来配置核心队列。我的猜测是,它似乎对您没有影响,因为默认情况下,核心JMS客户端会自动创建其所需的目标,因此无论您指定了CoreQueueConfiguration,在JNDI属性中配置的任何内容都会自动创建。如果您不想自动创建JMS目标所需的基础地址和队列,则应使用相应的地址设置禁用此功能。还有一些设置可以在不再使用时自动删除地址和队列,您也可能要禁用它们。这是一个例子:

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

请记住,JMS目标(即JMS队列和主题)以特定方式映射到基础核心资源。在the documentation中对此进行了描述。

第二,JNDI配置在this bit of documentation中进行了解释:

JMS目的地通常也通过JNDI查找。与连接工厂一样,可以在JNDI上下文环境中使用特殊属性来配置目标。属性name应该遵循以下模式:queue.<jndi-binding>topic.<jndi-binding>。属性value应该是Apache ActiveMQ Artemis服务器托管的队列的名称。

这说明了为什么需要此行:

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

The documentation还指出:

还可以查找在JNDI上下文环境中未显式配置的JMS目标。使用查询字符串中的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。网络上有很多教程。

最后,在添加了对AMQP,MQTT和OpenWire的支持之后,决定不赞成使用JMS配置和管理位是在发布2.0.0版本之前。那时,将配置和管理简化为仅核心资源(即地址,队列和路由类型)是有意义的。具有JMS的所有核心内容plus对应的配置和管理肯定会给用户造成混乱,并且也很难维护。我们花了很多时间来更新文档,以解释所有东西如何从受支持的各种协议和API到核心资源进行映射。 javax.jms.QueueBrowser提供了可能对您有所帮助的概述。

© www.soinside.com 2019 - 2024. All rights reserved.