【问题标题】:Spring Boot and Tomcat not finding JNDI resourcesSpring Boot 和 Tomcat 找不到 JNDI 资源
【发布时间】:2017-05-21 15:50:04
【问题描述】:

我正在使用Spring Boot 1.4.2.RELEASE。我也在使用Tomcat 8.5.9(未嵌入)和Java 8

在我的application.properties 文件中,我可以使用以下方法手动配置我的数据源:

spring.datasource.url = jdbc:as400://blahblah....
spring.datasource.username = myuser
spring.datasource.password = password
spring.datasource.driver-class-name=com.ibm.as400.access.AS400JDBCDriver

这很好用。但是,我们使用 Tomcat 来托管我们的连接。在 Tomcat 中,我们有:

<GlobalNamingResources>
    <Resource name="jdbc/BLAH" ..... />
</GlobalNamingResources>

然后我将 application.properties 更改为:

spring.datasource.jndi-name=java:comp/env/jdbc/BLAH
spring.jpa.database-platform=org.hibernate.dialect.DB2400Dialect
spring.jpa.show-sql=true

现在,我什至无法构建应用程序。我得到以下异常:

o.s.w.c.s.GenericWebApplicationContext   : 
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': 
Unsatisfied dependency expressed through constructor parameter 0; 
nested exception is org.springframework.beans.factory.BeanCreationException: 

Error creating bean with name 'dataSource' defined in class path resource 
[org/springframework/boot/autoconfigure/jdbc/JndiDataSourceAutoConfiguration.class]: 

Bean instantiation via factory method failed; 
nested exception is org.springframework.beans.BeanInstantiationException: 
Failed to instantiate [javax.sql.DataSource]: 

Factory method 'dataSource' threw exception; nested exception is 
org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException: 

Failed to look up JNDI DataSource with name 'java:comp/env/jdbc/BLAH'; 

nested exception is javax.naming.NoInitialContextException: 
Need to specify class name in environment or system property, or as an applet parameter, 
or in an application resource file:  java.naming.factory.initial

NoInitialContextException 让我相信 Spring Boot 找不到正在运行的 Tomcat,因此它无法执行 JNDI 查找。

请记住,确切相同的设置对我们使用 Spring Boot 1.2.5.RELEASE 有效。我们有另一个使用 1.2.5.RELEASE、Java 7 和 Tomcat 7 的应用程序,它使用 JNDI 资源工作。但是使用最新的 Spring Boot,Java 8 和 Tomcat 8 却没有。

感谢任何帮助。

我的 pom.xml 中的一些 sn-ps:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.2.RELEASE</version>
    <relativePath/>
</parent>
...
<dependencies>
    <dependency>
        <groupId>net.sf.jt400</groupId>
        <artifactId>jt400</artifactId>
        <version>6.7</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>com.vaadin</groupId>
        <artifactId>vaadin-spring-boot-starter</artifactId>
        <version>1.1.1</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
    ....
</dependencies>

其他代码sn-ps:

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}


@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(basePackages = "com.company.myapp")
@EnableJpaRepositories(basePackages = "com.company.myapp.repository")
@EnableTransactionManagement
@EnableVaadin
@EnableVaadinServlet
public class AppConfiguration {
}

更新

我已经使用server.xml 中的GlobalNamingResources 在Tomcat(外部)中创建了资源。 这适用于其他应用程序。

更新 2

忘了提到我在src/main/webapp/META-INF/context.xml 文件中有以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <ResourceLink global="jdbc/BLAH"
                  name="jdbc/BLAH"
                  type="com.mchange.v2.c3p0.ComboPooledDataSource"/>
</Context>

更新 3

另外,我想澄清一下问题发生在maven package 步骤中。

【问题讨论】:

  • 您是否尝试过使用前面的斜杠引用资源? (即 java:/...) spring.datasource.jndi-name=java:/comp/env/jdbc/BLAH
  • 对不起,我没听懂你的意思。
  • 不。还是一样。我也试过/jdbc/BLAHjdbc/BLAH

标签: java spring tomcat spring-boot jndi


【解决方案1】:

如果您在独立的 Tomcat(非嵌入式)上进行部署,我很确定您需要在 Tomcat 上定义 JNDI 资源,而不是在 application.properties 中,而是在 server.xml 中,如下所示:

<GlobalNamingResources>
    <Resource name="jdbc/serverdb" auth="Container" type="javax.sql.DataSource"
              maxTotal="5" maxIdle="5" maxWaitMillis="30000"
              validationQuery="select 1" testOnBorrow="true"
              username="$AUTH_DB_USER" password="$AUTH_DB_PASSWORD" driverClassName="org.postgresql.Driver"
              url="jdbc:postgresql://$AUTH_DB_HOST:5432/$AUTH_DB_NAME"/>
</GlobalNamingResources>

【讨论】:

  • 我已经做到了。我不是很清楚,但这就是我们通常做应用程序的方式。我会更新以反映我已经做到了。
  • 我有两个提示,第一个是你可能需要context.xml中的ResourceLink,它引用了server.xml中定义的全局资源。第二步是在 JndiLocatorSupport.lookup 中设置断点(我猜它是在 Boot 中使用的),然后调试 JNDI 树。
  • 感谢您的提示。我已经有了上下文条目。我将标记我的问题以反映这一点。我也试试断点。
  • 我还没有尝试使用带有 Boot war 文件的 JDNI,但是我有几个 Tomcat 8 应用程序可以与 JNDI 一起正常工作,但是我自己创建了 JndiDataSourceLookup 来获取数据源。我们不以“java:comp/env/”为前缀,但那是因为我们显式设置了 JndiDataSourceLookup.setResourceRef(true),所以它会加上前缀 -default 为 false,因此您可能需要设置它
  • 你有什么例子可以说明你是如何做到的吗?谢谢。
猜你喜欢
  • 1970-01-01
  • 2016-07-12
  • 1970-01-01
  • 2015-12-11
  • 1970-01-01
  • 2020-01-03
  • 2019-08-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多