英文:
Configure DataSource Using JNDI Using external Tomcat 9 Server: Spring Boot
问题
我有一个打包为WAR文件的SpringBootApplication:
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
在application.properties
文件中:
spring.datasource.jndi-name=java:comp/env/jdbc/bonanza
但是当我在Tomcat 9中部署WAR文件时,日志中出现以下消息:
名称[spring.datasource.jndi-name]未绑定到此上下文。无法找到[spring.datasource.jndi-name]。返回null。
日志:
12:37:53.989 [main] DEBUG o.springframework.jndi.JndiTemplate - 使用名称[java:comp/env/spring.datasource.jndi-name]查找JNDI对象
12:37:53.989 [main] DEBUG o.s.jndi.JndiLocatorDelegate - 转换后的JNDI名称[java:comp/env/spring.datasource.jndi-name]未找到 - 尝试原始名称[spring.datasource.jndi-name]。javax.naming.NameNotFoundException: 名称[spring.datasource.jndi-name]未在此上下文中绑定。无法找到[spring.datasource.jndi-name]。
12:37:53.990 [main] DEBUG o.springframework.jndi.JndiTemplate - 使用名称[spring.datasource.jndi-name]查找JNDI对象
12:37:53.991 [main] DEBUG o.s.jndi.JndiPropertySource - 对名称[spring.datasource.jndi-name]进行JNDI查找,抛出带有消息的NamingException:名称[spring.datasource.jndi-name]未在此上下文中绑定。无法找到[spring.datasource.jndi-name]。返回null。
12:37:53.995 [main] DEBUG o.springframework.jndi.JndiTemplate - 使用名称[java:comp/env/spring.datasource.jndi-name]查找JNDI对象
12:37:53.996 [main] DEBUG o.s.jndi.JndiLocatorDelegate - 转换后的JNDI名称[java:comp/env/spring.datasource.jndi-name]未找到 - 尝试原始名称[spring.datasource.jndi-name]。javax.naming.NameNotFoundException: 名称[spring.datasource.jndi-name]未在此上下文中绑定。无法找到[spring.datasource.jndi-name]。
12:37:53.996 [main] DEBUG o.springframework.jndi.JndiTemplate - 使用名称[spring.datasource.jndi-name]查找JNDI对象
12:37:53.997 [main] DEBUG o.s.jndi.JndiPropertySource - 对名称[spring.datasource.jndi-name]进行JNDI查找,抛出带有消息的NamingException:名称[spring.datasource.jndi-name]未在此上下文中绑定。无法找到[spring.datasource.jndi-name]。返回null。
12:37:53.998 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - 在PropertySource“configurationProperties”中找到键'spring.datasource.jndi-name',其值为String类型
在我的tomcat9/conf/context.xml
文件中:
<Resource name="jdbc/bonanza"
auth="Container"
type="javax.sql.DataSource"
maxTotal="100"
maxIdle="30"
maxWaitMillis="10000"
username="a_usr"
password="Mu*7gydlcdstg100@"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://172.175.77.55:3306/a_db"
/>
英文:
I have a SpringBootApplication, packaged as war file:
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
on the application.properties:
spring.datasource.jndi-name=java:comp/env/jdbc/bonanza
but on the logs I see those messages when I deploy the war in the Tomcat 9:
Name [spring.datasource.jndi-name] is not bound in this Context. Unable to find [spring.datasource.jndi-name].. Returning null.
the logs:
12:37:53.989 [main] DEBUG o.springframework.jndi.JndiTemplate - Looking up JNDI object with name [java:comp/env/spring.datasource.jndi-name]
12:37:53.989 [main] DEBUG o.s.jndi.JndiLocatorDelegate - Converted JNDI name [java:comp/env/spring.datasource.jndi-name] not found - trying original name [spring.datasource.jndi-name]. javax.naming.NameNotFoundException: Name [spring.datasource.jndi-name] is not bound in this Context. Unable to find [spring.datasource.jndi-name].
12:37:53.990 [main] DEBUG o.springframework.jndi.JndiTemplate - Looking up JNDI object with name [spring.datasource.jndi-name]
12:37:53.991 [main] DEBUG o.s.jndi.JndiPropertySource - JNDI lookup for name [spring.datasource.jndi-name] threw NamingException with message: Name [spring.datasource.jndi-name] is not bound in this Context. Unable to find [spring.datasource.jndi-name].. Returning null.
12:37:53.995 [main] DEBUG o.springframework.jndi.JndiTemplate - Looking up JNDI object with name [java:comp/env/spring.datasource.jndi-name]
12:37:53.996 [main] DEBUG o.s.jndi.JndiLocatorDelegate - Converted JNDI name [java:comp/env/spring.datasource.jndi-name] not found - trying original name [spring.datasource.jndi-name]. javax.naming.NameNotFoundException: Name [spring.datasource.jndi-name] is not bound in this Context. Unable to find [spring.datasource.jndi-name].
12:37:53.996 [main] DEBUG o.springframework.jndi.JndiTemplate - Looking up JNDI object with name [spring.datasource.jndi-name]
12:37:53.997 [main] DEBUG o.s.jndi.JndiPropertySource - JNDI lookup for name [spring.datasource.jndi-name] threw NamingException with message: Name [spring.datasource.jndi-name] is not bound in this Context. Unable to find [spring.datasource.jndi-name].. Returning null.
12:37:53.998 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Found key 'spring.datasource.jndi-name' in PropertySource 'configurationProperties' with value of type String
on my tomcat9/conf/context.xml:
<Resource name="jdbc/bonanza"
auth="Container"
type="javax.sql.DataSource"
maxTotal="100"
maxIdle="30"
maxWaitMillis="10000"
username="a_usr"
password="Mu*7gydlcdstg100@"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://172.175.77.55:3306/a_db"
/>
答案1
得分: 1
根据错误提示,Spring Boot 无法在 JNDI 查找中找到密钥。在 Spring Boot 的嵌入式 Tomcat 中禁用了 JNDI,所以您需要使用 Tomcat#enableNaming
启用它,一旦启用后,您需要在 JNDI 中创建一个查找条目。您可以参考下面的代码,这些代码是我从一个 Spring Boot 项目维护者的存储库 GitHub repo JNDI-Tomcat 复制来的:
@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/bonanza");
resource.setType(DataSource.class.getName());
resource.setProperty("driverClassName", "your.db.Driver");
resource.setProperty("url", "jdbc:yourDb");
context.getNamingResources().addResource(resource);
}
};
}
[编辑]
如果您没有使用嵌入式 Tomcat 服务器,可以通过配置 Tomcat 配置文件来配置 JNDI:
在 server.xml
中,在 <GlobalNamingResources>
下创建一个资源:
<Resource auth="Container" driverClassName="..."
maxActive="..."
maxIdle="..."
maxWait="..."
name="jdbc/bonanza"
username="..."
password="..."
type="..."
url="..."/>
在 context.xml
中,您可以链接资源:
<context>
<ResourceLink auth="Container" name="jdbc/bonanza" global="jdbc/bonanza" type="javax.sql.DataSource" />
</context>
此外,请确保您不是使用 Spring Boot 的 main
方法启动应用程序。您需要使用 Maven/Gradle 构建 WAR 文件,然后将其部署到 Tomcat 并进行测试。
英文:
As the error suggests, spring boot cannot find the key in the JNDI lookup. JNDI is disabled in Spring boot's embedded Tomcat so you would need to enable it using Tomcat#enableNaming
and once that is done you would need to create a lookup entry in JNDI. You can refer to the below code which I copied from one of the spring boot project maintainers repository GitHub repo JNDI-Tomcat
@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/bonanza");
resource.setType(DataSource.class.getName());
resource.setProperty("driverClassName", "your.db.Driver");
resource.setProperty("url", "jdbc:yourDb");
context.getNamingResources().addResource(resource);
}
};
}
[Edit]
As you are not using embedded tomcat server, you can configure JNDI by configuring it using tomcat config files:
In server.xml, create a Resource under <GlobalNamingResources>
<Resource auth="Container" driverClassName="..."
maxActive="..."
maxIdle="..."
maxWait="..."
name="jdbc/bonanza"
username="..."
password="..."
type="..."
url="..."/>
In Context.xml, you can link the resource
<context>
<ResourceLink auth="Container" name="jdbc/bonanza" global="jdbc/bonanza" type="javax.sql.DataSource" />
</context>
Also, make sure you are not starting the application using the spring-boot main
method. You need to build the war file using maven/gradle and then deploy it to the tomcat and test it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论