7

我在同一个 Tomcat 上运行的两个单独的战争中使用 Amazon S3 开发工具包。我在我的一项 Spring 服务的 @PostConstruct 中初始化了一个 AmazonS3Client。

如果我单独运行这些战争,通常一切正常。如果我一起运行它们,其中一个(第二个启动)会引发以下异常:

com.amazonaws.AmazonClientException:无法为 XMLReader 初始化 sax 驱动程序

如果发生这种情况,我有一个解决方法,我在捕获 AmazonClientException 后设置以下系统属性:

try {
  init();
} catch (AmazonClientException ase) {
  System.setProperty("org.xml.sax.driver", "com.sun.org.apache.xerces.internal.parsers.SAXParser");
  init();
}

但这当然是可怕的。有一个更好的方法吗?为什么会在这些情况下发生?

更新:起初,似乎将 AmazonS3Client 的初始化移出 @PostConstruct 并延迟初始化它完全防止了这个错误。但显然它有时仍然会发生 - 即使我只进行一场战争而不是两者。

4

2 回答 2

5

XMLReader 通过一系列步骤来识别要使用的驱动器。引用文档

  • 如果系统属性 org.xml.sax.driver 有一个值,则该值用作 XMLReader 类名。
  • JAR“服务 API”用于在运行时可用的 jarfile 中的 META-INF/services/org.xml.sax.driver 文件中查找类名。
  • 强烈建议 SAX 解析器分发提供默认的 XMLReader 类名,该类名仅在之前的选项(在此列表中)不成功时才会生效。
  • 最后,如果 ParserFactory.makeParser() 可以返回系统默认的 SAX1 解析器,则该解析器将包装在 ParserAdapter 中。(这是 SAX1 环境的迁移辅助工具,其中 org.xml.sax.parser 系统属性通常可用。)

查看AWS开发工具包的代码...

public XmlResponsesSaxParser() throws AmazonClientException {
    // Ensure we can load the XML Reader.
    try {
        xr = XMLReaderFactory.createXMLReader();
    } catch (SAXException e) {
        // oops, lets try doing this (needed in 1.4)
        System.setProperty("org.xml.sax.driver", "org.apache.crimson.parser.XMLReaderImpl");
        try {
            // Try once more...
            xr = XMLReaderFactory.createXMLReader();
        } catch (SAXException e2) {
            throw new AmazonClientException("Couldn't initialize a sax driver for the XMLReader");
        }
    }
}

有几件事我不喜欢该代码。

  1. SaxException e 的根本原因被吃掉了。
  2. SaxException e2 的根本原因也被吃掉了。代码至少应该打印一条提及根本原因的警告。
  3. 在关卡框架代码中使用 System.setProperty() 可能会导致一些难以调试的问题。

这些点使调试问题变得更加困难。我能做出的最有根据的猜测是,深红色解析器可以在一个类加载路径中访问,但在另一个类加载路径中不存在。找到问题的一个决定性方法是在代码上设置一个断点,试图实例化阅读器并找出根本原因是什么。

于 2012-10-21T12:24:44.893 回答
1

由于它使用单例模型,因此隔离此调用的唯一方法是在 WAR 本身中拥有一整套与 SAX 相关的 JAR(它们将加载到不同的类加载器)。当我遇到同样的问题时,它对我有用。这将产生 PermGen 的影响,但是该怎么办。或者如果您不介意更改 S3 库,请将此方法静态同步并共享该库。如果亚马逊的人让这个电话同步,这不会是问题。

于 2012-10-28T09:22:28.737 回答