I just hope if there is somebody who have seen and resolved this problem. I have a MBean and a MXBean classes. Both are using the same service class to get access to the database through a DAO class. I am using spring 3.0 to initialized those classes and using the JConsole to test those beans. Both those beans have the same method name to access to their service class, lets say methodA(). But when connecting to the oracle database, only the MBean class returns data. The other MXBean class produces some errors.
Here are the errors
EL Severe]: 2012-05-18 10:37:54.134--ServerSession(1992289)--Thread(Thread[RMI TCP Connection(6)-10.208.138.241,5,RMI Runtime])--java.lang.IllegalArgumentException: interface oracle.ucp.jdbc.LabelableConnection is not visible from class loader
at java.lang.reflect.Proxy.getProxyClass(Proxy.java:353)
at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:581)
at oracle.ucp.jdbc.proxy.ConnectionProxyFactory.createConnectionProxy(ConnectionProxyFactory.java:78)
at oracle.ucp.jdbc.PoolDataSourceImpl.getConnection(PoolDataSourceImpl.java:658)
at oracle.ucp.jdbc.PoolDataSourceImpl.getConnection(PoolDataSourceImpl.java:613)
at oracle.ucp.jdbc.PoolDataSourceImpl.getConnection(PoolDataSourceImpl.java:607)
at org.springframework.jdbc.datasource.DelegatingDataSource.getConnection(DelegatingDataSource.java:83)
at com.trgr.cobalt.dataorch.datasource.BaseDODataSource.getRawConnection(BaseDODataSource.java:76)
at com.trgr.cobalt.dataorch.datasource.BaseDODataSource.getConnection(BaseDODataSource.java:46)
at com.trgr.cobalt.dataorch.datasource.BaseDODataSource.getConnection(BaseDODataSource.java:35)
at org.eclipse.persistence.sessions.JNDIConnector.connect(JNDIConnector.java:126)
at org.eclipse.persistence.sessions.JNDIConnector.connect(JNDIConnector.java:94)
at org.eclipse.persistence.sessions.DatasourceLogin.connectToDatasource(DatasourceLogin.java:162)
at org.eclipse.persistence.internal.databaseaccess.DatasourceAccessor.connectInternal(DatasourceAccessor.java:327)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.connectInternal(DatabaseAccessor.java:291)
at org.eclipse.persistence.internal.databaseaccess.DatasourceAccessor.connect(DatasourceAccessor.java:415)
at org.eclipse.persistence.sessions.server.ConnectionPool.buildConnection(ConnectionPool.java:155)
at org.eclipse.persistence.sessions.server.ExternalConnectionPool.startUp(ExternalConnectionPool.java:118)
at org.eclipse.persistence.sessions.server.ServerSession.connect(ServerSession.java:495)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.login(DatabaseSessionImpl.java:627)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:230)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:389)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.getServerSession(EntityManagerFactoryImpl.java:164)
Here is my spring configuration
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"
lazy-init="false">
<property name="namingStrategy" ref="namingStrategy"></property>
<property name="assembler" ref="assembler"></property>
<property name="autodetect" value="true" />
</bean>
<bean id="attributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource" />
<bean id="assembler"
class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="attributeSource" />
</bean>
<bean id="namingStrategy"
class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
<property name="attributeSource" ref="attributeSource" />
</bean>
<bean class="myclass.jmx.DocumentMBean"
p:schedulerService-ref="documentService" />
<bean class="myclass.jmx.DocumentMXBean"
p:schedulerService-ref="documentService" />
The DocumentMBean is a regular MBean. The DocumentMXBean is a MXBean. Both those beans using the same documentService service class, which using the same DAO class to get data from Oracle database. The DocumentMBean returns data correctly. The DocumentMXBean has the errors mentioned above.
Does anyone know why the class oracle.ucp.jdbc.LabelableConnection is not visible from class loader? This happens ONLY when I execute my MXBean. My MBean returns data correctly. I have the jar file containing that class inside my WEB-INF/lib folder. And this is deployed in Tomcat. And I start Tomcat from within Eclipse.
Update 1:
I was able to temporary resolve this by adding the jar files for those "not visible" classes to Tomcat classpath inside Eclipse. It seems like for loading the MBeans, JConsole/java is using my web application class loader, which have access to all the libraries that the class loader needs. But when loading the MXBeans, JConsole/java using the class loader of Tomcat.
My question is: is there a way to force Tomcat/Eclipse/Java using the same class loader (which is my web app class loader) when loading either MBean or MXBean?
Update 2:
I found out that when loading my web application, Spring uses the web application's class loader while Tomcat when loading any MXBean, it uses the JVM class loader, which doesn't have my oracle class path in it. So, the work-around solution is to use the class loader of my classes instead of the one from JVM. The codes should be:
try
{
// your codes here
// Get the current class-loader. This might be the class-loader from Tomcat
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
// Set the class-loader to be the one from the DO and not the one from Tomcat
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
// your codes here
}
catch (Exception e)
{
// your codes here
}
finally
{
// Remember to set back the original class-loader
Thread.currentThread().setContextClassLoader(contextClassLoader);
}