我已经在OSGi上下文中成功启动了Hibernate,现在我想添加Envers。
The documentation声称这是可能的。我不相信了。这个主题没有任何文档,似乎没有人真正做过。此外,即使使用Blueprint实现,我也必须破解类加载器以使Hibernate甚至找到Envers:
osgiClassLoader = new org.hibernate.osgi.OsgiClassLoader();
osgiClassLoader.addBundle(requestingBundle);
osgiClassLoader.addBundle(FrameworkUtil.getBundle(SessionFactory.class));
osgiClassLoader.addBundle(FrameworkUtil.getBundle(HibernateEntityManagerFactory.class));
osgiClassLoader.addBundle(FrameworkUtil.getBundle(EnversService.class));
Thread.currentThread().setContextClassLoader(osgiClassLoader);
(我觉得我应该问:“OSGi中的Envers是否可能?”所以如果你对这个问题有明确的答案,请告诉我。我在这些问题上花了太多时间。)
但实际问题与Hibernate / Envers无关,而且与OSGi无关。两者都想访问使用的实体和枚举。尽管如此。他们当然不能。当然我不能添加Import-Packages。
相关的堆栈跟踪看起来像这样:
Caused by: java.lang.ClassNotFoundException: org.acme.project.MyEnum cannot be found by org.hibernate.core_5.1.0.Final
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:461)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:372)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:364)
at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:161)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at org.hibernate.internal.util.ReflectHelper.classForName(ReflectHelper.java:151)
at org.hibernate.type.EnumType.setParameterValues(EnumType.java:105)
... 62 more
通常使用OSGi无关的框架我只需要向MANIFEST.MF添加这样的内容:
// to org.hibernate.core
Eclipse-BuddyPolicy: registered
// to org.acme.project
Eclipse-RegisterBuddy: org.hibernate.core
但是我无法在Hibernate的清单中添加任何内容。我尝试通过片段贡献该行,但这也不起作用。
我甚至尝试将整个Hibernate依赖项作为JAR添加到插件中以添加上述内容。它不会起作用。
如何解决这些类加载器问题?
如果您的@Audited类引用了Enum,org.hibernate.core需要导入类包。执行此操作的最佳方法是注册片段包。
此外,明智的做法是确保hibernate捆绑包的起始级别低于实体捆绑包的起始级别。
以下是Gradle脚本示例的片段,用于创建片段包。确保将org.hibernate.core包版本更改为您正在使用的版本,并将'your.package'更新为包含您的Enum的版本。
/*
When using Envers, entities that reference Enum classes must be imported (Import-Package) by the org.hibernate.core bundle.
*/
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'biz.aQute.bnd:biz.aQute.bnd.gradle:3.2.0'
}
}
apply plugin: 'biz.aQute.bnd.builder'
jar {
manifest {
attributes(
'Fragment-Host': 'org.hibernate.core;' + 'bundle-version=' + '5.2.9.Final',
'Import-Package': 'your.package'
)
}
}
晚到派对,但在这里抛出这个以防其他人需要它:
Hibernate bootstrapping在OSGi中看起来与在SE / EE领域中看起来完全不同。我们在JIRA跟踪增强方面有很多票,特别是为了使事情更具动态性并减少启动顺序的脆弱性(Steven绝对正确,hibernate-core,hibernate-envers等目前必须首先在你的捆绑之前启动)。
我强烈建议不要使用捆绑片段方法,但我会在Steven的回答中评论为什么。
我们的hibernate-demos项目有一些OSGi快速入门,所有这些都包括Envers设置。这个可能更像你正在寻找的东西:https://github.com/hibernate/hibernate-demos/tree/master/hibernate-orm/osgi/unmanaged-native