当前位置: 首页 > 知识库问答 >
问题:

使用Spring Boot自动配置从JNDI检索JMS ConnectionFactory

阚英睿
2023-03-14

我想使用JMS的Spring引导自动配置来连接到远程JNDI,并根据通过application.properties文件中的spring.jms.jndi属性填充的名称检索ConnectionFactory。

我注意到Spring Boot自动配置依赖于JndiConnectionFactoryAutoConfiguration类来完成这项工作,而这个类又将调用JndiTemplate类来完成查找。问题是JndiTemplate类的environment属性的值为null,因此我们无法创建intialContext。

事实上,我注意到在启动应用程序和加载JndiConnectionFactoryAutoConfiguration类中定义的配置之前,JndiTemplate类是在没有参数构造函数的情况下实例化的。

我的问题:如何通过指定属性列表(Context.INITIAL_CONTEXT_FACTORY, Context.PROVIDER_URL...)来实例化JndiTemboard?知道JmsTemboard有一个接受Properties对象的构造函数。

仅供参考:我的应用程序是一个简单的jar,目前不在服务器上运行。

共有1个答案

薛兴德
2023-03-14

对于那些对答案感兴趣的人,必须使用VM选项来传递所需的JNDI属性。

下面是一个使用ActiveMQ的示例:

VM选项:

-Djava.naming.provider.url=tcp://hostname:61616

-Djava.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory

和spring属性文件(application.properties)必须包含连接工厂的JNDI名称:

spring.jms.jndi-name=ConnectionFactory

更好的是,您可以使用配置从JNDI为连接工厂提供fin。在我的项目中,我们通过创建可以在所有微服务中使用的jms启动器来完成。

属性类别:

import lombok.*;
import org.springframework.boot.context.properties.ConfigurationProperties;


@Getter
@Setter
@ToString
@NoArgsConstructor
@EqualsAndHashCode
@ConfigurationProperties( prefix = "custom.jms" )
public class CustomJmsProperties {
    private String jndiName;
    private String contextFactoryClass;
    private String providerUrl;
    private String username;
    private String password;
}

配置类:

import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter;
import org.springframework.jndi.JndiLocatorDelegate;

import javax.jms.ConnectionFactory;
import javax.naming.Context;
import javax.naming.NamingException;
import java.util.Properties;

@Configuration
@ConditionalOnProperty( "custom.jms.jndi-name" )
@ConditionalOnMissingBean( ConnectionFactory.class )
@EnableConfigurationProperties( { CustomJmsProperties.class } )
@AutoConfigureAfter( { JndiConnectionFactoryAutoConfiguration.class } )
public class CustomJndiConnectionFactoryAutoConfiguration {

    @Bean
    public ConnectionFactory connectionFactory( CustomJmsProperties customJmsProperties ) throws NamingException {
        ConnectionFactory connectionFactory = lookupForConnectionFactory( customJmsProperties );
        return getEnhancedUserCredentialsConnectionFactory( customJmsProperties, connectionFactory );
    }

    private ConnectionFactory lookupForConnectionFactory( final CustomJmsProperties customJmsProperties ) throws NamingException {
        JndiLocatorDelegate jndiLocatorDelegate = new JndiLocatorDelegate();
        Properties jndiProperties = getJndiProperties( customJmsProperties );
        jndiLocatorDelegate.setJndiEnvironment( jndiProperties );
        return jndiLocatorDelegate.lookup( customJmsProperties.getJndiName(), ConnectionFactory.class );
    }

    private Properties getJndiProperties( final CustomJmsProperties customJmsProperties ) {
        Properties jndiProperties = new Properties();
        jndiProperties.setProperty( Context.PROVIDER_URL, customJmsProperties.getProviderUrl() );
        jndiProperties.setProperty( Context.INITIAL_CONTEXT_FACTORY, customJmsProperties.getContextFactoryClass() );
        if ( StringUtils.isNotEmpty( customJmsProperties.getUsername() ) ) {
            jndiProperties.setProperty( Context.SECURITY_PRINCIPAL, customJmsProperties.getUsername() );
        }
        if ( StringUtils.isNotEmpty( customJmsProperties.getPassword() ) ) {
            jndiProperties.setProperty( Context.SECURITY_CREDENTIALS, customJmsProperties.getPassword() );
        }
        return jndiProperties;
    }

    private UserCredentialsConnectionFactoryAdapter getEnhancedUserCredentialsConnectionFactory( final CustomJmsProperties customJmsProperties,
                                                                                                 final ConnectionFactory connectionFactory ) {
        UserCredentialsConnectionFactoryAdapter enhancedConnectionFactory = new UserCredentialsConnectionFactoryAdapter();
        enhancedConnectionFactory.setTargetConnectionFactory( connectionFactory );
        enhancedConnectionFactory.setUsername( customJmsProperties.getUsername() );
        enhancedConnectionFactory.setPassword( customJmsProperties.getPassword() );
        enhancedConnectionFactory.afterPropertiesSet();
        return enhancedConnectionFactory;
    }
}

项目的属性文件:

custom.jms.provider-url=tcp://hostname:61616
custom.jms.context-factory-class=org.apache.activemq.jndi.ActiveMQInitialContextFactory
custom.jms.jndi-name=ConnectionFactory
 类似资料:
  • 本机Spring Boot自动配置(例如one)也可以检测主类中声明的bean(例如注释的方法)。 如何对主类中声明的bean进行正确的bean检测? 编辑

  • 4.1 根据条件的自动配置 @conditional是基于条件的自动配置,一般配合Condition接口一起使用,只有接口实现类返回true,才装配,否则不装配. 用实现了Condition接口的类传入@Conditional中 @Conditional可以标记在配置类的方法中,也可以标记在配置类上.标记的位置不同,作用域不同. @Conditional可以传入多个实现了condition接口的类

  • 本文向大家介绍浅谈springboot自动配置原理,包括了浅谈springboot自动配置原理的使用技巧和注意事项,需要的朋友参考一下 从main函数说起 一切的开始要从SpringbootApplication注解说起。 其中最重要的就是EnableAutoConfiguration注解,开启自动配置。 通过Import注解导入AutoConfigurationImportSelector。在这

  • 我有一个简单的SpringBoot应用程序,我想使用AutoConfiguration来配置Tomcat jdbc池数据源。 我正在使用这些Spring依赖项: 以下是我的 application.yml 文件中的数据源属性: 我确定正在加载属性,因为应用程序正在获取其他值。 我在配置文件中将 bean 定义为: 我将数据源注入到我的DAO中,如下所示: 如果我在getDataSource()方法

  • 我使用Reactjs作为前端。我想从javascript端检索自定义属性。就像这个答案所说的。 https://stackoverflow.com/a/32890003/2940265 但我找不到如何在javascript端实现它。 我在Chrome中进行了调试,但找不到适合自定义属性的结果。 请帮帮忙

  • 我在使用Spring ApplicationContext.xml文件中的JNDI配置dataSource bean时遇到了困难。 我的applicationContext.xml条目如下所示: 通过这些配置,我在Tomcat控制台上不断得到这样的错误: 由:javax.naming.NameNotFoundException:Name[jdbc/myapp]在此上下文中没有绑定。找不到[jdbc