Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using passed in Value for @JmsListener's destination paramter

Is there a specific way to accomplish this? I tried to find a solution on here but couldn't find what I need. I have a Spring Boot application that will be accepting multiple arguments from the command line. The argument in question is the queue name (i.e. the destination). It can be one of several of our many queues. The JmsListener is in the form

@JmsListener(destination="dest_goes_here")
public void processOrder(Message message){. . .}

I have a class that basically looks like this

 public class Arguments {
 private static queue
 private static antoherArg
 :
 :
getters and setters
 }

And what I would like to say is destination = Arguments.getQueue(), but it seems destination can only be a static final variable? I assume this because the error presents a little tooltip that alludes to that.

I also tested it, as I have yet another class called Constants, that obvioulsy contains constants, and if I hard code the queue name as public static final String QUEUE = "MyQ"; then say destination = Constants.QUEUE it is ok with that.

So then I assumed I could do something like this in my listener class private static final String QUEUE = Arguments.getQueue(); But it doesn't like that either. Alas, I am stumped.

So really two questions here if anyone is willing to knowledge share. Why is the @JmsListener ok with having destination set to my second solution, but not the first and the last?

And then the main question (that I'd prefer you answer over the first) is, what strategies can I make use of to set destination to a variable that originates from the command line (i.e. be dynamic)?

Edit: To clarify, I cannot keep the value in my Constants class, as the value will be coming from the command line and needs to be passed to the JmsListener class to be used as the destination.

like image 695
LumberSzquatch Avatar asked Jan 05 '23 13:01

LumberSzquatch


1 Answers

That's how Java works, destination must be a compile-time constant expression and a function invocation isn't considered one. Take a look at the official language specification for more details. EDIT: you can also look at this answer.

As far as your second (and more important) question goes, I have several suggestions for you.

First, you can read the queue name from a configuration property, like so: destination="${jms.queue.name1}" where jms.queue.name1 is your configuration property. Then, since you are using Spring Boot, you can use command-line arguments to override your configuration properties (see externalized configuration documentation for more details). That way, you'll be able to specify the queue name at runtime by passing it as a command-line argument like so --jms.queue.name1=foo.

Second, you can use programmatic listener registration, like so:

@Configuration
@EnableJms
public class AppConfig implements JmsListenerConfigurer {

    @Override
    public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
        SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
        endpoint.setId("myJmsEndpoint");
        endpoint.setDestination(Arguments.getQueue());
        endpoint.setMessageListener(message -> {
            // processing
        });
        registrar.registerEndpoint(endpoint);
    }
}
like image 91
Miloš Milivojević Avatar answered Jan 08 '23 02:01

Miloš Milivojević