OSGi中Envers的类加载器问题

问题描述 投票:1回答:2

我已经在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添加到插件中以添加上述内容。它不会起作用。

如何解决这些类加载器问题?

osgi hibernate-envers
2个回答
0
投票

如果您的@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'
        )
    }
}

0
投票

晚到派对,但在这里抛出这个以防其他人需要它:

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

© www.soinside.com 2019 - 2024. All rights reserved.