Apache POI 包装包的 Pax 考试问题

Pax Exam issue with Apache POI wrapped bundle

我一直在努力让 Apache POI 在 OSGi 包中工作。这是我尝试失败的历史:

1) 我最初尝试使用预包装的 Apache Servicemix POI 包。然而,这有许多我必须部署的依赖项,其中许多是不需要的。即使在添加 Apache POI servicemix(及其依赖项)之后,我还是碰壁了,我仍然遇到缺少 classes 的问题。

2) 由于第一个解决方案中有大量不需要的东西,我决定将依赖项打包在一个包中。基本上我有一个蓝图服务,它充当 POI 功能的包装器。所有单元测试工作正常,但我的 pax 考试测试失败。

起初,它找不到 class 依赖项(commons-codec、xmlbeans 等)。所以我添加了 POI 和 POI OOMXL 依赖项以及它需要的所有其他依赖项。这解决了大部分 class 加载器问题。然而,这是我目前坚持的那个。捆绑包开始时很好,但是一旦它到达尝试创建 excel 工作簿的位置,它就会失败并显示以下堆栈跟踪:

java.lang.ClassNotFoundException: com.bea.xml.stream.EventFactory not found by org.ops4j.pax.exam.rbc [104]

at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1574)
at org.apache.felix.framework.BundleWiringImpl.access0(BundleWiringImpl.java:79)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:2018)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at javax.xml.stream.FactoryFinder.newInstance(FactoryFinder.java:68)
at javax.xml.stream.FactoryFinder.find(FactoryFinder.java:178)
at javax.xml.stream.FactoryFinder.find(FactoryFinder.java:92)
at javax.xml.stream.XMLEventFactory.newInstance(XMLEventFactory.java:30)

