Ste*_* S. 5 java osgi apache-poi
序言:我见过这个问题,但它显然是关于旧版本的 POI,从那时起 Apache 就违背了每个 Java 标准。
问题:我的目标是让 POI 与 OSGi 一起工作。到目前为止,我很确定这是不可能的,但也许你们中的一个人有一个好主意。到目前为止我尝试过的:
1) 捆绑 JAR
最简单的方法是将捆绑信息直接添加到 POI jars(另一个答案有关于如何做到这一点的详细信息)。这是行不通的,因为 JAR 导出相同的包,例如poi-3.17.jar和poi-ooxml-3.17.jar都导出org.apache.poi,这在 OSGi 中是不允许的(在标准 Java 中,最好的做法是也有单独的包)。
2)使用预先打包好的插件
我发现org.apache.servicemix.bundles.poi,它是由不了解 OSGi 工作原理的人创建的(也许是 Apache 人?)。它包含任何 JAR 中都不存在的不稳定依赖项,尤其是导入包org.junit让我担心。
我无法让它工作,因为并非所有必要的导入都是捆绑包。而且由于捆绑是如此明显破损,我很快就放弃了。
3) 使用带有 lib 文件夹的插件
很难找到正确的导入和导出包。最终这失败了,因为 POI JAR 导出标准包(如javax.xmlfrom xmlbeans)。
4) 将源文件复制到插件
这大概是我的最爱。当您将源代码复制到它们自己的插件中时,您会遇到编译错误。JAR poi-ooxml-3.17.jar需要一个名为org.etsi.uri.x01903.v13.SignaturePolicyIdType. 该类包含在poi-ooxml-schemas-3.17.jar 中,但令人不安的事实是它的名称是SignaturePolicyIdentifierType.
5)询问阿帕奇
有个问题“POI可以和OSGI一起使用吗?” 在常见问题解答中:
从 POI 3.16 开始,有一个 OSGIs 上下文类加载器处理的解决方法,即将线程当前上下文类加载器替换为有限类视图的实现。这将导致 IllegalStateExceptions,因为 xmlbeans 在这个简化的视图中找不到 xml 模式定义。解决方法是初始化 POIXMLTypeLoader 的类加载器委托,默认为当前线程上下文类加载器。初始化应该在任何其他 OOXML 相关调用之前进行。示例中的类可以是任何类,它是 poi-ooxml-schema 或 ooxml-schema 的一部分:
POIXMLTypeLoader.setClassLoader(CTTable.class.getClassLoader());
我没有尝试过,因为它对我来说没有任何意义:他们是如何将不符合标准的 JAR 打包成包的?以及如何在类加载后设置类加载器甚至有帮助?
问题:有没有办法让当前的 POI 与 OSGi 一起工作?
注意:我刚刚发现了这个问题,但它是针对更旧版本的 POI。但显然这是一个持续存在的问题。
小智 1
我通过构建自己的 3.17 OSGi 包来让它工作,我将其放入 Virgo /repository/usr 中:
<project ..>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.1.7</version>
<packaging>bundle</packaging>
<name>OSGi-wrapped poi-ooxml</name>
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>com.github.virtuald</groupId>
<artifactId>curvesapi</artifactId>
<version>1.04</version>
</dependency>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>stax</groupId>
<artifactId>stax-api</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.7</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Export-Package>org.apache.poi.*</Export-Package>
<!--
One important thing to note: if you are not exporting a package, you add it to the Private-Package instruction.
Otherwise, the classes inside the package will not be copied to your bundle, as the default value of this instruction is empty.
-->
<Private-Package>org.openxmlformats.*,org.apache.commons.*,com.graphbuilder.curve.*,org.apache.xmlbeans.*,schemaorg_apache_xmlbeans.*,schemasMicrosoftComOfficeExcel.*</Private-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
Run Code Online (Sandbox Code Playgroud)
然后在我的调用代码中,我创建一个线程并使用父类加载器。希望听到更好的方法 - 这对于设置来说并不简单。如果 Apache 有 OSGi 包就好了。我可能有额外或缺少的步骤,但正在使用以下代码生成 Excel 文件:
public void write(OutputStream out) throws IOException {
Runnable sheetCreator = new Runnable() {
@Override
public void run() {
Workbook workbook = null;
try {
// 3.16, but now obsolete
// POIXMLTypeLoader.setClassLoader(CTTable.class.getClassLoader());
workbook = new XSSFWorkbook();
buildWorkbook(workbook);
workbook.write(out);
out.flush();
} catch (Throwable t) {
// log
} finally {
if (workbook != null) {
try {
workbook.close();
} catch (IOException e) {
// log
}
}
}
}
};
try {
Thread thread = Thread.currentThread();
ClassLoader cl = thread.getContextClassLoader();
Thread th = new Thread(sheetCreator);
th.setContextClassLoader(cl.getParent());
th.start();
th.join();
} catch (Throwable t) {
// log
}
}
Run Code Online (Sandbox Code Playgroud)