JNDI context initialization fails in Tomcat when connecting via JMX

1.6k views Asked by At

I have a webapp deployed in Tomcat 7.0.8. Recently I started implementing MBeans to be able to monitor a few actions, which normally are invoked from a quartz scheduler. I connect to Tomcat's MBean server using JConsole and invoke a method, which tries to connect to a database via JNDI.

When execution reaches Context initContext = new InitialContext(); the following exception is thrown:

javax.naming.NoInitialContextException: Cannot instantiate class: org.apache.naming.java.javaURLContextFactory [Root exception is java.lang.ClassNotFoundException: org.apache.naming.java.javaURLContextFactory]

When the method is called from the regular servlet (a JAX-WS webservice), there are no problems with the class loading. It seems class loading works differently when JMX is involved, but I can't figure out how... Could it have something to do with RMI class loader disabled, which JConsole tells me?

3

There are 3 answers

2
Elliott Frisch On

Yes. It's actually a little more complex then that; you're used to the Web Container - but JMX MBeans run in a different container (with a seperate life-cycle). That is the MBeanServer.

The MBeanServer

0
Daniel Wahlberg On

I realized that the context was available during startup, so I made a ServletContextListener save the datasource (looked up from the context) in a static variable. When my application requests a database connection, it is retrieved from the stored datasource.

0
slevin On

Another workaround for this sort of issue: retrieve the classloader for the class containing your Context initContext = new InitialContext(); code, and set it to be the current classloader for the thread.

ClassLoader origLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
InitialContext ctx = new InitialContext();
Object obj = ctx.lookup("java:global/some/path");
Thread.currentThread().setContextClassLoader(origLoader);

This has worked for me for problems with classloading when making method calls from a JMX console.