以下是我包含的依赖项:

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>${apache.poi.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>${apache.poi.version}</version>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.9</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlbeans</groupId>
            <artifactId>xmlbeans</artifactId>
            <version>2.6.0</version>
        </dependency>

pax 容器似乎找不到 EventFactory。如果有人有任何建议,我将不胜感激。

这里是 pom.xml 用于创建 XLSX 导出的工作 POI osgi 包。由于可选的导入,可能一些奇特的功能不是 100% 支持,但它适用于标准导出。

apache commons bundle 是 osgi 兼容的,所以如果你使用这些依赖项,它必须工作(一些 commons 被其他功能使用,所以不是全部都是必需的)。这些功能在我们的 karaf 功能文件中,但您可以在任何 OSGi 容器中使用来自给定 Maven 源的包。

<feature name="stax" version="2.4.0">
    <bundle>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.stax-api-1.0/2.4.0</bundle>
    <bundle>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jaxb-api-2.2/2.4.0</bundle>
</feature>  

<feature name="repo-apache-commons" version="1.0.0">
    <bundle>mvn:commons-beanutils/commons-beanutils/1.9.2</bundle>
    <bundle>mvn:commons-collections/commons-collections/3.2.1</bundle>
    <bundle>mvn:commons-io/commons-io/2.4</bundle>
    <bundle>mvn:org.apache.commons/commons-pool2/2.4.2</bundle>
    <bundle>mvn:org.apache.commons/commons-dbcp2/2.1.1</bundle>
    <bundle>mvn:commons-codec/commons-codec/1.9</bundle>
</feature>

<feature name="repo-bouncycastle" version="1.46">
    <bundle>mvn:org.bouncycastle/bcprov-jdk16/1.46</bundle>
    <bundle>mvn:org.bouncycastle/bcmail-jdk16/1.46</bundle>
    <bundle>mvn:org.bouncycastle/bctsp-jdk16/1.46</bundle>
</feature> 

POM.XML:

<?xml version="1.0" encoding="ISO-8859-1"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<version>3.13.1</version>

<properties>
    <poi.version>3.13</poi.version>
    <poi.schema.version>1.1</poi.schema.version>
    <poi.security.version>1.0</poi.security.version>
</properties>

<groupId>org.yourgroupid</groupId>
<artifactId>osgi-apache-poi</artifactId>
<packaging>bundle</packaging>
<name>osgi-apache-poi</name>
<description>Apache poi framework</description>

<build>
<plugins>

    <plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    <extensions>true</extensions>
    <configuration>
        <instructions>
                    <_exportcontents>
                        org.apache.poi.*;version=${poi.version},
                        org.openxmlformats.schemas.*;version=${poi.schema.version},
                        schemasMicrosoftComOfficeExcel.*;version=${poi.schema.version},
                        schemasMicrosoftComOfficeOffice.*;version=${poi.schema.version},
                        schemasMicrosoftComOfficePowerpoint.*;version=${poi.schema.version},
                        schemasMicrosoftComVml.*;version=${poi.schema.version},
                        org.etsi.uri.*;version=${poi.security.version}
                    </_exportcontents>
                    <Import-Package>
                        com.sun.javadoc;resolution:=optional,
                        com.sun.tools.javadoc;resolution:=optional,
                        org.apache.crimson.jaxp;resolution:=optional,
                        org.apache.tools.ant;resolution:=optional,
                        org.apache.tools.ant.taskdefs;resolution:=optional,
                        org.apache.tools.ant.types;resolution:=optional,
                        junit.framework.*;resolution:=optional,
                        junit.textui.*;resolution:=optional,
                        org.junit.*;resolution:=optional,
                        org.apache.xml.security.*;resolution:=optional,
                        org.apache.jcp.xml.dsig.internal.dom.*;resolution:=optional,
                        *
                    </Import-Package>
                    <DynamicImport-Package>
                        org.apache.xmlbeans.*,
                        schemaorg_apache_xmlbeans.*
                    </DynamicImport-Package>

        <!-- bundle supplied resource prefixes -->
        <Include-Resource>{maven-resources}</Include-Resource>

        <!-- Do not inline jars, include as jar files -->
        <!-- There are config files with same name will be overwritten -->
        <Embed-Dependency>*;scope=compile;inline=false</Embed-Dependency>


        </instructions>
    </configuration>
    </plugin>
</plugins>
</build>
<dependencies>
    <!-- Embedded dependencies -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>${poi.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml-schemas</artifactId>
        <version>${poi.version}</version>
    </dependency>

    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>${poi.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-scratchpad</artifactId>
        <version>${poi.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>ooxml-schemas</artifactId>
        <version>${poi.schema.version}</version>
    </dependency>
    <dependency>
       <groupId>org.apache.poi</groupId>
       <artifactId>ooxml-security</artifactId>
       <version>${poi.security.version}</version>
    </dependency>
</dependencies>

除了上面的回答我也想通了我的问题。我没有 运行 要调试的单元测试,而是启动了 pax 创建的 karaf 实例。日志中有更多花絮让我发现缺少包导入。一旦我添加了丢失的导入,原来的错误就消失了。

尝试添加这个,它对我有用

<dependency>
   <groupId>stax</groupId>
   <artifactId>stax-api</artifactId>
   <version>1.0.1</version>
</dependency>

<dependency>
   <groupId>stax</groupId>
   <artifactId>stax</artifactId>
   <version>1.2.0</version>
</dependency>

maven bundle plugin无法自动找到依赖stax:stax:1.2.0,另外你可能需要手动导出包com.bea.*

下面是一个使用 bnd https://github.com/stempler/bnd-platform-minimal

的 osgi-fied apache poi 的例子

将build.gradle修改为以下代码:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.standardout:bnd-platform:1.2.0'
        // uncomment line below if using Gradle 1.x
        // classpath 'org.codehaus.groovy:groovy-backports-compat23:2.3+'
    }
}

apply plugin: 'org.standardout.bnd-platform'

/* XXX Problem with new plugin notation: dependency of bnd-platform is not resolved correctly / cannot be loaded as plugin
plugins {
  id "org.standardout.bnd-platform" version "1.2.0"
}
*/

repositories {
    mavenCentral()
}

defaultTasks 'clean', 'updateSiteZip'

platform {
    fetchSources = true
    determineImportVersions = true

    override {
        optionalImport(
            // no version requirement for certain JRE provided packages
            // use wildcards to not enforce imports
            'javax.xml.*',
            // also make JUnit optional everywhere - so we can exclude it from products
            'junit.framework.*',
            'org.junit.*'
        )
    }

    def poiVersion = '3.15'
    feature id: 'org.apache.poi.osgi',
            name: 'Apache POI OSGI All In One',
            version: poiVersion, {
        // merged POI bundle
        merge(failOnDuplicate: false) {
            bundle "org.apache.poi:poi:$poiVersion"
            bundle "org.apache.poi:poi-ooxml:$poiVersion"
            bundle "org.apache.poi:poi-ooxml-schemas:$poiVersion"
            bundle "org.apache.xmlbeans:xmlbeans:2.6.0"
            bundle "com.github.virtuald:curvesapi:1.04"
            bundle "commons-codec:commons-codec:1.10"
            bundle "org.apache.commons:commons-collections4:4.1"
            bundle "stax:stax-api:1.0.1"
            bundle "stax:stax:1.2.0"

            bnd {
                symbolicName = 'org.apache.poi'
                bundleName = 'Apache POI'
                version = poiVersion
                // only provide poi packages as exported packages
                instruction 'Export-Package', "org.apache.poi.*;version=$version, com.bea.*"
                instruction 'Private-Package', '*'
                // don't import any poi packages
                prependImport '!org.apache.poi.*', '!org.apache.xmlbeans.*', '!com.graphbuilder.*', '!org.apache.commons.codec.*'
            }
        }
    }
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.2'
}

运行 ./gradlew clean bundles updateSite 为 osgi-fied apache.poi

生成你的包和 repo