5

我有一个 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 上下文。

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

4

2 回答 2

8

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

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

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

于 2013-09-09T14:48:21.537 回答
0

我的团队遇到了同样的错误消息。在我们的例子中,有问题的类位于两个 jar 文件中,并且似乎旧版本正在加载到 JAXBContext 中。一旦清理了重复的类文件,问题就解决了。

于 2014-01-15T14:26:33.290 回答