即使所需的 JAR 在 Bundle-classpath 中,OSGI 类也不可见
Posted
技术标签:
【中文标题】即使所需的 JAR 在 Bundle-classpath 中,OSGI 类也不可见【英文标题】:OSGI classes not visible even though the required JARs are in Bundle-classpath 【发布时间】:2012-01-03 16:08:50 【问题描述】:我们正在使用基于 Equinox 的 OSGI 框架来运行多个包。 我们的包在 Bundle-classpath 中有依赖的 JAR,依赖的 JAR 与其他类和资源一起打包在一个 JAR/WAR 文件中。 但是我们在运行多个这样的 Bundle 时遇到了问题。 说, Bundle A:经过全面测试/工作的 JAR 包。包含捆绑包类路径中的所有依赖 JAR 和内部的所有依赖 JAR(在名为 lib 的文件夹下)。通过仅部署此捆绑包进行测试时工作正常
Bundle B:与 Bundle A 类似。单独部署时再次工作
但是当两个包一起加载时,OSGI 无法从包类路径中提到的 JAR 中为第二个加载的包加载类。第一个加载的包运行良好,而第二个加载的包失败。
当前在 SPRING 尝试加载 javax.persistence.QueryHint
类时会出现此问题。
我们使用我们的 xxxx-EntityManager.xml 创建一个数据源,我们在其中创建我们的entityManagerFactory
使用的依赖 JAR:(两个包中的 JAR 相同)
春季:3.0.6.RELEASE JARS 休眠:3.6.7 罐子 Hibernate-JPA:hibernate-jpa-2.0-api-1.0.1.Final.jar例外:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'targetDataSources' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [xxxx-EntityManager.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: interface javax.persistence.QueryHint is not visible from class loader
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:102)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:58)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1358)
注意:
两个捆绑包都经过单独测试并且工作正常 我们知道,我们可以在包之外提取第三方 JAR 并使用 import-package,而不是创建 Bundle-classpath。但是对于当前的要求,我们只需要父包中的第三方 JAR。请求 OSGI 专家帮助我们。
【问题讨论】:
我认为下面的答案已经过时了,我们首先需要更多信息。 应该可以创建两个捆绑包,以便它们完全隔离并单独工作。我想知道javax.persistence
包是从 working 包中的哪个位置加载的。
【参考方案1】:
我建议将您的依赖项放在单独的包中,并使所有包对其他包可见。然后将这些单独的包添加为依赖项(或者更好:只导入所需的包而不是整个包!)。这样,您可以确保您的依赖项只加载一次。我建议您当前的配置会导致类加载问题,因为类被加载两次,很可能是相同的serialVersionUID
。而且由于每个包都有自己的类加载器,第二个包将看不到辅助(未)加载的类。
【讨论】:
感谢您的 cmets。是的,我们也有这样做的计划。但是根据我们的要求,我们将为此版本提供大型自给自足的捆绑包(使用捆绑类路径),并为即将发布的捆绑包提供更精细的捆绑包(使用导入包)。如果我们能让包 A 和 B 像现在一样工作,那将会很有帮助。.. 如果@Tassos Bassoukos 建议的解决方案也不适合,恐怕也没有办法。无论如何不建议在 OSGi 环境中使用类路径。而且我很确定您使用的 JAR 已经有 OSGi 捆绑版本,所以这一步非常小。此外,OSGi 的概念与大型可交付成果完全相反。 我不同意,应该可以创建两个捆绑包,以便它们封装所有必需的功能并且可以独立使用(尽管我同意它不是最佳的)。这里还有其他事情发生,我们需要深入了解。 我采用了“hibernate-jpa-2.0-api-1.0.1.Final.jar”的OSGI兼容版本(捆绑)并安装在OSGI VM中。然后我修改了我的包“A”和“B”以导入 javax.persistence.* 包。通过这样做,解决了早期的类可见性异常。但我们有一个新的例外。 java.lang.IllegalStateException: EntityManagerFactory interface [interface org.hibernate.ejb.HibernateEntityManagerFactory] 似乎与 Spring 的 EntityManagerFactoryInfo mixin 冲突 - 考虑将 'entityManagerFactoryInterface' 属性重置为普通 [javax.persistence.EntityManagerFactory] 我们使用这个bean定义和一堆参数来创建数据源“如果您不能将 JAR 打包为单独的包,请指定 A 或 B 以包含所有 JAR,导出所有包,并使另一个包依赖它(并从第二个包中删除 JAR)。
【讨论】:
这可能对我们不起作用。我们有一个要求,其中每个捆绑包 A/B 都应该在同一个 OSGI VM 中独立工作并一起工作。因此,我们不能从任何一个包中排除这些库,而只能依赖于导入包。 那么你就在没有桨的众所周知的小溪上,因为本地包类路径将优先于导入;由于您将拥有两组相同的类,因此您将在两个类加载器中加载相同的类,并且这些类将彼此不兼容。以上是关于即使所需的 JAR 在 Bundle-classpath 中,OSGI 类也不可见的主要内容,如果未能解决你的问题,请参考以下文章