运行带有嵌入式容器和JNDI的Spring Boot应用程序

时间:2018-01-04 08:51:58

标签: java maven spring-boot spring-data jndi

我有一个具有spring.datasource.jndi-name=java:/foo属性的Spring Boot应用程序,它在WildFly下运行良好。

我希望使用嵌入式容器(即mvn spring-boot:run)运行相同的应用程序,但是当WildFly在其配置中配置了JNDI数据源时,嵌入式容器不会即是{&1;得到:

org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException:
Failed to look up JNDI DataSource with name 'java:/foo'

我想我必须在某处包含一个XML文件来配置嵌入式容器的JNDI数据源,但我找不到有关此文档的文档。我刚刚找到了有关如何在Java源代码中创建JNDI数据源的教程,但我想避免这种情况,以便相同的应用程序可以在外部和嵌入式容器中运行。

我怎样才能做到这一点?

EDIT This answer展示了如何在Tomcat中创建JNDI上下文,以便在其他容器(例如WildFly)中运行相同的应用程序。我正在寻找一个答案,让应用程序在不同的容器中使用相同的源运行,例如只需使用在WildFly中配置的相同JNDI资源配置嵌入式容器。

2 个答案:

答案 0 :(得分:3)

要使应用程序也可以在其他启用jndi的容器中部署,请执行以下操作:

  1. 扩展TomcatEmbeddedServletContainerFactory并启用jndi命名并添加资源
  2. 使用Profile annotation创建一个配置类,该配置类公开扩展的TomcatEmbeddedServletContainerFactory bean
  3. 参见下面的代码;

    扩展TomcatEmbeddedServletContainerFactory

    class EmbeddedServletContainerFactory extends TomcatEmbeddedServletContainerFactory {
        @Override
        protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {
            tomcat.enableNaming(); // This is essential. Naming is disabled by default which needs enabling
            return super.getTomcatEmbeddedServletContainer(tomcat);
        }
    
        @Override
        protected void postProcessContext(Context context) {
            ContextResource resource = new ContextResource();
            // All the below properties you can retrieve via preferred method
            resource.setName("jdbc/test");
            resource.setAuth("Container");
            resource.setType(DataSource.class.getName());
            resource.setProperty("driverClassName", driverClass);
            resource.setProperty("factory", "org.apache.commons.dbcp2.BasicDataSourceFactory");
            resource.setProperty("url", dbUrl);
            resource.setProperty("username", username);
            resource.setProperty("password", password);
            context.getNamingResources().addResource(resource);
        }
    }
    

    暴露bean的Config类

    @Profile("embedded")
    @Configuration
    public class EmbeddedConfig {
    
        @Bean
        public TomcatEmbeddedServletContainerFactory tomcatFactory() {
            return new EmbeddedServletContainerFactory();
        }
    }
    

    如果你在java配置中不喜欢这样,你可以用xml方式做同样的事情

    <beans profile="embedded">
        <bean id="TomcatEmbeddedServletContainerFactory" class="EmbeddedServletContainerFactory" />
    </bean>
    

    现在,您可以在pom中对配置文件名称进行硬编码,或通过jvm参数添加;

    mvn spring-boot:run -Drun.profiles=embedded
    

    您的其他代码保持不变,并且在其他容器中的行为相同。通过jndi查找数据源也是一样的。此代码确保在嵌入式容器中实际存在绑定到该jndi的数据源。

答案 1 :(得分:0)

@ Setu的回答对我不起作用,因为在TomcatEmbeddedServletContainerFactory刷新后创建了ApplicationContext,但我需要在ApplicationContext刷新期间使用JNDI。

相反,我在启动Spring Boot应用程序之前设置了以下系统属性以启用Tomcat命名:

System.setProperty(Context.URL_PKG_PREFIXES, "org.apache.naming");
System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
                   "org.apache.naming.java.javaURLContextFactory");