OSGi中的Apache POI 3.17 [英] Apache POI 3.17 in OSGi

查看:113
本文介绍了OSGi中的Apache POI 3.17的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

序言:我看过此问题,但这显然是关于POI的较早版本,从那以后Apache就违反了所有Java标准.

Preamble: I've seen this question, but it's obviously about an older version of POI, and Apache went contra to every Java standard since then.

问题:我的目标是使POI与OSGi一起使用.到目前为止,我很确定这是不可能的,但是也许你们中的一个有个好主意.到目前为止,我尝试过的事情:

Problem: My goal is to get POI to work with OSGi. As of now I'm pretty sure that's not possible, but maybe one of you guys has a good idea. What I tried so far:

1)捆绑JAR

最简单的方法是将捆绑包信息直接添加到POI罐中(另一个答案包含有关如何执行此操作的详细信息).因为JAR会导出相同的软件包,例如 poi-3.17.jar poi-ooxml-3.17.jar 都导出org.apache.poi,这在OSGi中是不允许的(并且在标准Java中,这是最佳做法也可以使用单独的程序包.)

The easiest would be to add bundle information directly to the POI jars (the other answer has details on how to do that). This cannot work, because the JARs export the same packages, e.g. poi-3.17.jar and poi-ooxml-3.17.jar both export org.apache.poi, which is not allowed in OSGi (and in standard Java it's a best practice to have separate packages, too).

2)使用预包装的插件

我找到了org.apache.servicemix.bundles.poi,它是由对OSGi的工作原理不了解的人(也许是Apache的人)创建的.它包含任何JAR中都不存在的依赖,特别是导入包org.junit令我担心.

I found org.apache.servicemix.bundles.poi, which was created by someone with no understanding of how OSGi works (maybe the Apache guys?). It contains wonky dependencies that are not present in any of the JARs, and especially the import package org.junit worries me.

由于无法将所有必需的进口货物都捆绑在一起,因此我无法使其正常工作.而且由于捆绑包显然很破损,所以我很快放弃了.

I could not get it to work, since not all the necessary imports are bundles, yet. And since the bundle was so obviously broken I gave it up quickly.

3)使用带有lib文件夹的插件

真的很难找到正确的导入和导出包.最终这失败了,因为POI JAR导出了标准软件包(如xmlbeans中的javax.xml).

It's really hard to find the correct import and export packages. Ultimately this fails because the POI JARs export standard packages (like javax.xml from xmlbeans).

4)将源复制到插件

这可能是我的最爱.当您将源代码复制到他们自己的插件中时,会出现编译错误. JAR poi-ooxml-3.17.jar 需要一个名为org.etsi.uri.x01903.v13.SignaturePolicyIdType的类.该类包含在 poi-ooxml-schemas-3.17.jar 中,但令人不安的是它的名称是SignaturePolicyIdentifierType.

This is probably my favorite. When you copy the sources into their own plug-ins you get compile errors. The JAR poi-ooxml-3.17.jar needs a class named org.etsi.uri.x01903.v13.SignaturePolicyIdType. The class is contained in poi-ooxml-schemas-3.17.jar, but the disturbing truth is its name is SignaturePolicyIdentifierType.

5)问Apache

存在一个问题"OSGI可以使用POI吗?" 在常见问题解答中:

There is a question "Can POI be used with OSGI?" in the FAQ:

从POI 3.16开始,有一个针对OSGI上下文类加载器处理的解决方法,即它以受限类视图的实现替换了当前上下文类加载器的线程.这将导致IllegalStateExceptions,因为xmlbeans在此缩小的视图中找不到xml模式定义.解决方法是初始化POIXMLTypeLoader的类加载器委托,该委托默认为当前线程上下文类加载器.初始化应在任何其他与OOXML相关的调用之前进行.示例中的类可以是任何类,它们是poi-ooxml-schema或ooxml-schema的一部分: POIXMLTypeLoader.setClassLoader(CTTable.class.getClassLoader());

我没有尝试过,因为这对我来说没有任何意义:他们如何将非标准的JAR打包成捆?以及在加载类后如何设置类加载器甚至会有所帮助?

I've not tried it, because it does not make any sense for me: How did they even get their non-standard-conform JARs into bundles? And how would setting the classloader AFTER the class was loaded even help?

问题:有什么方法可以使当前的POI与OSGi一起使用?

Question: Is there any way to get the current POI to work with OSGi?

注意::我刚刚找到了

Note: I just found this question, but it's for an even older version of POI. But obviously it's an ongoing problem.

推荐答案

我通过构建自己的3.17 OSGi捆绑软件使其工作,我将其放入了Virgo/repository/usr:

I got it working by building my own 3.17 OSGi bundle, which i've dropped in 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>

然后在我的调用代码中,创建一个线程并使用父类加载器.希望听到更好的方法-这并非微不足道.如果Apache有OSGi捆绑包,那就太好了.我可能有多余或缺少的步骤,但是正在使用以下代码生成Excel文件:

Then in my calling code, I create a thread and use the parent classloader. Would like to hear a better way - this is not trivial to setup. Would be nice if Apache had OSGi bundles. I may have extra or missing steps, but am generating Excel files with this code:

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
    }
}

这篇关于OSGi中的Apache POI 3.17的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