Oracle JVM runtime error: Provider com.sun.xml.stream.ZephyrParserFactory not found

Oracle JVM runtime error: Provider com.sun.xml.stream.ZephyrParserFactory not found

背景:

我们有一个 Oracle 11g 数据库 运行 一个 Java 带有 JRE 1.6 版的虚拟机。0_43。我们的用户界面托管在 Apache 网络服务器上,该服务器通过 mod-plsql.

与数据库交互

我们有一些 PLSQL 程序调用存储在 Java 数据库中的 Java 程序 - 一个例子是我们用来生成 XLS 文件的 Java 程序。

我们之前一直在使用 Apache POI 套件 3.8 版通过 DOM 解析器从 XML 生成 XLS 文件,但我们已经升级到 POI 3.9 以便我们可以使用流式传输 XSSF 工作簿 classes 以高效生成 XLSX 文件(SXSSF 在 POI 3.8 中可用,但核心过程 dispose() 直到 POI 3.9 才可用)。

同样出于效率原因,我们在生成 XLSX 文件时使用 StAX 解析 (XMLStreamReader),而不是我们用于 XLS 生成的更耗内存的 DOM 解析器方法。

要将我们数据库中的 Java POI 3.8 升级到 3.9,我们有两个步骤:

1) 运行 将 java 放到包含 POI 3.8 套件的罐子上:

dropjava -user=xxxxxx@xxxxxx poi-3.8-20120326.jar poi-examples-3.8-20120326.jar poi-excelant-3.8-20120326.jar poi-ooxml-3.8-20120326.jar poi-ooxml-schemas-3.8-20120326.jar poi-scratchpad-3.8-20120326.jar lib\commons-logging-1.1.jar lib\junit-3.8.1.jar lib\log4j-1.2.13.jar ooxml-lib\dom4j-1.6.1.jar ooxml-lib\stax-api-1.0.1.jar ooxml-lib\xmlbeans-2.3.0.jar

2) 然后我们运行一个loadjava命令来安装3.9套件:

loadjava -user=xxxxxx@xxxxxx -genmissing -resolve -force poi-3.9-20121203.jar poi-examples-3.9-20121203.jar poi-excelant-3.9-20121203.jar poi-ooxml-3.9-20121203.jar poi-ooxml-schemas-3.9-20121203.jar poi-scratchpad-3.9-20121203.jar lib\commons-logging-1.1.jar lib\junit-3.8.1.jar lib\log4j-1.2.13.jar ooxml-lib\dom4j-1.6.1.jar ooxml-lib\stax-api-1.0.1.jar ooxml-lib\xmlbeans-2.3.0.jar

XLSX 生成一开始根本不起作用;我们在运行时 Java 中收到此异常:

java.lang.ClassCastException

我们没有确认具体是哪个 class 导致了问题,但我们注意到,在安装 POI 3.9(包括 StAX stax-api-1.0.1 jar)之后,有在我们数据库的 Java class 库中有一些重复项。具体来说,这些 classes 及其路径被复制(并被导入到我们的 xlsx 生成 Java 来源):

import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;

考虑到重复项可能导致异常,我们删除了 StAX 解析器 jar(StAX 套件 "folded-in" 在我们的 Java 版本之前的某个时候成为核心 JDK , 所以可能不需要导入 POI 3.9 中包含的 StAX jar):

dropjava -user=xxxxxx@xxxxxx ooxml-lib\stax-api-1.0.1.jar

这删除了重复的 classes 并解决了 ClassCastException,即它不再发生。但是有一个新的问题。

问题:

新的 XLSX 方法现在在运行时间歇性失败并出现此错误:

javax.xml.stream.FactoryFinder$ConfigurationError: Provider com.sun.xml.stream.ZephyrParserFactory not found

有问题的 class、com.sun.xml.stream.ZephyrParserFactory、 似乎已正确安装在我们的数据库中。我们在一个单独的平台上做了一些测试,我们发现删除 class 完全破坏了我们的解析,即我们确信 class 安装在我们的实时平台上,因为我们的代码最有效的时间,但如果未安装 class,则可以工作 none。

错误大约每 10 次左右的 XLSX 生成尝试发生一次(我们每次都使用不同的文件和相同的文件进行测试 - [=85= 的内容似乎无关紧要) ] 是)。这行代码产生错误:

XMLInputFactory factory = XMLInputFactory.newInstance();    

通过一些调查,我们发现错误是否发生取决于哪个 Oracle 会话正在处理网络服务器收到的初始 HTTP 请求。 我觉得这里真正的问题是什么可能导致仅某些 Oracle 会话无法访问作为提供者的 Zephyr class 并产生错误? 任何想法都会很好赞赏。

这可能与此处描述的 CDATA events 的处理有关 http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.6/tutorial/doc/SJSXP5.html

是否触发此事件取决于输入文件。如果事件被抛出,你会得到 Provider com.sun.xml.stream.ZephyrParserFactory not found 错误。

您需要调查哪些代码试图实例化这个具体的服务提供者。

通常,实现特定接口的服务提供者在 Jar 文件内的目录 META-INF/services 中声明。在此处找到 ServiceLoader 的描述,其中提供 a simple service-provider loading facility

基于:

how to override a service provider in java

https://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.6/tutorial/doc/SJSXP4.html

您可以为 javax.xml.stream.XMLInputFactory 设置系统 属性 以指定实现 class 用于在运行时创建 XMLInputFactory 的实现实例。

我们在核心 Java API 中有这样一个实现 class 可用,存储在我们的数据库 class 库中:

XMLInputFactoryImpl

我们现在在 Java 过程开始时使用这样的一行来为该 Oracle 会话期间设置系统 属性:

System.setProperty("javax.xml.stream.XMLInputFactory", "<class path>XMLInputFactoryImpl");

这似乎解决了我们的一些 Oracle 会话在运行时遇到的 XMLInputFactory 服务提供者混淆问题。