javax.xml.bind.JAXBException: class <ClassName> 或其任何超类在此上下文中都是已知的

Posted

技术标签:

【中文标题】javax.xml.bind.JAXBException: class <ClassName> 或其任何超类在此上下文中都是已知的【英文标题】:javax.xml.bind.JAXBException: class <ClassName> nor any of its super class is known to this context 【发布时间】:2013-09-13 01:23:27 【问题描述】:

我有一个 RESTful Web 服务,我正在使用 Java 1.6 部署在 Tomcat 6 上,但我看到了一些奇怪的行为。我正在部署这个特定的战争文件和大约 5 个其他战争文件。有问题的 Web 应用程序还定期以 xml 格式向远程服务器发送状态消息,所有 XML 绑定都是使用 JAXB 2.1.13 完成的。在初始部署后,JAXB 绑定似乎无法正常工作。也就是说,如果我启动 tomcat 并等待发送状态消息,我会收到以下错误:

javax.xml.bind.JAXBException: class StatusMessage nor any of its super class is known to this context. 

(为简洁起见,我省略了完全限定的类名)此外,对 RESTful 服务的任何传入请求都会引发相同的异常。

如果我在每次战争中打包所有库,我看不到这个问题,但我尽量不这样做,因为我的 WAR 文件变得非常臃肿。JAX 库被打包在这场战争中,但是像Spring、commons-*、hibernate 都在 tomcat/lib 中。有谁知道是什么导致了这种奇怪的部署顺序敏感性?

这里有更多代码细节,每次触发状态消息时都会发生以下情况:

JAXBElement<StatusMessage> el = ( new ObjectFactory() ).createHeartbeat( statusMessage );
ApiUtils apiUtil = new ApiUtils();

NamespaceFilter outFilter = new NamespaceFilter("http://middleware/status", true);
String xml = apiUtil.makeXml( el, "com.package.path.status", ApiUtils.getFormatXMLSetting(), ApiUtils.getValidateXMLSetting(), outFilter);

makeXML 调用如下所示:

public String makeXml(JAXBElement el, String packageName, Boolean formatXml, Boolean validateXml, NamespaceFilter outFilter) throws JAXBException,
SAXException, UnsupportedEncodingException, IOException

    // Marshal XML
    JAXBContext jaxbContext = JAXBContext.newInstance( packageName );
    Marshaller marshaller = jaxbContext.createMarshaller();

    OutputFormat format = new OutputFormat();;
    if (formatXml)
        format.setIndent(true);
        format.setNewlines(true);
    

    //Create a filter that will remove the xmlns attribute      
    if(outFilter == null)
        outFilter = new NamespaceFilter(null, false);

    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    if ( validateXml ) 
        SchemaFactory schemaFactory = SchemaFactory.newInstance( "http://www.w3.org/2001/XMLSchema" );
        InputStream is = this.getClass().getClassLoader().getResourceAsStream( packageName.replaceAll( "\\.", "/" ) + "/schema.xsd" );
        Source source = new StreamSource( is );
        Schema schema = schemaFactory.newSchema( source );

        // This line enforces schema validation
        marshaller.setSchema( schema );
    

    XMLWriter writer = new XMLWriter(baos, format);
    outFilter.setContentHandler(writer);

    marshaller.marshal( el, outFilter );

    return baos.toString( "UTF-8" );

马歇尔线是引发异常的地方。似乎每次执行时都应该创建 JAXB 上下文。

更新、取消部署/重新部署并不总能解决这个问题,但是用它打包所有库。是否有我需要注意的静态对象?

【问题讨论】:

【参考方案1】:

在您的代码中的某处,您正在创建一个JAXBContext 对象,该对象列出了所有可以编组和/或取消编组的Java 类。将包名称或 ObjectFactory 传递给它是很常见的,以便它知道很多类。该错误消息听起来好像在构造 JAXBContext 时上下文中的那些类不在类路径中。

跟踪代码并找到构造此JAXBContext 实例的位置并检查正在设置的Java 类。它在重新部署后起作用的事实让我认为这是一个类路径问题;可能在其余代码加载之前,某些类没有被加载到类路径中。

web.xml 中的 load-on-startup 值也可能提供一些提示。

【讨论】:

不幸的是,这两个建议都没有对这个问题产生太大影响。 谢谢。我需要将正确的 getter 和 setter 添加到我的 ObjectFactory【参考方案2】:

我的团队遇到了同样的错误消息。在我们的例子中,有问题的类在两个 jar 文件中,看起来旧版本正在加载到 JAXBContext 中。清理完重复的类文件后,问题就解决了。

【讨论】:

以上是关于javax.xml.bind.JAXBException: class <ClassName> 或其任何超类在此上下文中都是已知的的主要内容,如果未能解决你的问题,请参考以下文章