Hello Hibernate-Community
I'm using Hibernate 3.2.0 with annotations in Eclipse 3.2.1 plug-ins and I have the following intention:
I would like to encapsulate the Hibernate libs and the session handling in a single plug-in, called org.myplugin.hibernate. This plug-in defines an extension-point: Extensions provide the classes that should be mapped and for this, they have to implement my interface IModelProvider. The mappings are specified by annotations. My goal is to provide a flexible mechanism for adding new datamodels to my application. Currently, there exists one extension for testing-purpose - org.myplugin.hibernate.test - that contributes a trivial class for mapping:
Code:
import javax.persistence.*;
@Entity
public class TestClass {
private Long id;
private String str = "Hello World";
@Id
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public String toString(){
return str;
}
}
When org.myplugin.hibernate is loaded, it queries the Eclipse extension registry for extensions to its extension point. For each extension that was found, it gets the annotated classes by invoking IModelProvider.getAnnotatedClasses().
For example, org.myplugin.hibernate implements IModelProvider as follows:
Code:
public class TestModelProvider implements IModelProvider {
public Class[] getHibernateAnnotatedClasses() {
Class[] result = {TestClass.class};
return result;
}
}
org.myplugin.hibernate then creates a configuration, adds the mappings, creates a session factory and session respectively:
Code:
Class[] annotatedClasses = myModelProvider.getHibernateAnnotatedClasses();
AnnotationConfiguration config = new AnnotationConfiguration();
config.addAnnotatedClass(annotatedClasses[0]);
...//configure database credentials
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.openSession();
Until here, everything seems to work fine.
Now, org.myplugin.hibernate publishes a proxy for saving instances of mapped objects. Basically it implements the following method:
Code:
public void saveObject(Object saveableObject) {
session.save(saveableObject); //session is the Hibernate session created above
}
Whenever an instance of TestClass is passed to this method for making it persistant, I encounter the following exception (I have included the full stacktrace at the end of my post):
Quote:
org.hibernate.MappingException: Unknown entity: org.myplugin.hibernate.test.TestClass
at org.hibernate.impl.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:548)
...
.
After extensive reading, I'm now aware that this is an issue concerning classloaders - org.myplugin.hibernate uses another classloader than org.myplugin.hibernate.test. Consequently, I
DID introduce
buddy loading as proposed in
Hibernate and Eclipse Integration. I'm confident that I did this correctly, since I'm now able to do the following (which I wasn't before) in org.myplugin.hibernate:
Code:
public void saveObject(Object saveableObject) {
try {
Class.forName(saveableObject.getClass().getCanonicalName()); // No Exception occurs - the class is loadable!
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//session.save(saveableObject); <-- still throws a MappingException!
}
Saving triggers still the same exception as before - it seems (I'm speculating; I'm not quite sure, what's happening) that, despite of the buddy loading, Hibernate is not able to recognize the class TestClass. I assume that telling Hibernate to use the classloader provided by saveableObject.getClass().getClassLoader() would overcome my problem, but obviously, that is not possible/intended by the Hibernate developers.
Any ideas how to solve my problem?
Thanks in advance,
Michael
Complete Stacktrace:Quote:
org.hibernate.MappingException: Unknown entity: org.evolizer.hibernate.test.TestClass
at org.hibernate.impl.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:548)
at org.hibernate.impl.SessionImpl.getEntityPersister(SessionImpl.java:1338)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:96)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:186)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:33)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:175)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:27)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:535)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:523)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:519)
at org.evolizer.hibernate.session.EvolizerSession.saveObject(EvolizerSession.java:56)
at org.evolizer.hibernate.test.EvolizerSessionTest.testSaveObject(EvolizerSessionTest.java:41)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99)
at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75)
at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45)
at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:71)
at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35)
at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.pde.internal.junit.runtime.RemotePluginTestRunner.main(RemotePluginTestRunner.java:58)
at org.eclipse.pde.internal.junit.runtime.CoreTestApplication.run(CoreTestApplication.java:24)
at org.eclipse.core.internal.runtime.PlatformActivator$1.run(PlatformActivator.java:78)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:92)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:68)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:400)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:177)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.eclipse.core.launcher.Main.invokeFramework(Main.java:336)
at org.eclipse.core.launcher.Main.basicRun(Main.java:280)
at org.eclipse.core.launcher.Main.run(Main.java:977)
at org.eclipse.core.launcher.Main.main(Main.java:952)