Spring Boot 独立 JAR 应用程序的 JNDI 配置
JNDI configuration for Springboot standalone JAR application
我用 Springboot 创建了一个 JAR 应用程序。
我在 Tomcat 服务器下启动这个 JAR 应用程序。
有人问我使用 JNDI 检索存储在 Tomcat context.xml 中的数据源,说这很容易。
我试着用下面的代码来做到这一点。
Context initContext;
try {
initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/mydatabase");
} catch (NamingException e) {
System.out.println("ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
e.printStackTrace();
System.out.println("ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
但是不行。
我得到这个错误:
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
克服这个问题有什么简单的方法吗?
或者用我的JAR独立应用,还是绝对不可能克服这个问题,就像先例post Tomcat JNDI + Standalone Java告知的那样?
我看到很多 posts,很多文档,但我仍然不清楚。
感谢您的帮助,您的分享。
托马斯
Kedar 给我一个答案。
我总结了 Kedar 的回答:
- 当 运行 你的 JAR 应用程序使用 jar 命令行时,我使用的是嵌入式 Tomcat
- 当我使用嵌入式 Tomcat 时,我可能无法访问我的 JNDI 数据源
这就是为什么我的 JNDI 不工作的原因。
我将尝试查看此 post 来配置我的应用程序,以便尝试使用 JNDI:
How to create JNDI context in Spring Boot with Embedded Tomcat Container
但是,现在,多亏了 Kedar,我明白了为什么我的 JNDI 代码不起作用。
我将查看其他 post 以查看如何配置以尽可能使用 JNDI。
谢谢 Kedar。
很抱歉延迟给出答案。
感谢 Kedar 告诉我 JNDI 不适用于 JAR,我尝试:
- 在 Tomcat 服务器上读取 context.xml 文件
- 从此 context.xml 文件中提取 XML 元素,其中包含有关数据库的所有属性
- 从这个数据库属性构造一个 DataSource 对象
也感谢 MKyong 提供本教程:
https://mkyong.com/java/how-to-read-xml-file-in-java-dom-parser/
这是我在 SpringBoot 下的工作代码:
@Configuration
public class ApplicationConfiguration {
/**
* Absolute path of the configuration file named context.xml on any Tomcat Server (DEV, TEST, PROD).
*/
private final String CONTEXT_XML_PATH_ON_SERVER = "/opt/tomcat/apache-tomcat-version/conf/context.xml";
@Bean
@Primary
public DataSource dataSource() {
try {
Element datasourceElement = getDatasourceElementInTomcatContextXml();
return DataSourceBuilder
.create()
.username(datasourceElement.getAttribute("username"))
.password(datasourceElement.getAttribute("password"))
.url(datasourceElement.getAttribute("url"))
.driverClassName(datasourceElement.getAttribute("driverClassName"))
.build();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException | IOException e) {
e.printStackTrace();
}
return null;
}
private Element getDatasourceElementInTomcatContextXml() throws ParserConfigurationException, SAXException, IOException {
File contextXmlFile = new File(CONTEXT_XML_PATH_ON_SERVER);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(contextXmlFile);
//optional, but recommended
//read this -
doc.getDocumentElement().normalize();
NodeList resourceElementList = doc.getElementsByTagName("Resource");
Node nNode = resourceElementList.item(0);
Element eElement = (Element) nNode;
return eElement;
}
}
谢谢 Kedar 和 MKyong。
托马斯
我用 Springboot 创建了一个 JAR 应用程序。 我在 Tomcat 服务器下启动这个 JAR 应用程序。
有人问我使用 JNDI 检索存储在 Tomcat context.xml 中的数据源,说这很容易。
我试着用下面的代码来做到这一点。
Context initContext;
try {
initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/mydatabase");
} catch (NamingException e) {
System.out.println("ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
e.printStackTrace();
System.out.println("ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
但是不行。
我得到这个错误:
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
克服这个问题有什么简单的方法吗?
或者用我的JAR独立应用,还是绝对不可能克服这个问题,就像先例post Tomcat JNDI + Standalone Java告知的那样?
我看到很多 posts,很多文档,但我仍然不清楚。
感谢您的帮助,您的分享。
托马斯
Kedar 给我一个答案。 我总结了 Kedar 的回答:
- 当 运行 你的 JAR 应用程序使用 jar 命令行时,我使用的是嵌入式 Tomcat
- 当我使用嵌入式 Tomcat 时,我可能无法访问我的 JNDI 数据源 这就是为什么我的 JNDI 不工作的原因。 我将尝试查看此 post 来配置我的应用程序,以便尝试使用 JNDI: How to create JNDI context in Spring Boot with Embedded Tomcat Container 但是,现在,多亏了 Kedar,我明白了为什么我的 JNDI 代码不起作用。 我将查看其他 post 以查看如何配置以尽可能使用 JNDI。 谢谢 Kedar。
很抱歉延迟给出答案。
感谢 Kedar 告诉我 JNDI 不适用于 JAR,我尝试:
- 在 Tomcat 服务器上读取 context.xml 文件
- 从此 context.xml 文件中提取 XML 元素,其中包含有关数据库的所有属性
- 从这个数据库属性构造一个 DataSource 对象
也感谢 MKyong 提供本教程: https://mkyong.com/java/how-to-read-xml-file-in-java-dom-parser/
这是我在 SpringBoot 下的工作代码:
@Configuration
public class ApplicationConfiguration {
/**
* Absolute path of the configuration file named context.xml on any Tomcat Server (DEV, TEST, PROD).
*/
private final String CONTEXT_XML_PATH_ON_SERVER = "/opt/tomcat/apache-tomcat-version/conf/context.xml";
@Bean
@Primary
public DataSource dataSource() {
try {
Element datasourceElement = getDatasourceElementInTomcatContextXml();
return DataSourceBuilder
.create()
.username(datasourceElement.getAttribute("username"))
.password(datasourceElement.getAttribute("password"))
.url(datasourceElement.getAttribute("url"))
.driverClassName(datasourceElement.getAttribute("driverClassName"))
.build();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException | IOException e) {
e.printStackTrace();
}
return null;
}
private Element getDatasourceElementInTomcatContextXml() throws ParserConfigurationException, SAXException, IOException {
File contextXmlFile = new File(CONTEXT_XML_PATH_ON_SERVER);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(contextXmlFile);
//optional, but recommended
//read this -
doc.getDocumentElement().normalize();
NodeList resourceElementList = doc.getElementsByTagName("Resource");
Node nNode = resourceElementList.item(0);
Element eElement = (Element) nNode;
return eElement;
}
}
谢谢 Kedar 和 MKyong。
托马斯