我有一个 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 上下文。
更新、取消部署/重新部署并不总能解决这个问题,但是用它打包所有库。我需要注意的地方是否有静态对象?