我是OSGi环境的新手,也许我想念一些东西。我无法加载OSGI包中包含的JPA实体(ClassNotFoundException)。
我正在使用Apache Felix和Hibernate。我没有使用蓝图。
这是我的架构:
我遇到的问题是在应用程序C实现中:它配置运行时org.hibernate.cfg.Configuration和load是自己的JPA模型(cfg.addAnnotatedClass(EntityTest.class))。此时我得到了这个例外:
org.hibernate.AssertionFailure:PersistentClass名称无法转换为org.hibernate.cfg.BinderHelper.getPropertyOverriddenByMapperOrMapsId(BinderHelper.java:877)中的org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:2179)中的org .hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:925)...
这是由
引起:org.hibernate.annotations.common.reflection.ClassLoadingException:无法在org.hibernate.annotations.common.util.StandardClassLoaderDelegateImpl.classForName(StandardClassLoaderDelegateImpl.java:60)加载Class [com.osgi.bundle1.model.EntityTest] )org.hibernate的org.hibernate.boot.internal.MetadataBuilderImpl $ MetadataBuildingOptionsImpl $ 4.classForName(MetadataBuilderImpl.java:758)org.hibernate的org.hibernate.annotations.common.reflection.java.JavaReflectionManager.classForName(JavaReflectionManager.java:144) .cfg.BinderHelper.getPropertyOverriddenByMapperOrMapsId(BinderHelper.java:874)... 58常见的帧省略由以下原因引起:java.lang.ClassNotFoundException:com.osgi.bundle1.model.EntityTest at org.apache.catalina.loader.WebappClassLoaderBase.loadClass (webappClassLoaderBase.java:1333)位于java.lang.Class.forName(Class.java)java.lang.Class.forName0(Native Method)的org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1167) :348)org.hibernate .annotations.common.util.StandardClassLoaderDelegateImpl.classForName(StandardClassLoaderDelegateImpl.java:57)...省略了61个常用帧
应用程序C已经导出模型,我使用了https://docs.gradle.org/current/userguide/osgi_plugin.html。
编辑:添加更多细节。
应用程序B是使用Jersey构建的webapp。它有一个启动felix的ServletContextListener:
@WebListener
public class Felixbootstrap implements ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent sce) {
OsgiHost.initialize();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
public class OsgiHost {
public static void initialize() {
OsgiHost host = new OsgiHost();
host.start();
}
private void start() {
Map<String, Object> config = new HashMap<>();
config.put(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, Arrays.asList(
, new HostBundle()//Activator that starts bundles of the project
));
config.put(FelixConstants.FRAMEWORK_STORAGE_CLEAN, Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);
//package to export
String felixPackageExportConfiguration =
//common api
"com.osgi.test.api"
+ ",com.osgi.test.dto"
//hibernate
+ ",javax.persistence;version=2.1.0"
+ ",org.hibernate"
+ ",org.hibernate.cfg"
+ ",javassist.util.proxy"
+ ",org.hibernate.proxy"
+ ",org.hibernate.query"
;
config.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, felixPackageExportConfiguration);
Felix felix = new Felix(config);
try {
felix.start();
} catch (BundleException e) {
e.printStackTrace();
}
}
}
应用程序C有一个由应用程序B上的端点调用的方法(通过公共接口)。当它被调用时,这个类被初始化(总是在应用程序C中):
public class HibernateUtil {
private SessionFactory sf;
private static HibernateUtil instance = null;
public static HibernateUtil getInstance() {
if (instance == null) {
instance = new HibernateUtil();
}
return instance;
}
private HibernateUtil() {
}
public Session getSession() {
return getSessionFactory().openSession();
}
private SessionFactory getSessionFactory() {
if (sf == null) {
Configuration cfg = new Configuration();
cfg.addAnnotatedClass(EntityTest.class);
cfg.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQL94Dialect")
.setProperty("hibernate.connection.datasource", "java:comp/env/jdbc/jdbcname")
.setProperty("hibernate.ejb.naming_strategy", "org.hibernate.cfg.DefaultNamingStrategy")
.setProperty("hibernate.archive.autodetection", "class")
.setProperty("hibernate.hbm2ddl.auto", "update")
;
sf = cfg.buildSessionFactory();
}
return sf;
}
}
这根本不像OSGi问题。堆栈跟踪表明Hibernate正在尝试从Web Application类加载器加载模型类,即部署在Tomcat上的WAR文件(Apache Catalina是实现Servlet规范的Tomcat的一部分)。
此WAR文件的WEB-INF/classes
目录或WEB-INF/lib
下的某个JAR文件中是否包含相关的类?
从代码段:
//package to export
String felixPackageExportConfiguration =
//common api
"com.osgi.test.api"
+ ",com.osgi.test.dto"
//hibernate
+ ",javax.persistence;version=2.1.0"
+ ",org.hibernate"
+ ",org.hibernate.cfg"
+ ",javassist.util.proxy"
+ ",org.hibernate.proxy"
+ ",org.hibernate.query"
;
config.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, felixPackageExportConfiguration);
它看起来非常像Hibernate在OSGi框架之外。虽然您使用的命名方案不明确,但听起来好像您的JPA实体位于OSGi包中的OSGi框架内。
然后,您引导Hibernate的方式是使用专为在平坦的Java SE类路径中使用而设计的API。没有理由期望Hibernate能够找到你的实体类型,因为Hibernate可以访问的ClassLoader没有对OSGi框架的可见性。
回到更高的层次 - 通过使用OSGi框架,您试图实现的目标是什么?如果你想使用OSGi进行数据访问,那么为什么Hibernate不能在OSGi框架内运行,因为它有机会看到实体类?
在你可以使用的OSGi框架中有一个使用JPA的标准,但是我觉得这个应用程序还有很多其他的东西你还没有告诉我们 - 例如,没有代码显示请求如何进入OSGi框架,也没有任何代码显示框架是如何停止的......
蒂姆很可能是现货。 Hibernate ORM必须以三种支持的方式之一进行引导。我们的文档遍历所有这些,看起来您可能对“非托管本机”模式最感兴趣。简而言之,除非您使用Apache Aries之类的东西来发现您的持久性单元并为您启动内容,否则您需要手动执行此操作。
https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/chapters/osgi/OSGi.html