Helo大师,我必须动态创建一个JNDI数据源,我试着用一个叫做SetupApplicationListener的监听器来做。这是WEB-LIB/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee">
<display-name>pri-web</display-name>
<!-- Listeners -->
<listener>
<listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>
<listener>
<listener-class>myapp.SetupApplicationListener</listener-class>
</listener>
听众的代码:
public class SetupApplicationListener implements ServletContextListener {
public static Log LOG = null;
public void contextInitialized(ServletContextEvent ctx){
try {
createOracleDataSource();
.....
}
}
private void createOracleDataSource() throws SQLException, NamingException {
OracleDataSource ds = new OracleDataSource();
ds.setDriverType(...);
ds.setServerName(...);
ds.setPortNumber(...);
ds.setDatabaseName(...);
ds.setUser(...);
ds.setPassword(...);
new InitialContext().bind("java:comp/env/jdbc/myDS", ds);
}
.....
}
有错误:
[ERROR] 29/01/2013 09:44:50,517 (SetupApplicationListener.java:86) -> Error
javax.naming.NamingException: Context is read only
at org.apache.naming.NamingContext.checkWritable(NamingContext.java:903)
at org.apache.naming.NamingContext.bind(NamingContext.java:831)
at org.apache.naming.NamingContext.bind(NamingContext.java:171)
at org.apache.naming.NamingContext.bind(NamingContext.java:187)
at org.apache.naming.SelectorContext.bind(SelectorContext.java:186)
at javax.naming.InitialContext.bind(InitialContext.java:359)
at myapp.SetupApplicationListener.createOracleDataSource(SetupApplicationListener.java:102)
我可以将Context的只读属性设置为“true”吗?谢谢! :)
Tomcat 6.0
Oracle 11g
jdk1.5
编辑:不需要动态,我必须在内部定义jndi数据源我无法修改服务器文件,因为它是共享服务器。它必须是jndi,因为其他模块以这种方式使用它,谢谢。
答案 0 :(得分:4)
如果需要动态创建数据源,是否真的需要JNDI查找? JNDI旨在使应用程序外部连接,而在您的场景中,由于合法的要求,它与应用程序紧密耦合。为什么不直接使用JDBC连接?
答案 1 :(得分:2)
之前我没有遇到过这个问题,因为我经常在应用服务器(tomcat,weblogic等)中定义JNDI。就像凯文所说的那样,这正是JNDI的设计目标;将数据源配置与源代码分离,并通过查找和注入检索JNDI资源;
回到你的问题,我认为tomcat在运行时有很多关于修改JNDI的严格规则。换句话说,您无法从Context重新绑定或删除jndi。如果你通过tomcat规范,你可能会看到一些关于jndi查找但没有重新绑定的事情。
答案 2 :(得分:2)
来自EE 6平台规范(JSR 316)的EE.5.3.4节:
容器必须确保应用程序组件实例 只有对其命名上下文的读访问权限。容器必须 抛出所有的javax.naming.OperationNotSupportedException 修改的javax.naming.Context接口的方法 环境命名上下文及其子上下文。
请注意,本节中的“命名上下文”是指java:comp
。
答案 3 :(得分:2)
你需要创建一个ServletContextListener,你可以在那里使InitialContext可写 - 这不是它应该做的方式,但如果你真的需要它,这是你可以做到的一种方式。
这也适用于Java Melody!
protected void makeJNDIContextWritable(ServletContextEvent sce) {
try {
Class<?> contextAccessControllerClass = sce.getClass().getClassLoader().loadClass("org.apache.naming.ContextAccessController");
Field readOnlyContextsField = contextAccessControllerClass.getDeclaredField("readOnlyContexts");
readOnlyContextsField.setAccessible(true);
Hashtable readOnlyContexts = (Hashtable) readOnlyContextsField.get(null);
String context = null;
for (Object key : readOnlyContexts.keySet()) {
String keyString = key + "";
if (keyString.endsWith(sce.getServletContext().getContextPath())) {
context = keyString;
}
}
readOnlyContexts.remove(context);
} catch (Exception ex) {
ex.printStackTrace();
}
}
答案 4 :(得分:0)
我发现我正在关闭environmentContext对象时解决了这个问题 例如:
Context context=new InitialContext();
Context environmentContext=(Context) context.lookup("java:comp/env");
我的代码是:
environmentContext.close();
从environmentContext中删除close函数后,问题被解决了;
答案 5 :(得分:0)
我也遇到过这个问题,但对Tomee来说是新手,我不知道有一个简单的解决方案。当我将我的Web应用程序部署到webapps文件夹时,该应用程序工作正常,但当我将其部署到服务文件夹时,我得到了相同的中止。问题是文件夹名称与战争名称(减去.war)不匹配。一旦我解决了这个问题,应用程序运行良好。确保战争名称,文件夹名称和服务名称相同。此问题会产生几个不同的错误,包括Context是只读和Error合并Java EE JNDI条目。
答案 6 :(得分:0)
我通过在context.xml中设置useNaming="false"
解决了这个问题。
useNaming:设置为true(默认值)以使Catalina对此Web应用程序启用与Java2 Enterprise Edition(J2EE)平台约定兼容的JNDI InitialContext。