The context is read-only.

Helo Helpers, I have to dynamically create a JNDI Datasource, I tried to do this with a listener called SetupApplicationListener. Here is the beginning of 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> 

Listener Code:

 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 an 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 “Context” properties of “true”? Thank you :)

 Tomcat 6.0 Oracle 11g jdk1.5 

EDIT : not needed dynamically, I have to determine the jndi data source myself. I cannot change server files because it is a shared server. It must be jndi, because other modules use it that way, thanks.

+6
source share
6 answers

If you need to dynamically create a data source, is there really a need for a JNDI lookup? JNDI is designed to make the connection external to the application, while in your scenario it is closely related to the application due to a legal requirement. Why not just use the JDBC connection?

+4
source

I did not have this problem before, since I usually defined JNDI on the application server (tomcat, weblogic, etc.). Just like Kevin said, this is exactly what JNDI was designed for; separating the configuration of the data source from the source code and extracting JNDI resources by searching and entering;

Returning to your question, I think tomcat has all the strict rules for changing JNDI at runtime. In other words, you cannot re-bind or remove jndi from context. If you go through the tomcat spec, you are likely to see something in the jndi search, but don’t overbind.

+2
source

From the EE.5.3.4 section of the EE 6 platform specification (JSR 316):

The container must ensure that instances of the application component have access only to their naming context. The container should throw javax.naming.OperationNotSupportedException from all methods of the javax.naming.Context interface that change the environment naming context and its subcontexts.

Note that “their naming context” in this section refers to java:comp .

+2
source

You need to create a ServletContextListener, and you can make the InitialContext entry available - this is not how it should be done, but if you really need it, this is one way to do it.

This also works with 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(); } } 
+2
source

I solved this problem when I discovered that I was closing an environmentContext object For example:

 Context context=new InitialContext(); Context environmentContext=(Context) context.lookup("java:comp/env"); 

And my code is:

 environmentContext.close(); 

After removing the close function from environmentContext, the problem was sold to me;

0
source

I also had this problem, but being new to Tome, I did not know that there was a simple solution. When I deployed my web application in the webapps folder, the application worked fine, but when I deployed it in the service folder, I got the same interrupt. The problem was that the folder name did not match the name of the war (minus .war). As soon as I fixed it, the application worked perfectly. Make sure the war name, folder name, and service name are identical. This issue causes several different errors, including Read-only Context and Java EE JNDI Merge Error.

0
source

All Articles