title: spring jmsListener to listen to multiple Queues
body: <p>In this post , Garry Russell explained how to programmatically create multiple KafkaListeners to listen from multiple topics..  [this setup is actually working successfully for me ] 
  <a href="https://stackoverflow.com/questions/53715268/kafka-spring-how-to-create-listeners-dynamically-or-in-a-loop">Kafka Spring: How to create Listeners dynamically or in a loop?</a></p>
  
  <p>Now i want to have a similar setup working for JMSListeners as well - where I can have one class with one @JMSListener in it and i can programmatically create multiple instances of that JMSListener each injected with its own queueName. </p>
  
  <p>I found this post 
  <a href="https://stackoverflow.com/questions/40791567/spring-jms-start-listening-to-jms-queues-on-request">Spring JMS start listening to jms queues on request</a> </p>
  
  <p>In the end of this post Gary made a similar comment, </p>
  
  <blockquote>
    <p>If you wish to dynamically create lots of containers, then just create the containers programmatically, call afterPropertiesSet(), then start()</p>
  </blockquote>
  
  <p>I used the setup that i had working from the first post above(related to KafkaListeners), my multiple instances of JMS listeners are starting up but not consuming any messages.</p>
  
  <p>Basically i didn't understand where do i do this </p>
  
  <blockquote>
    <p>then just create the containers programmatically, call afterPropertiesSet(), then start()</p>
  </blockquote>
  
  <p>I am confused with the word - container, I know there's JMSListener and there's 
  JmsListenerContainerFactory, what is a container in this context - i guess JMSListener?</p>
  
  <p>i have confirmed there are messages in the queue. also when i don't create the listeners programmatically and just have one listener with hardcoded queue mentioned on it, it consumes the message fine.</p>
  
  <p>Basically none of the listeners are consuming the messages when i am creating multiple JMS Listeners programmatically</p>
  
  <pre><code>    @SpringBootApplication
  @EnableJms
  public class MqProdConsumerApplication {
      private static Logger logger = LogManager.getLogger(MqProdConsumerApplication.class.getName());
      private static Consumers consumersStatic;
  
      @Autowired
      Consumers consumers;
  
      @PostConstruct
      public void init() {
          consumersStatic = this.consumers;
      }
  
      @Bean
      public Gson gson() {
          return new Gson();
      }
  
      public static void main(String[] args) {
          ConfigurableApplicationContext context = SpringApplication.run(MqProdConsumerApplication.class, args);
          List&lt;QueueInformation&gt; queueInformationList = consumersStatic.getQueueInformationList();
          Assert.notEmpty(queueInformationList, "queueInformationList cannot be empty");
          logger.debug("queueInformationList ************" + queueInformationList.toString());
          for (QueueInformation queueInformation : queueInformationList) {
              AnnotationConfigApplicationContext child = new AnnotationConfigApplicationContext();
              child.setParent(context);
              child.register(MQConfig.class);
              Properties props = new Properties();
              props.setProperty("mqQueueName", queueInformation.getMqQueueName());
              //
              PropertiesPropertySource pps = new PropertiesPropertySource("listenerProps", props);
              child.getEnvironment().getPropertySources().addLast(pps);
              child.refresh();
          }
      }
  }
  </code></pre>
  
  <p>Here's the MQConfig that has the listenerContainerFactory </p>
  
  <pre><code>@Configuration
  public class MQConfig {
      Logger logger = LoggerFactory.getLogger(this.getClass());
  
      @Value("${ibm.mq.user}")
      private String mqUserName;
  
      @Bean
      public MQListener listener() {
          return new MQListener();
      }
  
      @PostConstruct
      public void afterConstruct() {
          logger.debug("************* initialized MQ Config successfully for user =" + mqUserName);
      }
  
      @Bean
      public JmsListenerContainerFactory&lt;?&gt; myFactory(ConnectionFactory connectionFactory,
                                                      DefaultJmsListenerContainerFactoryConfigurer configurer) {
          DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
          configurer.configure(factory, connectionFactory);
  
          // Put the MQ username in the PCF environment.
          // Otherwise, the connection is identified by PCF's default user, "VCAP"
          System.setProperty("user.name", mqUserName);
          return factory;
      }
  }
  </code></pre>
  
  <p>Then comes the MQListener which has the actual @JMSListener </p>
  
  <pre><code>    public class MQListener {
      Logger logger = LoggerFactory.getLogger(this.getClass());
  
      @Value("${mqQueueName}")
      private String mqQueueName;
  
      @PostConstruct
      public void afteConstruct() {
          logger.debug("************* initialized MQ Listener successfully, will read from =" + mqQueueName);
  
      }
  
      @JmsListener(destination = "${mqQueueName}", containerFactory = "myFactory")
      public void receiveMessage(String receivedMessage) throws JAXBException, ExecutionException, InterruptedException {
          logger.debug("***********************************************receivedMessage:" + receivedMessage);
      }
  }
  </code></pre>
  
  <p>Here's my application.yml</p>
  
  <pre><code>    ibm.mq.queueManager: ABCTOD01
  ibm.mq.channel: QMD00.SERVER
  ibm.mq.connName: mqdv1.devfg.ABC.com
  ibm.mq.user: pmd0app1
  ibm.mq.password:
  consumers:
    queueInformationList:
    -
      mqQueueName: QMD00.D.SRF.PERSON.LITE.PHONE.LOAD
    -
      mqQueueName: QMD00.D.SRF.PERSON.PHONE.LOAD
  </code></pre>