Connect JMS queue using JNDI with Spring Boot

前端 未结 1 1857
梦谈多话
梦谈多话 2021-02-10 20:40

I had a hard time figuring out how to implement a Spring Boot JMS Listener, listening to an ActiveMQ queue within a JBoss application server. Therefore I choose to post a questi

1条回答
  •  孤独总比滥情好
    2021-02-10 21:09

    ActiveMQ is supported by Spring Boot autoconfiguration, but since it was inside the JBoss server Spring Boot was failing to connect ActiveMQ. In fact you need to define connectionFactory and jmsListenerContainerFactory beans yourself by doing a lookup on the JNDI provider.

    @Configuration
    @EnableJms
    public class ActiveMqConnectionFactoryConfig {
    
      @Value("${broker.url}")
      String brokerUrl;
    
      @Value("${borker.username}")
      String userName;
    
      @Value("${borker.password}")
      String password;
    
      @Value("${queue}")
      String queueName;
    
      private static final String INITIAL_CONTEXT_FACTORY = "org.jboss.naming.remote.client.InitialContextFactory";
      private static final String CONNECTION_FACTORY = "jms/RemoteConnectionFactory";
    
    
      @Bean
      public ConnectionFactory connectionFactory() {
        try {
          System.out.println("Retrieving JMS queue with JNDI name: " + CONNECTION_FACTORY);
          JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
          jndiObjectFactoryBean.setJndiName(CONNECTION_FACTORY);
    
          jndiObjectFactoryBean.setJndiEnvironment(getEnvProperties());
          jndiObjectFactoryBean.afterPropertiesSet();
    
          return (QueueConnectionFactory) jndiObjectFactoryBean.getObject();
    
        } catch (NamingException e) {
          System.out.println("Error while retrieving JMS queue with JNDI name: [" + CONNECTION_FACTORY + "]");
        } catch (Exception ex) {
          System.out.println("Error");
        }
        return null;
      }
    
      Properties getEnvProperties() {
        Properties env = new Properties();
        env.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_FACTORY);
        env.put(Context.PROVIDER_URL, brokerUrl);
        env.put(Context.SECURITY_PRINCIPAL, userName);
        env.put(Context.SECURITY_CREDENTIALS, password);
        return env;
      }
    
      @Bean
      public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(ConnectionFactory connectionFactory) {
    
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        JndiDestinationResolver jndiDestinationResolver = new JndiDestinationResolver();
    
        jndiDestinationResolver.setJndiEnvironment(getEnvProperties());
        factory.setDestinationResolver(jndiDestinationResolver);
        return factory;
      }
    

    Then if you want to consume the queue you just define your JMS consumer class with a method annotated with @JmsListener(destination = "${queue}")

     @JmsListener(destination = "${queue}")
      public void receive(Message message) {
        System.out.println("Received Message: " + message);
      }
    

    Hope that helps save a few hours of research ;)

    Cheers

    0 讨论(0)
提交回复
热议问题