have a look on org.hibernate.internal.util.ClassLoaderHelper.
All you have to do, is replacing the ClassLoader with a ClassLoader which is able to resolve your entity classes.
Hibernate-Osgi is also setting it to the OSGI ClassLoader (see org.hibernate.osgi.HibernateBundleActivator). So suggest the following:
BundleWideClassLoader cl = new BundleWideClassLoader();
if (ClassLoaderHelper.overridenClassLoader != null
&& ClassLoaderHelper.overridenClassLoader instanceof OsgiClassLoader)
{
OsgiClassLoader ocl = (OsgiClassLoader)ClassLoaderHelper.overridenClassLoader;
for (Bundle b : cl.getBundles()) {
ocl.addBundle(b);
}
} else {
ClassLoaderHelper.overridenClassLoader = new BundleWideClassLoader();
}
I put this to my HibernateConfiguration class by overriding buildSessionFactory which performs this routine and returns super.buildSessionFactory.
The BundleWideClassLoader looks like this
public class BundleWideClassLoader extends ClassLoader
{
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
for (BundleClassLoader cl : this.getAllClassLoader()) {
try {
Class clazz = cl.findClass(name);
return clazz;
} catch (Exception ex) {
}
}
throw new ClassNotFoundException(name);
}
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
Class clazz = this.findClass(name);
if (resolve) {
this.resolveClass(clazz);
}
return clazz;
}
@Override
public URL findResource(String name) {
for (BundleClassLoader cl : this.getAllClassLoader()) {
URL ret = cl.findResource(name);
if (ret != null) {
return ret;
}
}
return null;
}
/**
* Returns a list of all available BundleClassLoader.
*
* @return classloader
*/
public HashSet<BundleClassLoader> getAllClassLoader() {
//
// Do some magic here to get your ClassLoaders from all of your Bundles
//
}
/**
* Returns a list of all bundles which are registered in this BundleWideClassLoader.
*
* @return list of managed bundles
*/
public HashSet<Bundle> getBundles() {
HashSet<Bundle> bundles = new HashSet<>();
for (BundleClassLoader cl : this.getAllClassLoader()) {
bundles.add(cl.getBundleContext().getBundle());
}
return bundles;
}
}
And finally the BundleClassLoader:
public class BundleClassLoader extends ClassLoader
{
/**
* Bundle context.
*/
private BundleContext context;
/**
* Constructor.
* @param ctx Bundle Context
*/
public BundleClassLoader(BundleContext ctx) {
this.context = ctx;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
return this.context.getBundle().loadClass(name);
}
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
Class clazz = this.findClass(name);
if (resolve) {
this.resolveClass(clazz);
}
return clazz;
}
@Override
public URL findResource(String name) {
return this.context.getBundle().getResource(name);
}
/**
* Returns bundle context.
* @return bundle context
*/
public BundleContext getBundleContext() {
return this.context;
}
}
I suggest to create a new BundleClassLoader in each of your BundleActivators and add it to some kind of registry so the BundleWideClassLoader can get a list of BundleClassLoader from there. Do not forget to remove the BundleClassLoader, when the bundle is stopped or removed.