设置要使用的JAXB上下文工厂初始化类

时间:2013-11-01 16:59:12

标签: java jaxb websphere

我已经更新了我们的项目(基于Java EE,在Websphere 8.5上运行),以使用公司内部框架的新版本(以及Ejb 3.x部署描述符而不是2.x部署描述符)。从那时起,我的集成测试失败,出现以下异常:

 [java.lang.ClassNotFoundException: com.ibm.xml.xlxp2.jaxb.JAXBContextFactory]

我可以使用之前的框架版本构建应用程序,一切正常。 调试时我注意到在ContextFinder(javax.xml.bind)中有两种不同的行为:

  1. 以前的版本(一切正常):不同的地方都没有出现工厂类,因此加载了默认的工厂类,即com.sun.xml.internal.bind.v2.ContextFactory(定义为类中的字符串常量)。

  2. 升级版本(ClassNotFound):有一个资源" META-INF / services / javax.xml.bind.JAXBContext" beeing成功加载并且第一行读取使ContextFinder尝试加载" com.ibm.xml.xlxp2.jaxb.JAXBContextFactory"这会导致错误。

  3. 我现在有两个问题:

    1. 那资源是什么类型的?因为在我们的EAR中有两个WAR,这两个中没有一个包含文件夹服务 META-INF目录。

    2. 那个价值在哪里呢?因为档案室向我显示没有新的或更改的属性文件。

    3. 无需说我将阅读有关JAXB配置可能性的所有内容,但如果您对可能出错的内容有所了解或帮助我使用该资源(是否需要查找真实文件?)我非常欣赏。非常感谢!

      编辑(根据评论输入/问题):

        

      出于好奇,您的框架是否包含JAXB JAR?您的框架的旧版本是否包含jaxb.properties?

      确实(我有点惊讶)该框架在EAR中有一个自定义的eclipselink-2.4.1-.jar,它包括一个JAXB实现和一个jaxb.properties文件,在两个版本中显示以下条目(一个找到工厂以及抛出异常的工厂:

      javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
      

      我认为这与当前问题无关,因为jar在两个EAR(运行的那个/带有期望的那个)中保持完全相同

        

      我也不清楚为什么旧版本的框架选择了com.sun实现

      有一个类javax.xml.bind.ContextFinder,它负责初始化JAXBContextFactory。此类搜索各种访问以查找jaxb.properties文件或" javax.xml.bind.JAXBContext"资源。如果所有这些地方都没有显示要使用哪个Context Factory,那么就会加载一个在类本身中硬编码的deault工厂:

      private static final String PLATFORM_DEFAULT_FACTORY_CLASS = "com.sun.xml.internal.bind.v2.ContextFactory";
      

      现在回到我的问题:

      使用以前版本的框架(以及EJB 2.x部署描述符)构建一切正常。调试时我可以看到没有找到配置,因此上面提到了默认工厂。

      使用新版本的框架构建(以及我可以部署的EJB 3.x部署描述符)只有TESTCASE失败但其余功能都有效(就像我可以向我们的web服务发送请求而它们不会触发任何错误)。调试时我可以看到找到了配置。该资源名为" META-INF / services / javax.xml.bind.JAXBContext"。以下是此资源如何导致尝试加载com.ibm.xml.xlxp2.jaxb.JAXBContextFactory'然后抛出ClassNotFoundException。这是上述javax.xml.bind.ContextFinder类的简化源:

      URL resourceURL = ClassLoader.getSystemResource("META-INF/services/javax.xml.bind.JAXBContext");
      
      BufferedReader r = new BufferedReader(new InputStreamReader(resourceURL.openStream(), "UTF-8"));
      
      String factoryClassName = r.readLine().trim();  
      

      字段factoryClassName现在具有值' com.ibm.xml.xlxp2.jaxb.JAXBContextFactory'

      因为这已成为一个超级大问题,我还会添加赏金:) 我将整天工作,如果有任何消息,请告知您。

      更新/解决方案

      这个问题已经解决了。原始问题已经发生,因为错误配置了复杂构建的多模型maven项目,其中一个依赖项使用了自定义eclipse链接jar的更新版本,其中包含发生错误的组件中不可用的JAXBFactory的定义。在大多数情况下,设置JAXB上下文工厂是使用包含相同定义的jaxb.propertie文件或JAXBContext文件配置的。适当的JAXBContextFactory的详细加载过程发生在javax.xml.bind.ContextFinder中。

      错误尚未解决(事实上超过4个主要EE / SE应用程序导致错误)并且没有一般答案但是定义的JAXBContextFactorys必须存在于您的类路径中(哇多么奇怪......)所以你要么有一个ClassNotFound错误,因为你缺少资源(这就是实际原因),或者因为你在上面提到的任何属性文件中定义了一个错误的JAXBContextFactory,其中包含根据下面答案的定义。

      非常感谢您的出色评论和支持,我真的很感激!

2 个答案:

答案 0 :(得分:5)

您可以在与域模型相同的包中包含jaxb.properties文件,以指定您希望使用的JAXB(JSR-222)实现。例如,如下所示将EclipseLink MOXy指定为JAXB提供程序。

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

了解更多信息

答案 1 :(得分:3)

另一个对我有用的快速和脏的解决方案(真正的解决方法)是明确地将jAXB实现包含到maven构建中。例如

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.2.7</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.2.7</version>
</dependency>

请注意,这会为您的构建添加一些不必要的依赖,因为JAXB显然已经是每个JRE&gt; =版本6的一部分。

最有可能的是,只有当WAS类加载器设置为父级时才会起作用。