0

I am trying out Spring Boot and ActiveMQ, and have been able to get things "working". But, I'd like to be able to dynamically set the destination for a JmsListener, and am failing spectacularly.

This code (not surprisingly) works...

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class MsgReceiver {

    @JmsListener(destination = "Consumer.myConsumer1.VirtualTopic.TEST-TOPIC")
    public void receiveMessage(String strMessage) {
        System.out.println("Received -> " + strMessage);
    }
}

So does this code (because Spring is okay with a String constant?)...

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class MsgReceiver {

    private final String consumer = "Consumer.myConsumer.VirtualTopic.TEST-TOPIC";

    @JmsListener(destination = consumer)
    public void receiveMessage(String strMessage) {
        System.out.println("Received -> " + strMessage);
    }
}

But, this code does not work...

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class MsgReceiver {

    private String consumer;

    public MsgReceiver() {
        consumer = "Consumer.myConsumer.VirtualTopic.TEST-TOPIC";
    }

    @JmsListener(destination = consumer)
    public void receiveMessage(String strMessage) {
        System.out.println("Received -> " + strMessage);
    }
}

I understand that Spring is not liking the non-constant value (I am guessing that this has to do with how the annotations get expanded at runtime?). I also understand that I could do something like:

@JmsListener(destination="${consumer}")

with the value being provided in an application.properties file. However, I'm trying to work towards a final solution where the consumer value is set using something like...

consumer = SomeConfigUtil.getValueForKey("foo");

Is there a way to get this to work? Or, is there a better way to achieve my objective?

Add Note: I have seen the examples using "straight JMS" to manage all of this, but have to admit that the annotations in Spring Boot make it much simpler. However, it's looking like hand-rolling things with "just JMS" might be the only solution?

SoCal
  • 801
  • 1
  • 10
  • 23
  • Possible duplicate of [How to supply value to an annotation from a Constant java](https://stackoverflow.com/questions/2065937/how-to-supply-value-to-an-annotation-from-a-constant-java) – Not a JD Apr 02 '19 at 23:17
  • I reviewed the linked question, and my question is different. Code example #2 addresses that question. I am asking if it is possible to supply a non-constant value (and, fear that the answer is "no"). Failing to get a hoped for "here's how you go do that", my secondary hope is that someone will point out a better approach to making the destination a runtime decision, short of abandoning Spring's very helpful annotations and rolling-my-own using straight JMS (which doesn't seem horribly heinous at first-blush, but I'm concerned may get more complicated as I move forward). – SoCal Apr 03 '19 at 15:07
  • Answer is no - compile time constants are compile time constants. Here's what you can do to make it delegate to a SpEL evaluation at runtime: https://stackoverflow.com/questions/42532613/how-to-add-different-destination-dynamically-to-jmslistener-annotation-in-spring – Not a JD Apr 03 '19 at 15:19
  • Thanks. I was hoping to avoid that approach, as I really want to provide the values via a utility, instead of having to potentially update multiple app config files. It's looking more-and-more like "abandon JmsTemplate" is going to be the answer. – SoCal Apr 03 '19 at 16:31
  • Also consider: section 10.3 https://docs.spring.io/spring/docs/4.3.15.RELEASE/spring-framework-reference/html/expressions.html. You can consume the result of a bean method invocation and use that as a SPeL expression! So if you can abstract your "utility" into something that the SPeL evaluator can eval, you should be good to go. No properties files needed! This is a one-time thing though... `JmsTemplate` itself has `receive(Destination)` methods that you can use for true dynamic message acquisition but you have to control lifecycle etc (see JmsTemplate docs - no room to paste URL in, sorry!) – Not a JD Apr 03 '19 at 16:49

0 Answers0