java - Spring应用程序监听器-ContextRefreshedEvent java :comp/env/jdbc/db not found

标签 java spring

我试图在应用程序首次启动时进行一些数据库清理。 首先,我定义了 JNDI 连接,如下所示:

@Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() {
    return new TomcatEmbeddedServletContainerFactory() {

        @Override
        protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
                Tomcat tomcat) {
            tomcat.enableNaming();
            return super.getTomcatEmbeddedServletContainer(tomcat);
        }

        @Override
        protected void postProcessContext(Context context) {
            ContextResource resource = new ContextResource();
            resource.setName("jdbc/myDataSource");
            resource.setType(DataSource.class.getName());
            resource.setProperty("driverClassName", "your.db.Driver");
            resource.setProperty("url", "jdbc:yourDb");

            context.getNamingResources().addResource(resource);
        }
    };
}

然后我希望在ApplicationListener ContextRefreshedEvent中检索资源,ApplicationListener实现如下:

@Component
public class StartupConfiguration implements ApplicationListener<ContextRefreshedEvent>
{
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event)
    {
        ApplicationContext ctx = event.getApplicationContext();

        Context initialContext = new InitialContext();
        DataSource datasource = (DataSource) initialContext.lookup("java:comp/env/jdbc/myDataSource");
        ...
    }

}

问题是它无法找到 java:comp/env/jdbc/myDataSource,我已经使用各种事件进行了测试,唯一有效的事件是在我所做的 RequestHandledEvent 中不认为这是一个好的解决方案。

最佳答案

我在以下堆栈溢出问题中找到了答案 stackoverflow.com/questions/27822619

我会引用安迪·威尔金森

Tomcat uses the thread's context class loader to determine the JNDI context to perform the lookup against. If the thread context class loader isn't the web app classloader then the JNDI context is empty, hence the lookup failure.

安迪·威尔金森建议的修复

@Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() {
return new TomcatEmbeddedServletContainerFactory() {

    @Override
    protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
            Tomcat tomcat) {
        tomcat.enableNaming();
        TomcatEmbeddedServletContainer container = 
                super.getTomcatEmbeddedServletContainer(tomcat);
        for (Container child: container.getTomcat().getHost().findChildren()) {
            if (child instanceof Context) {
                ClassLoader contextClassLoader = 
                        ((Context)child).getLoader().getClassLoader();
                Thread.currentThread().setContextClassLoader(contextClassLoader);
                break;
            }
        }
        return container;
    }

    @Override
    protected void postProcessContext(Context context) {
        ContextResource resource = new ContextResource();
        resource.setName("jdbc/myDataSource");
        resource.setType(DataSource.class.getName());
        resource.setProperty("driverClassName", "your.db.Driver");
        resource.setProperty("url", "jdbc:yourDb");

        context.getNamingResources().addResource(resource);
    }
};
}

关于java - Spring应用程序监听器-ContextRefreshedEvent java :comp/env/jdbc/db not found,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31482356/

相关文章:

java - 使用 getAssets() 给出错误 "The method getAssets() is undefined for the type ClassName"?

java - 使用 Spring JPA 查询从序列中获取 nextval

java - Spring + jackson : Wrapping Response Body in response object

java - 通过 RMI : any sense? 访问 session 范围的 bean

Spring Data JPA 将原生查询结果映射到非实体 POJO

java - 一种在字母数组中搜索单词的算法

java - Spring data + MongoTemplate - 对文档的约束不会影响插入\保存

java - 为什么人们如此害怕使用 clone()(在集合和 JDK 类上)?

java - Java 8 中的流 : simple solution to use parallelstream() on a cluster?

java - 在 Spring Controller 中声明互参数