1

This problem ties in with the many discussions about the Xerces dependency hell, but I can't seem to solve it.

I'm trying to export LaTeX code to PDF in Java. My code is part of an OSGI bundle for Cytoscape 3.4 and is managed and built with Maven. The LaTeX library is jlatexmath (1.0.6) and to write to SVG and PDF I want to try the apache fop (0.95) libs.

Fop is depending on a whole range of batik libraries, which in turn depend on xml-apis (1.3.04).

With xml-apis included, I get this error:

java.lang.ClassCastException: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl cannot be cast to javax.xml.parsers.DocumentBuilderFactory
        at javax.xml.parsers.DocumentBuilderFactory.newInstance(Unknown Source)
        at org.scilab.forge.jlatexmath.TeXFormulaSettingsParser.<init>(TeXFormulaSettingsParser.java:74)

Which is understandable as the implementation of DocumentBuilderFactory is supposed to be com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl as included in the JRE.

When I exclude the xml-apis and xml-apis-ext libs, I get another error:

<dependency>
    <groupId>org.apache.xmlgraphics</groupId>
    <artifactId>fop</artifactId>
    <version>0.95</version>
    <exclusions>
        <exclusion>
            <groupId>xml-apis</groupId>
            <artifactId>xml-apis</artifactId>
        </exclusion>
        <exclusion>
            <groupId>xml-apis</groupId>
            <artifactId>xml-apis-ext</artifactId>
        </exclusion>
    </exclusions>
</dependency>


java.lang.ClassNotFoundException: org.w3c.dom.Document not found by... [115]
        at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1532)
        at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:75)
        at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1955)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

Which is weird, as org.w3c.dom.Document should also just be in the JRE.

So, how can I force Java to use the classes included in Java instead of looking for the ones loaded from the Maven dependencies?

1

2 Answers 2

1

Your bundle needs to import the package org.w3c.dom. You must import all packages that your bundle depends on, with the solitary exception of packages starting with java., e.g. java.lang, java.net etc.

Sign up to request clarification or add additional context in comments.

4 Comments

My maven-bundle-plugin configuration instructions already state <Import-Package>*;resolution:=optional</Import-Package>. Or is that not what you meant?
Indeed explicitly importing this package solved this part of the problem: <Import-Package>org.w3c.dom,*;resolution:=optional</Import-Package>
Probably this is because the classes are loaded by reflection, e.g with Class.forName. When your code uses a package statically (i.e. compiled into the .class file), bnd can detect that dependency and automatically adds it when you have Import-Package: * (which is the default). However bnd cannot detect reflective class loading.
By the way you should NOT say Import-Package: *; resolution:=optional. This makes ALL of the imports of your bundle optional, which is a really bad thing. I will add this comment to your answer.
0

I managed to fix it, thanks to the suggestion of Neil Bartlett that org.w3c.dom wasn't imported (although I'm still not sure why an "import *" didn't suffice).

In the configuration instructions of the maven-bundle-plugin, I changed the import to:

<Import-Package>org.w3c.dom,*;resolution:=optional</Import-Package>

Also, xml-apis-ext should not be excluded, so the fop dependency became:

<dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>fop</artifactId>
            <version>0.95</version>
            <exclusions>
                <exclusion>
                    <groupId>xml-apis</groupId>
                    <artifactId>xml-apis</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

Then, to be complete, the fop artifact seemed to be needing a class from the avalon-framework-impl, which was nowhere in the maven dependencies, so I added it separately, while excluding all new attempts to include xml-apis:

<dependency>
            <groupId>avalon-framework</groupId>
            <artifactId>avalon-framework-impl</artifactId>
            <version>4.3</version>
            <exclusions>
            <exclusion>
                    <groupId>xml-apis</groupId>
                    <artifactId>xml-apis</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>xml-apis</groupId>
                    <artifactId>xmlParserAPIs</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

1 Comment

You should NOT say Import-Package: *; resolution:=optional. This makes ALL of the imports of your bundle optional, which is a really bad thing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.