You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 2内嵌Tomcat中JNDI注册及使用失败求助

Hey there! Let's dig into why your JNDI datasource isn't being found in your embedded Tomcat setup with Spring Boot 2.0.0.RELEASE. The core issue here is a timing mismatch between when Spring tries to look up the JNDI resource and when Tomcat actually binds it to the naming context. Here's how to fix it step by step:


Problem Breakdown

Your error Name [jdbc/OracleDSNonXA] is not bound in this Context happens because Spring's context initializes and tries to fetch the JNDI datasource before Tomcat finishes registering the resource in its naming context. Let's adjust the configuration to sync these processes.


Step 1: Fix Tomcat Factory Configuration

Your TomcatServletWebServerFactory setup is close, but we need to ensure the naming context initializes properly and the resource is bound correctly. Update your startup class bean:

@Bean
public ServletWebServerFactory tomcatFactory() {
    return new TomcatServletWebServerFactory() {
        @Override
        protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
            tomcat.enableNaming();
            // Prevent auto-deploy issues that can delay context setup
            tomcat.getHost().setAutoDeploy(false);
            return super.getTomcatWebServer(tomcat);
        }

        @Override
        protected void postProcessContext(Context context) {
            ContextResource resource = new ContextResource();
            // Use the base name here; we'll add the java:comp/env/ prefix in lookup
            resource.setName("jdbc/OracleDSNonXA");
            resource.setType(javax.sql.DataSource.class.getName());
            resource.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver");
            resource.setProperty("url", "DBURL");
            resource.setProperty("username", "DBUSER");
            resource.setProperty("password", "PASSWORD");
            
            context.getNamingResources().addResource(resource);
            
            // Add a resource link to ensure cross-context lookup works
            ContextResourceLink resourceLink = new ContextResourceLink();
            resourceLink.setName("jdbc/OracleDSNonXA");
            resourceLink.setGlobal("jdbc/OracleDSNonXA");
            resourceLink.setType(javax.sql.DataSource.class.getName());
            context.getNamingResources().addResourceLink(resourceLink);
        }
    };
}

Step 2: Adjust JNDI DataSource Bean

We need to make sure Spring doesn't try to look up the JNDI resource too early. Update your jndiDataSource bean in ApplicationConfig:

@Bean(destroyMethod = "")
public DataSource jndiDataSource() throws NamingException {
    JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
    // Match the full JNDI path with the prefix
    bean.setJndiName("java:comp/env/jdbc/OracleDSNonXA");
    bean.setProxyInterface(javax.sql.DataSource.class);
    bean.setLookupOnStartup(false);
    // Lazy init ensures we wait until Tomcat is ready
    bean.setLazyInit(true);
    bean.afterPropertiesSet();
    return (DataSource) bean.getObject();
}

Step 3: Clean Up Hibernate Configuration

Your Hibernate setup has a potential conflict. The hibernate.transaction.manager_lookup_class setting is usually for standalone Hibernate setups, not when using Spring's transaction management. Comment it out:

// jpaProperties.setProperty("hibernate.transaction.manager_lookup_class", trxManagerLookupClass);

Step 4: Quick Pre-Flight Checks

  • Verify Oracle Driver: Make sure the Oracle JDBC driver is in your dependencies (e.g., for Maven):
    <dependency>
        <groupId>com.oracle.database.jdbc</groupId>
        <artifactId>ojdbc8</artifactId>
        <version>12.2.0.1</version>
    </dependency>
    
  • Remove Auto-Configured Datasource: If you have spring.datasource.* properties in application.properties, delete them—Spring Boot will auto-create a datasource that conflicts with your JNDI setup.
  • Double-Check Credentials/URL: Ensure your DBURL, DBUSER, and PASSWORD are correct (no typos!).

Why This Works

In Spring Boot 2.x, embedded Tomcat starts in parallel with the Spring context. By enabling Tomcat's naming early, adding the resource link, and making the JNDI bean lazy-init, we ensure Spring waits until Tomcat has fully bound the datasource before trying to look it up.

内容的提问来源于stack exchange,提问作者sahas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:20:01