- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试在 osgi 环境 (Liferay DXP) 中使用 JAXB 2.2.11。我在创建 JAXBContext 时遇到问题。基于研究时发现的其他一些来源,如 this和 this ,我已经确定在 osgi 容器中我需要为 JAXB 提供正确的类加载器来实例化上下文。所以我有这样的代码:
ClassLoader cl package.with.jaxb.objects.ObjectFactory.class.getClassLoader();
JAXBContext jc = JAXBContext.newInstance("package.with.jaxb.objects", cl);
此代码会导致空指针异常,堆栈跟踪如下:
Caused by: java.lang.NullPointerException
at javax.xml.bind.ContextFinder.handleClassCastException(ContextFinder.java:129)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:201)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:146)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:371)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:446)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:409)
查看 ContextFinder 的来源我可以在第 129 行看到 context
必须为 null:
抛出 handleClassCastException(context.getClass(), JAXBContext.class);
我认为问题可能在于我的模块依赖于 jaxb-api 2.2.11,但是 jaxb-impl 类在运行时由 rt.jar 提供并且可能比 2.2.11 更新,因为 Liferay DXP 在 JDK 上运行1.8.为了解决这个问题,我尝试将 jaxb-impl.jar 2.2.11 作为依赖项包含在我的 osgi 模块中,认为 jaxb-api 和 jaxb-impl 版本会匹配。之后,尝试使用与上面相同的代码创建 JAXBContent 会导致以下错误:
ClassCastException: attempting to cast jar:file:/C:/Program%20Files/Java/jdk1.8.0_144/jre/lib/rt.jar!/javax/xml/bind/JAXBContext.class to bundleresource://623.fwk616113009:13/javax/xml/bind/JAXBContext.class. Please make sure that you are specifying the proper ClassLoader.
从这条消息的外观来看,正在实例化的 JAXBContext 来自通过 rt.jar 加载的 JAXBContext 版本。这让我很困惑,因为我希望使用由我的模块的类加载器加载的 JAXBContext 版本,因为我已经在我的模块中包含了 jaxb-impl.jar 并且我已经指定我的模块的类加载器是在我对 JAXBContext.newInstance 的调用。谁能阐明我如何让 jaxb 2.2.11 在 osgi 容器中工作?
*请注意,我无法升级模块使用的 jaxb-api 版本,因为 JAXB 代码实际上位于需要 jaxb 2.2.11 的第 3 方 jar 中(我刚刚从现在通过编写一些测试 JAXB 代码来解决方程式)。
最佳答案
经过大量研究,我找到了以下解决方案。因为它似乎按照 this post 中接受的答案所建议的那样传递了 bundle 类加载器。必须是正确的,我遵循了弄清楚为什么我在尝试时得到 NullPointerException 的路径。在仔细查看 jaxb-api 的源代码以跟踪 NullPointerException 的堆栈跟踪之后,我可以看到 jaxb-api 代码执行类似
classLoader.loadClass("com.sun.xml.internal.bind.v2.ContextFactory")
classLoader
是我的 bundle 的类加载器(因为这是我传入的),ContextFactory
实际上是 jaxb-impl 中的一个类,由引导类加载器加载.这就是问题所在,因为我的bundle 的类加载器将无法看到引导类加载器加载的类。这让我很困惑,因为我不习惯类加载器在 osgi 中的工作方式。我错误地认为引导类加载器加载的类是可见的,因为我习惯于在有委托(delegate)的情况下加载 Web 应用程序类。在 osgi 类加载器中彼此完全隔离,事物只有在导出时才可见。为了解决这个问题,我发现了 some helpful posts谈论类似的问题。原来有一个概念在 osgi 中称为引导委托(delegate),您可以在其中指定始终通过引导类加载器加载的类/包列表。所以最终的结果是两步:
1) 在调用代码以获取 JAXBContext 之前,将线程的类加载器切换到您的 bundle 类加载器:
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
try {
// ObjectFactory here is in the same package as my classes to be marshalled
ClassLoader objectFactoryClassLoader = ObjectFactory.class.getClassLoader();
Thread.currentThread().setContextClassLoader(objectFactoryClassLoader);
// JAXB code goes here
} finally {
Thread.currentThread().setContextClassLoader(currentClassLoader);
}
2) 使用引导委托(delegate)机制指定要加载的包。这个列表需要包括你需要加载的类的传递依赖。就我而言,我使用的是 Liferay,所以列表特定于 Liferay,它位于 portal-ext.properties 配置文件中。幸运的是我找到了this post有人为我完成了大部分工作:
module.framework.properties.org.osgi.framework.bootdelegation=\
__redirected,\
com.liferay.aspectj,\
com.liferay.aspectj.*,\
com.liferay.portal.servlet.delegate,\
com.liferay.portal.servlet.delegate*,\
com.sun.ccpp,\
com.sun.ccpp.*,\
com.sun.crypto.*,\
com.sun.image.*,\
com.sun.jmx.*,\
com.sun.jna,\
com.sun.jndi.*,\
com.sun.mail.*,\
com.sun.management.*,\
com.sun.media.*,\
com.sun.msv.*,\
com.sun.org.*,\
com.sun.syndication,\
com.sun.tools.*,\
com.sun.xml.*,\
com.yourkit.*,\
org.eclipse.persistence.internal.jaxb,\
org.eclipse.persistence.internal.jaxb.*,\
javax.xml.*,\
sun.*
有用的链接:
Why can't JAXB find my jaxb.index when running inside Apache Felix?
What is the difference between bootdelegation and DynamicImport-Package in osgi
https://web.liferay.com/web/user.26526/blog/-/blogs/liferay-dxp-and-weblogic-
https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/bundle-classloading-flow
http://apache-felix.18485.x6.nabble.com/Classloading-for-JAXB-td4834670.html
关于jaxb - 如何在 osgi (Liferay DXP) 中使用 JAXB 2.2.11,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46554116/
在我的程序中,我们已经创建了词汇表,并且在每个词汇表下创建了类别,但我正在尝试修改代码,以便我们可以在每个类别下创建子类别,并且子类别将是唯一的。 我可以使用 Liferay 在每个类别下添加一个子类
我正在使用 Liferay DXP,并创建了一个服务构建器模块。在这个模块中,我必须使用“oracle.jdbc.driver.OracleDriver”类,因为我已经开发了一个 FinderImpl
我在 Liferay DXP 中为 Google Analytics API 编写了代码。我通过在 build.gradle 中写入以下 jars compile group: 'common
Liferay DXP 7.2 无法使用 OpenJDK 启动(干净版本)。不使用任何IDE,它是Windows Server 2016版本(不认为服务器版本会有任何问题)刚刚在E:\PROJECT_
假设存在答案,这应该(我认为)有一个简单的答案。 是否可以使用 IronPython 将当前 *.dxp 项目的路径作为字符串返回?我经常在 VBA 中使用类似的东西,它变得非常有用。 我已经尝试查看
我希望得到您的支持,以便在自定义 Liferay DXP 7.0 Enterprise 中的搜索组件时获得一些帮助。 我已经查看了所有可用的文档,但尽管我找到了很多关于该问题的文章,但对我来说一步一步
到目前为止,我一直为我的主题提供某种用 Java 编写的 NavigationUtil-Class,并将其放在 docroot\WEB-INF\src 下。 我使用主题生成器和blade cli将主题
我正在尝试将 Apache POI 集成到 Liferay DXP(OSGi) 中,但无法解决 gradle 项目中与 POI 3.17 版本的依赖关系。我用下面的 JAR 创建了独立项目: poi-
我正在使用 Jenkins 进行 Liferay 7.2 部署自动化,我们在 GitLab 存储库中有 Liferay 工作区(源代码),我的问题是我无法克隆仅更改/修改的单个模块(portlet)并
我编写了下面的代码,但它总是返回用户 ID(数字,如“40156”、“20147”等),而不是用户名 有人可以告诉我如何获取屏幕名称 ThemeDisplay themeDisplay; HttpSe
我正在尝试在 osgi 环境 (Liferay DXP) 中使用 JAXB 2.2.11。我在创建 JAXBContext 时遇到问题。基于研究时发现的其他一些来源,如 this和 this ,我已经
我有下一个环境: 具有集群许可证的 Liferay 7.1 DXP(与 wildfly 16.0 捆绑在一起) 这个包在本地主机上的同一台机器(2 个节点)上运行,但端口不同 每个节点都有相同的数据库
我是一名优秀的程序员,十分优秀!