look at org.hibernate.internal.util.ClassLoaderHelper.
All you have to do is replace ClassLoader with ClassLoader, which is able to resolve your entity classes. Hibernate-Osgi also installs it in the OSGI ClassLoader (see Org.hibernate.osgi.HibernateBundleActivator). Therefore, 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 in my HibernateConfiguration class, overriding the buildSessionFactory, which executes this procedure and returns super.buildSessionFactory.
BundleWideClassLoader is as follows:
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; } public HashSet<BundleClassLoader> getAllClassLoader() {
And finally, BundleClassLoader:
public class BundleClassLoader extends ClassLoader { private BundleContext 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); } public BundleContext getBundleContext() { return this.context; } }
I suggest creating a new BundleClassLoader in each of your BundleActivators and adding it to some registry so that the BundleWideClassLoader can get a list of BundleClassLoader from there. Remember to remove the BundleClassLoader when the package is stopped or removed.
source share