我是OSGi环境的新手,也许我想念一些东西。我无法加载OSGI包中包含的JPA实体(ClassNotFoundException)。
我正在使用Apache Felix和Hibernate。我没有使用蓝图。
这是我的架构:
应用程序A:通用接口。对此没什么好说的。
应用程序B:是WebApp。它在启动Host bundle的启动时启动felix框架。主机Host包安装特定文件夹中包含的所有bundle的jar并跟踪服务(在Application C中实现的服务)。它有应用程序A作为依赖。
应用程序C:它是客户端捆绑包。它实现了Application A接口并对其进行了注册(它将App A作为依赖项)。它还包含我在这个包中需要的所有JPA模型。
我遇到的问题是在应用程序C实现中:它配置运行时org.hibernate.cfg.Configuration和load是自己的JPA模型(cfg.addAnnotatedClass(EntityTest.class))。 此时我得到了这个例外:
org.hibernate.AssertionFailure:PersistentClass名称不能 转换成一个类 at 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:无法加载类[com.osgi.bundle1.model.EntityTest] 在org.hibernate.annotations.common.util.StandardClassLoaderDelegateImpl.classForName(StandardClassLoaderDelegateImpl.java:60) at org.hibernate.boot.internal.MetadataBuilderImpl $ MetadataBuildingOptionsImpl $ 4.classForName(MetadataBuilderImpl.java:758) 在org.hibernate.annotations.common.reflection.java.JavaReflectionManager.classForName(JavaReflectionManager.java:144) at org.hibernate.cfg.BinderHelper.getPropertyOverriddenByMapperOrMapsId(BinderHelper.java:874) ...省略了58个常用帧 引起:java.lang.ClassNotFoundException:com.osgi.bundle1.model.EntityTest 在org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1333) 在org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1167) at java.lang.Class.forName0(Native Method) 在java.lang.Class.forName(Class.java:348) at org.hibernate.annotations.common.util.StandardClassLoaderDelegateImpl.classForName(StandardClassLoaderDelegateImpl.java:57) ...省略了61个常见帧
应用程序C已导出模型,我使用了https://docs.gradle.org/current/userguide/osgi_plugin.html。
编辑添加了更多详细信息。
应用程序B是使用Jersey构建的webapp。它有一个ServletContextListener,它启动felix:
@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;
}
}
答案 0 :(得分:1)
这看起来根本不像OSGi问题。堆栈跟踪表明Hibernate正在尝试从Web Application类加载器加载模型类,即部署在Tomcat上的WAR文件(Apache Catalina是实现Servlet规范的Tomcat的一部分)。
此WAR文件的WEB-INF/classes
目录或WEB-INF/lib
下的某个JAR文件中是否有相关的类?
答案 1 :(得分:1)
来自代码段:
//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框架,也没有任何代码显示框架是如何停止的......
答案 2 :(得分:0)
https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/chapters/osgi/OSGi.html