Search code examples
jmsspring-jmsactivemq-artemis

Setting ActiveMQ Artemis routing type, Spring Boot JmsListener as client


I've been using ActiveMQ Artemis for over a year. My requirements so far have been to preserve messages like orders, emails, supplier updates, etc. Therefore, I've been explicitly creating an address and under it a queue for each consumer. This way even if both producer and consumer shut down I won't lose pending orders, for example.

My new case is basically the opposite. I have loads of data coming from a web socket. I need to filter this and provide it on ActiveMQ Artemis. Preferably, the clients could subscribe to the address and receive messages based on the message selector they provide. For example, here are two clients I'm experimenting with using Spring Boot:

@JmsListener(destination="price.address::price.2.queue", selector="JMSType='test'")
public void testReceiver1(String msg) {
    System.out.println("1 " + msg); 
}
@JmsListener(destination="price.address::price.2.queue")
public void testReceiver2(String msg) {
    System.out.println("2 " + msg); 
}

Ideally these two clients/listeners should be able to subscribe with anycast, so one or both can specify a selector and get those messages.

But when they connect, anycast queues are created. So I tried adding the address to my broker like so:

<addresses>
   <address name="price.address">
      <multicast/>
   </address>
</addresses>

This didn't seem to do anything. Anycast queues are created.

I also tried setting both listeners to point directly to the topic/address (not using FQQN) but still an anycast routing type appears -- a single queue named price.address.

I'm not sure how all this data will be use in the end, so I'm trying to supply is as flexibly as possible. I know most of it won't be used at all, at least not for a while.

I have another project where most of the incoming data isn't used. I setup an address and explicit queues with filters for that, one for each client needing the filtered data. That works well, but the difference now is that I need the clients to be able to connect and specify the filter (selector) for the data they need, and only receive the new incoming messages.

I'm not sure if this is an ActiveMQ Artemis question of a JMS client or Spring Boot @JmsListener question.

  • ActiveMQ Artemis 2.17
  • Spring Boot 2.5

Solution

  • Given that you want clients to be able to connect and:

    • specify a selector for the data they need
    • only receive new incoming messages

    That means that you want to use a JMS topic.

    However, your @JmsListener definitions are using a JMS queue instead, because that's what they use by default. Take a look at this answer for details on how to make them use a JMS topic.

    Since your @JmsListener definitions are using a JMS queue the broker is auto-creating and using anycast resources automatically. This is why you see the same behavior no matter what configuration you change on the broker.

    Ultimately you don't need to define any address or queue in broker.xml. As long as the client is using the right kind of JMS resources all the broker-side resources will be created automatically. Also, your @JmsListener definition should just use the name of the address and not the FQQN.