当前位置: 首页 > 知识库问答 >
问题:

JAXB内部实现接口com.sun.xml.bind.NamespacePrefixMapper的类加载器问题

祁绪
2023-03-14

我需要帮助解决以下问题:我使用Websphere Liberty 19.0.0.9和Oracle以及IBM Java1.8运行一个包含EJB的旧应用程序(EAR),它用JAXB序列化XML。应用程序需要控制XML名称空间定义和前缀,并通过将com.sun.XML.bind.NamespacePrefixMapper的实现提供给javax.XML.bind.Marshaller.SetProperty(属性为“com.sun.XML.bind.NamespacePrefixMapper”)来实现。在运行时,加载实现类时出现错误java.lang.NoClassDefoundError:com/sun/xml/bind/marshaller/namespacePrefixMapper。server.xml包含JavaEE-8.0特性,自由的JAXB实现WLP-19.0.0.9\lib\com.ibm.ws.JAXB.tools.2.2.10_1.0.32.jar包含类com.sun.xml.bind.Marshaller.NamespacePrefixMapper。

我试图通过将jaxb-impl-2.2.4.jar放入ear/lib来解决这个问题(这是错误的,因为JAXB是由JEE提供的),但是在com.sun.xml.bind.v2.runtime.MarshallerImpl.SetProperty(MarshallerImpl.java:511)中出现了一个错误,因为检查if(!(value instanceof NamespacePrefixMapper))失败,因为实现的Classloader(AppClassLoader)为类NamespacePrefixMapper提供了另一个类对象,而不是MarshallerImpls的Classloader(org.eclipse.osgi.internal.loader.equinoxClassLoader)。但这表明liberty可以访问NamespacePrefixMapper。

在加载实现和MarsHallerImpl时,我多次尝试使用相同的类加载器,并尝试通过server.xml中的classloder设置来解决这一问题。没有成功。我知道不建议使用这样的JAXB实现特定类,但应用程序是这样开发的,不能轻易更改。

感谢任何帮助,它告诉我如何说服liberty将NamespacePrefixMapper类提供给application classloader或者在MarsHallerImpl中也使用application classloader NamespacePrefixMapper。谢谢你。

//The implementation class looks for example like this:
public class MyNamespacePrefixMapperImpl extends com.sun.xml.bind.marshaller.NamespacePrefixMapper {...}
JAXBContext c = JAXBContext.newInstance(some mapped class);
Marshaller m = c.createMarshaller();
com.sun.xml.bind.marshaller.NamespacePrefixMapper mapper = new MyNamespacePrefixMapperImpl();// Here the NoClassDefFoundError occurs.
m.setProperty("com.sun.xml.bind.namespacePrefixMapper", mapper); // Here the instanceof check fails if jaxb-impl.jar is in EAR/lib.

共有1个答案

郑俊彦
2023-03-14

这是一个不稳定的局势,没有一个容易的解决办法。Liberty试图“隐藏”内部包,以避免用户想要的实现版本与框架提供的略有不同的场景--这个问题最明显的例子是在传统的was中,用户想要使用的Jakarta Commons日志版本与附带的was不同--这要求用户提供自己的,或者在一个隔离的共享库中,或者使用其他父级Last类加载黑客来使其工作。Liberty通过将内部实现与用户应用程序隔离来避免这些问题。

因此,当用户想要使用与Liberty提供的不同版本的第三方库时,这非常有效,但是正如您所发现的,当您的遗留应用程序依赖于那些隐藏的/隔离的第三方库时,这就不那么有效了。

最理想的解决方案是重构应用程序代码,使其不依赖于内部JAXB类--拥有更多JAXB专业知识的人也许可以帮助实现这一点。但听起来那可能不可行,所以另一个替代方案将是创建一个用户特性。用户特性本质上是对Liberty运行时的扩展--因此它可以访问用户应用程序没有的包。它还允许您将包添加为用户应用程序的API--因此您可以使用用户特性将com.sun.xml.bind.marshaller添加为公共API--然后您的用户应用程序可以自由地扩展它。您还可以在用户特性中包含MyNamespacePrefixMapPerImpl类,并在其中注册它,以便它自动应用于服务器中的所有应用程序。

您可以在这里找到关于用户特性的更多信息:https://www.ibm.com/support/knowledgecenter/en/sseqtp_liberty/com.ibm.websphere.wlp.doc/ae/twlp_feate_example.html

希望这有帮助,安迪

 类似资料:
  • 如果我有一个内部类声明,例如: 其次是: A$B内部类也会加载吗?如果B内部类没有被声明为“静态”呢?

  • 问题内容: 我将如何为正在实现接口的内部类编写构造函数?我知道我可以上一门全新的课,但是我认为必须有一种方法可以做到这一点: 当我输入此内容时,它不会将AbstractAction方法识别为构造函数(编译器要求返回类型)。有人有主意吗? 问题答案: 只需在扩展类的名称后面插入参数即可: 另外,您可以使用初始化块:

  • 使用(方法1)单独的侦听器类(可能是内部类)的好处/缺点是什么: 与(方法2)实现接口 与(方法3)相比,为每个需要侦听器的元素设置一个匿名类。 问:这些方法的优点和缺点是什么?是否有性能优势,或者任何推荐一个而不是另一个的设计模式?或者任何其他好处? 我可以看到: 第一种方法是清洁 注意:我看到一个关于嵌套类vs实现ActionListener的问题;但大多数答案似乎给出了患者使用的方法,而不是

  • 我有一个类,它实现了接口。类由system classloader加载,接口在第三方组件中定义,我认为第三方组件将接口加载到另一个类加载器(动态类加载器)中。 当我试图创建的新实例时,我得到的是的。我想这是因为它是由不同的类加载器加载的。 我尝试创建(与Guice使用的类似),然后从system类加载器加载类,并从另一个类加载器加载所有其他类,我认为这是用于的类加载器,但没有成功。 有办法绕过它吗

  • 问题内容: 这两个内部类声明之间有什么区别?还评论优点/缺点吗? 案例A:班级内的班级。 案例B:接口内的类。 进行了更正:放置getvalue方法。 进一步的信息:我能够在没有实现AT AT ALL接口的另一个类中实例化A和B的Items类。 由于未实例化接口,因此不通过实例化LEVELS接口就可以通过点表示法来访问接口内的所有元素,这仅仅是因为您无法实例化接口- 有效地使接口内定义的类可渗透静

  • 问题内容: C ++具有多重继承。汇编级别的多重继承的实现可能非常复杂,但是在线上通常有很好的说明(vtable,指针修复,thunk等)。 Java没有多重实现继承,但是它确实具有多重接口继承,因此我认为每个类只有一个vtable的直接实现无法实现。java如何在内部实现接口? 我意识到与C++相反,Java是Jit编译的,因此不同的代码段可能会进行不同的优化,并且不同的JVM可能会做不同的事情