kimathie
kimathie

Reputation: 426

How to configure an ActiveMQ Artemis queue not be created again

I have an embedded ActiveMQ Artemis 2.17.0 broker that has no pre-configured queues. I'd like for the client to connect to the broker and have its queue created automatically if it doesn't exist. This works just fine the 1st time when I run the client but on the second time I connect again to the broker the client throws an error :

errorType=QUEUE_EXISTS message=AMQ229019: Queue hornetq already exists on address router

Is it possible to configure the client or the server in such a way that if a queue is already in existence it should not attempt to recreate it again?

Below are the programs I am running:

Server

try {
    ActiveMQServer server = new ActiveMQServerImpl(new ConfigurationImpl()
         .setPersistenceEnabled(true)
         .setBindingsDirectory("./router/data/bindings")
         .setLargeMessagesDirectory("./router/data/large")
         .setPagingDirectory("./router/data/paging")
         .setJournalDirectory("./router/data/journal")
         .setSecurityEnabled(false)
         .addAcceptorConfiguration("tcp", "tcp://0.0.0.0:61617?protocols=CORE,AMQP"));
    server.start();
} catch (Exception ex) {
    System.err.println(ex);
}

Client

ServerLocator serverLocator = ActiveMQClient.createServerLocator("tcp://127.0.0.1.3:61617");
ClientSessionFactory factory = serverLocator.createSessionFactory();
ClientSession session = factory.createSession();
session.createQueue(new QueueConfiguration("router::hornetq")
        .setAutoCreateAddress(Boolean.FALSE)
        .setAutoCreated(Boolean.FALSE)
        .setRoutingType(RoutingType.ANYCAST));
ClientProducer producer = session.createProducer("router::hornetq");
ClientMessage message = session.createMessage(true);
message.getBodyBuffer().writeString("Core Queue Message");
producer.send(message);
session.start();
ClientConsumer consumer = session.createConsumer("router::hornetq");
ClientMessage msgReceived = consumer.receive();
System.out.println("message = " + msgReceived.getBodyBuffer().readString());
session.close();

I'm using the fully qualified queue name here (i.e. router::hornetq) because I have multiple queues on the router address.

Upvotes: 1

Views: 1489

Answers (1)

Justin Bertram
Justin Bertram

Reputation: 35008

Your client is using the core API which is a low-level API that does not support auto-queue creation. Your client is creating (or attempting to create) the queue manually, e.g.:

session.createQueue(new QueueConfiguration("router::hornetq")
        .setAutoCreateAddress(Boolean.FALSE)
        .setAutoCreated(Boolean.FALSE)
        .setRoutingType(RoutingType.ANYCAST));

The exception you're seeing is no doubt being thrown here if the queue exists already. Creating a queue is not idempotent so you have 3 options from what I can see:

  • Simply catch the ActiveMQQueueExistsException that is being thrown here and ignore it.
  • Use ClientSession.queueQuery to see if the queue exists before you attempt to create it. If it exists then don't try to create it again. If it doesn't exist then create it. That said, if you have lots of clients like this running concurrently it's still possible you could get an ActiveMQQueueExistsException due to race conditions between the clients.
  • Use a client/protocol that supports auto-creation like the core JMS client or AMQP.

A few other things are worth mentioning:

  • Since you're not explicitly calling ClientSession.createAddress() you probably want to use setAutoCreateAddress(Boolean.TRUE).
  • Your consumer doesn't have to use router::hornetq. It can just use hornetq and it will receive any messages sent to the hornetq queue. Queue names are universally unique in the broker.

Upvotes: 1

Related Questions