序言:我见过this question,但这显然是关于POI的较旧版本,从那时起Apache就违反了所有Java标准。
问题:我的目标是让POI与OSGi一起使用。到目前为止,我很确定这是不可能的,但是也许你们中的一个有一个好主意。到目前为止,我尝试过的事情:
1)捆绑JAR
最简单的方法是将捆绑包信息直接添加到POI罐中(另一个答案包含有关如何执行此操作的详细信息)。因为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.xml
中的xmlbeans
)。
4)将源复制到插件
这可能是我的最爱。将源代码复制到他们自己的插件中时,会出现编译错误。 JAR poi-ooxml-3.17.jar 需要一个名为org.etsi.uri.x01903.v13.SignaturePolicyIdType
的类。该类包含在 poi-ooxml-schemas-3.17.jar 中,但令人不安的事实是其名称为SignaturePolicyIdentifierType
。
5)问Apache
有一个问题“ OSI可以使用POI吗?” in the FAQ:
从POI 3.16开始,有一种针对OSGI上下文类加载器处理的解决方法,即,它使用受限类视图的实现替换了当前上下文类加载器的线程。这将导致IllegalStateExceptions,因为xmlbeans在此简化视图中找不到xml模式定义。解决方法是初始化POIXMLTypeLoader的类加载器委托,该委托默认为当前线程上下文类加载器。初始化应在任何其他与OOXML相关的调用之前进行。示例中的类可以是任何类,它们是poi-ooxml-schema或ooxml-schema的一部分:
POIXMLTypeLoader.setClassLoader(CTTable.class.getClassLoader());
我没有尝试过,因为这对我来说没有任何意义:他们如何将非标准的JAR打包成捆?以及在加载类后如何设置类加载器甚至会有所帮助?
问题:有什么方法可以使当前的POI与OSGi一起使用?
注意::我刚刚找到了this question,但它是用于更旧版本的POI。但这显然是一个持续的问题。
答案 0 :(得分:1)
我通过构建自己的3.17 OSGi捆绑软件使其工作,我将其放入了处女座/ 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>
然后在我的调用代码中,创建一个线程并使用父类加载器。希望听到更好的方法-这并非微不足道。如果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
}
}