How to use Apache POI in OSGi
I want to use an Apache POI in OSGi to write an Excel workbook with OOXML Streaming API (SXSSF). The streaming API is available since POI 3.9.
Since the latest Apache POI 3.11 applications are not packages: What's the best way to get POI working in OSGi?
I tried two approaches:
- embed cans directly into a single package that will use them
- use POI jars prepackaged as packages
I am desperate to collect all the dependencies.
First about embedding a POI banner in my package: my bndtools file contains
-buildpath: \ ... libs/dom4j-1.6.1.jar;version=file,\ libs/poi-3.11.jar;version=file,\ libs/poi-ooxml-3.11.jar;version=file,\ libs/poi-ooxml-schemas-3.11.jar;version=file Private-Package: \ ... org.openxmlformats.schemas.*,\ org.apache.poi.*,\ org.dom4j.*,\ com.microsoft.schemas.office.x2006.*,\ schemaorg_apache_xmlbeans.*,\ schemasMicrosoftComOfficeExcel.*,\ schemasMicrosoftComOfficeOffice.*,\ schemasMicrosoftComVml.*
The result is a package that imports many, many things, such as
. I don't plan on encrypting or testing in my application - so those two are probably "optional" somehow. How can I indicate this? Is there a good way to collect all these dependencies?
Note: at least
and are required,
but they are already packages.
Using prepackaged jars I tried using
3.9_2. This is also required
, so I used prewrapped
, but it requires at least version 1.0 of
which my JVM / Felix OSGi advertises as a "only" version
. I fixed it manually (ugly) but then got stuck on a different dependency.
What's a good way?
source to share
We use Gradle with bnd-platform to create OSGi packages for our apps based on Maven dependencies. Not sure if this is a "good way", but this is how we create the target framework for our OSGi applications, of which Apache POI is a part. This is especially useful in cases where you need to adapt to packages (for example, make JUnit optional) or combine JARs (for example, due to class loading issues in OSGi) to get them to work.
I have installed a sample build with Apache POI package (and implicitly, its POM dependent dependencies) on GitHub. You can clone it ( sample-poi branch) and try running . The created packages will be in .
./gradlew clean bundles
Please note that any additional Maven dependencies will not be included by default and must be manually added to the build if you need to (due to limitations in Gradle ).
source to share
I don't have a working example of this working, but this piece of documentation might be helpful to you.
Starting with POI 3.16, there is a workaround for OSGI context. handling the classloader, i.e. it replaces the current threading context classloader with a constrained class view implementation. This will result in IllegalStateExceptions as xmlbeans cannot find the definition xml schema in this shorthand. The workaround is to initialize the classloader delegate to POIXMLTypeLoader, which is the default classloader of the current context. The initialization must take place before any other OOXML-related calls. The class in the example can be any class that is part of the poi-ooxml schema or OOXML schema: POIXMLTypeLoader.setClassLoader (CTTable.class.getClassLoader ());
source to share