【问题标题】:Spring Boot: Reading spring.jms.jndi-name property from application.properties file using a Java Bean classSpring Boot:使用 Java Bean 类从 application.properties 文件中读取 spring.jms.jndi-name 属性
【发布时间】:2015-10-08 05:34:01
【问题描述】:

我正在使用 JNDI 查找 来获取 tomcat 服务器上 Websphere MQ 代理的连接对象。我正在使用 JmsTemplate 将消息发送到 WMQ 代理上的队列并试图避免基于 Spring Xml 的配置,因此我配置了 Spring boot 的 application.properties 文件以指定 JNDI 查找 name.below 是 application.properties 文件中的属性。

spring.jms.jndi-name= java:comp/env/XXXX

我正在使用 Spring bean 来定义 JmsTemplate,下面是它的代码。

@Configuration
public class JmsMessageTemplateBean {

    //@Value("${spring.jms.jndi-name}")
    //private ConnectionFactory connectionFactory;

    @Bean
    public JmsTemplate jmsTemplate() throws Exception{
        JmsTemplate jmsMessagingTemplate = new JmsTemplate();
        jmsMessagingTemplate.setDefaultDestinationName("Some Queue");
        jmsMessagingTemplate.setConnectionFactory(connectionFactory);
        return jmsMessagingTemplate;
    }
}

我有几个问题:

1.如何从 application.properties 文件中读取 JNDI 属性,并将 Connection 对象设置为上述 bean 中的 Jms 模板。

2.我观察到 JNDI 查找 中的连接对象是MQQueueConnectionFactory,而我研究过的JmsTemplate 支持javax.jms.ConnectionFactory 对象。有没有办法将MQQueueConnectionfactory 对象转换为javax.jms.Connectionfactory

感谢您的回答。

【问题讨论】:

  • 你正在让它变得复杂。删除您的 bean,您已经获得了带有 Spring Boots 自动配置的 JmsTemplateMQQueueConnectionFactoryConnectionFactory
  • @M. Deinum 感谢您的回复。使用 Spring 的自动启动配置,我得到了 JmsTemplate,但它的连接工厂默认查看 localhost 代理。如何配置 JmsTemplate 以使用 application.properties 文件中指定的 spring.jms.jndi-name。
  • 如果您确实指定了应该用于查找的属性。还要确保你的类路径中没有像 activemq 这样的东西。您必须使用 Spring Boot 1.2 或更高版本才能正常工作。

标签: java spring spring-boot ibm-mq


【解决方案1】:

我也很难弄清楚如何实现 Spring Boot JMS 侦听器,侦听 JBoss 应用程序服务器中的 ActiveMQ 队列。

Spring Boot 自动配置支持 ActiveMQ,但由于它位于 JBoss 服务器内部,因此 Spring Boot 无法连接 ActiveMQ。 事实上,您需要通过查找 JNDI 提供者自己定义 connectionFactoryjmsListenerContainerFactory bean。

@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;
  }

然后,如果您想使用队列,您只需使用带有 @JmsListener(destination = "${queue}") 注释的方法定义您的 JMS 消费者类

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

希望这有助于节省几个小时的研究时间;) 干杯

【讨论】:

  • 这是一个非常详细的答案,但问题是关于 IBM 的 Websphere MQ,而您提供的答案是关于 ActiveMQ,我不确定您为 ActiveMQ 提供的底层配置详细信息是否会帮助某人为 IBM 的 MQ 解决问题,如果是这样,他们可能值得留在这个问题上。如果不是,那么最好找到一个与 ActiveMQ 相关的问题来提供这个答案,甚至问你自己的问题并自己回答。
  • 谢谢乔希,是的,你是对的,我最好创建一个新问题并回答它。我发布这个是因为它是与我面临的实施问题最相关的一个,但原始问题和我的答案之间仍然存在相当大的差距:)
  • @ThomasJoeisseint 我正在尝试在 JBOSS 服务器中连接 activemq。但是,我得到以下错误原因:java.lang.IllegalArgumentException:org.springframework.jms.support.JmsAccessor.afterPropertiesSet(JmsAccessor.java:169)需要属性'connectionFactory'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-24
  • 2017-06-17
  • 1970-01-01
  • 2018-01-07
  • 2018-09-15
  • 2019-09-18
  • 2016-11-11
相关资源
最近更新 更多