java 上下文是只读的
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14580286/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Context is read only
提问by rubenGL
Helo masters, I have to create a JNDI Datasource dynamically, I tried to do it with a listener called SetupApplicationListener. Here is the beginning of WEB-LIB/web.xml
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>
The code of the 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);
}
.....
}
And there is the error:
并且有错误:
[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)
Can I set the read-only properties of the Context to "true"? Thanks! :)
我可以将 Context 的只读属性设置为“true”吗?谢谢!:)
Tomcat 6.0
Oracle 11g
jdk1.5
EDIT: Don't need to be dynamically, i have to define a jndi datasource internally I can't modify the server files because it is a shared server. It must be jndi because other modules use it in that way, thanks.
编辑:不需要动态,我必须在内部定义一个 jndi 数据源我不能修改服务器文件,因为它是一个共享服务器。它必须是 jndi,因为其他模块以这种方式使用它,谢谢。
采纳答案by Kevin Bowersox
If you need to create a datasource dynamically is there really any need for a JNDI lookup? JNDI is designed to make the connection external to the application, while in your scenario its tightly coupled to the application due to a legitimate requirement. Why not just use a JDBC connection?
如果您需要动态创建数据源,是否真的需要 JNDI 查找?JNDI 旨在建立应用程序外部的连接,而在您的场景中,由于合法要求,它与应用程序紧密耦合。为什么不直接使用 JDBC 连接?
回答by spiritwalker
I haven't got this problem before since I usually defined JNDI in application server(tomcat, weblogic and etc). Just like what Kevin said, this is exactly what JNDI was designed for; separating datasource config from your source code and retrieving JNDI resources through lookup and inject;
我以前没有遇到过这个问题,因为我通常在应用程序服务器(tomcat、weblogic 等)中定义 JNDI。正如凯文所说,这正是 JNDI 的设计目的;将数据源配置与源代码分离,并通过查找和注入检索 JNDI 资源;
Back to your question, I think tomcat has every strict rules on modifying JNDI at runtime. In another word, you cannot re-bind or remove jndi from Context. If you go through the tomcat specification you will probably see some thing about jndi lookup but no re-bind.
回到你的问题,我认为 tomcat 在运行时修改 JNDI 有所有严格的规则。换句话说,您不能从 Context 重新绑定或删除 jndi。如果您仔细阅读 tomcat 规范,您可能会看到一些关于 jndi 查找但没有重新绑定的内容。
回答by Brett Kail
From section EE.5.3.4 of the EE 6 platform specification (JSR 316):
来自 EE 6 平台规范 (JSR 316) 的 EE.5.3.4 部分:
The container must ensure that the application component instances have only read access to their naming context. The container must throw the javax.naming.OperationNotSupportedException from all the methods of the javax.naming.Context interface that modify the environment naming context and its subcontexts.
容器必须确保应用程序组件实例对其命名上下文只有读访问权限。容器必须从修改环境命名上下文及其子上下文的 javax.naming.Context 接口的所有方法中抛出 javax.naming.OperationNotSupportedException。
Note that "their naming context" in this section is referring to java:comp
.
请注意,本节中的“他们的命名上下文”是指java:comp
.
回答by Halko Karr-Sajtarevic
You need to create a ServletContextListener and there you can make the InitialContext writable - it's not the way it should be done, but if you really need it, this is one way you can do it.
您需要创建一个 ServletContextListener 并且您可以在那里使 InitialContext 可写 - 这不是应该完成的方式,但如果您真的需要它,这是您可以做到的一种方式。
This also works with Java Melody!
这也适用于 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();
}
}
回答by Jim Reitz
I also had this problem, but being new to Tomee, I didn't know that there is a simple solution. When I deployed my web app to the webapps folder, the app worked fine, but when I deployed it to a service folder, I got the same abort. The problem was that the folder name did not match the war name (minus the .war). Once I fixed that, the app worked fine. Make sure the war name, folder name and service name are identical. This problem produces several different errors, including Context is read only and Error merging Java EE JNDI entries.
我也遇到了这个问题,但我是 Tomee 的新手,我不知道有一个简单的解决方案。当我将我的 web 应用程序部署到 webapps 文件夹时,该应用程序运行良好,但是当我将它部署到服务文件夹时,我得到了同样的中止。问题是文件夹名称与War名称不匹配(减去 .war)。一旦我解决了这个问题,该应用程序运行良好。确保War名称、文件夹名称和服务名称相同。此问题会产生多种不同的错误,包括 Context is read only 和 Error merging Java EE JNDI 条目。
回答by alarive
I solved this issue by setting useNaming="false"
in my context.xml.
我通过useNaming="false"
在我的 context.xml 中设置解决了这个问题。
从文档:
useNaming : Set to true (the default) to have Catalina enable a JNDI InitialContext for this web application that is compatible with Java2 Enterprise Edition (J2EE) platform conventions.
useNaming :设置为 true(默认值)以使 Catalina 为与 Java2 Enterprise Edition (J2EE) 平台约定兼容的 Web 应用程序启用 JNDI InitialContext。
回答by Kaxa
I solved this problem when found that I was closing environmentContext object For example:
当发现我正在关闭 environmentContext 对象时,我解决了这个问题 例如:
Context context=new InitialContext();
Context environmentContext=(Context) context.lookup("java:comp/env");
And my code was:
我的代码是:
environmentContext.close();
After removing close function from environmentContext problem was solded for me;
从 environmentContext 问题中删除关闭功能后,问题被卖给了我;