我只能提供一些关于让 JDO/datanucleus 在 Karaf 之上工作的基本提示。
正如教程中所指出的,您需要扩展LocalPersistenceManagerFactoryBean
、实现BundleContextAware
接口。
这里的关键点是类加载:LocalPersistenceManagerFactoryBean
期望所有类都由一个类加载器加载,而在 OSGi 运行时中并非如此。
为了让它工作,你需要:
org.datanucleus.api.jdo
在清单文件中显式导入。
- 该
datanucleus.primaryClassLoader
属性可以设置为您将传递给该JDOHelper.getPersistenceManagerFactory
方法的相同类加载器。类加载器是org.datanucleus.api.jdo
包使用的类加载器(参见下面的示例)
- 您需要将
datanucleus.plugin.pluginRegistryClassName
属性设置为org.datanucleus.plugin.OSGiPluginRegistry
.
- 停止/卸载捆绑包时,您必须刷新
javax.jdo
捆绑包以避免在重新创建持久性管理器工厂时出现错误(检查这个问题的主题)
示例自定义 LocalPersistenceManagerFactoryBean:
public class OSGiLocalPersistenceManagerFactoryBean
extends LocalPersistenceManagerFactoryBean implements BundleContextAware {
public static final String JDO_BUNDLE_NAME = "org.datanucleus.api.jdo";
public static final String JDO_PMF_CLASS_NAME = "org.datanucleus.api.jdo.JDOPersistenceManagerFactory";
private BundleContext bundleContext;
@Override
protected PersistenceManagerFactory newPersistenceManagerFactory(String name) {
return JDOHelper.getPersistenceManagerFactory(name, getClassLoader());
}
@Override
protected PersistenceManagerFactory newPersistenceManagerFactory(Map props) {
ClassLoader classLoader = getClassLoader();
props.put("datanucleus.primaryClassLoader", classLoader);
if (FrameworkUtil.getBundle(this.getClass()) != null) { // running in OSGi
props.put("datanucleus.plugin.pluginRegistryClassName", "org.datanucleus.plugin.OSGiPluginRegistry");
}
PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props, classLoader);
return pmf;
}
private ClassLoader getClassLoader() {
ClassLoader classLoader = null;
Bundle thisBundle = FrameworkUtil.getBundle(this.getClass());
if (thisBundle != null) { // on OSGi runtime
Bundle[] bundles = bundleContext.getBundles();
for (Bundle bundle : bundles) {
if (JDO_BUNDLE_NAME.equals(bundle.getSymbolicName())) {
try {
classLoader = bundle.loadClass(JDO_PMF_CLASS_NAME).getClassLoader();
} catch (ClassNotFoundException e) {
// do something fancy here ...
}
break;
}
}
} else { // on Java runtime
classLoader = this.getClass().getClassLoader();
}
return classLoader;
}
@Override
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
}