3
votes

I am using Spring boot, and I would like to dynamically create multiple JMS Templates, as I would like to connect to different JMS instances. I am aware of the standard approach of using annotations, linking the ConnectionFactory to the JMSTemplate. I would expect a different JMSTemplate to each different JMS Instance.

I have the connection details currently loaded into a Map, I would like to dynamically create a JMSTemplate for each key.

The main purpose is to publish messages to Topic destinations based on a map lookup. But for testing, it would be could to have listeners as well.

Potential approaches:

1) add the JMSTemplates to a map that is associated with a Spring Component, and lookup the JMSTemplate on spring component map.

2) what about dynamically registering multiple jmsTemplate beans using:

BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(JmsTemplate.class); CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();

         builder.addPropertyValue("connectionFactory", cachingConnectionFactory);      // set property value
        DefaultListableBeanFactory factory = (DefaultListableBeanFactory) context.getAutowireCapableBeanFactory();
        factory.registerBeanDefinition("jmsTemplateName", builder.getBeanDefinition());

Then lookup the jms bean -> ctx.getBean("jmsTemplateName");

Which approach is favorable?

Please advise.

B

1
Are you planning to poll MQs or you want to dynamically register listeners also?luboskrnac

1 Answers

3
votes

So if you have ConnectionFactory objects in a map, you can create similar map of JmsTemplates. Use this JmsTempalte contructor and after one loop (or stream) and you can have map of JmsTemplates. So sending is easy.

Harder part would be listeners. If you have dynamic destinations, you need to forget about listener annotations (@JmsListener). You can make it working by creating map of DefaultMessageListenerContainer.

Each container will be created by something like:

DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setDestination(topic);
container.setMessageListener(listenerInstance);
container.start();

You can also control lifecycle of each listener container via stop, shutdown, ....

But bear in mind that handling a lot of queues this way may be resource intensive. Also you will need to take care about closing resources yourself probably (Spring wouldn't do it for you).