Search code examples
javawebsphereclassloaderpdfbox

loading constraint violation when resolving method "javax/imageio/metadata/IIOMetadata.getAsTree(Ljava/lang/String;)Lorg/w3c/dom/Node


I am using Apahce Pdfbox 2.0.30 on Websphere ND 9.0.5.13 which is running on Java 8 The application class loader is set to Parent Last

My POM file is as follows:

<dependencies>
    
   <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
            <exclusion>
                <artifactId>logback-classic</artifactId>
                <groupId>ch.qos.logback</groupId>
            </exclusion>
            <exclusion>
                <artifactId>log4j-to-slf4j</artifactId>
                <groupId>org.slf4j</groupId>
            </exclusion>
        </exclusions>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    

    
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    
    <dependency>
        <groupId>xerces</groupId>
        <artifactId>xercesImpl</artifactId>
        <version>2.11.0</version>
    </dependency>
    
    
    
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-data-jdbc</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-ui</artifactId>
        <version>${springdoc.version}</version>
    </dependency>
    

    <dependency>
        <groupId>com.microsoft.sqlserver</groupId>
        <artifactId>mssql-jdbc</artifactId>
        <scope>runtime</scope>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>

    
    <dependency>
        <groupId>com.oracle.jdbc</groupId>
        <artifactId>ojdbc14</artifactId>
        <version>1.4</version>
    </dependency>


    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
    </dependency>
    
    <dependency>
        <groupId>net.sf.flexjson</groupId>
        <artifactId>flexjson</artifactId>
        <version>3.3</version>
    </dependency>
    
    <dependency>
        <groupId>javax.jws</groupId>
        <artifactId>javax.jws-api</artifactId>
        <version>1.1</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    
    <dependency>
        <groupId>javax.activation</groupId>
        <artifactId>javax.activation-api</artifactId>
    </dependency>


    
    <dependency>
        <groupId>com.sun.mail</groupId>
        <artifactId>javax.mail</artifactId>
        <version>1.6.2</version>
    </dependency>
    
    
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15</artifactId>
        <version>1.46</version>
    </dependency>



    
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.11.0</version>
    </dependency>
    
    <dependency>
        <groupId>com.github.mlaccetti</groupId>
        <artifactId>javapns</artifactId>
        <version>2.3.2</version>
    </dependency>
    
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itextpdf</artifactId>
        <version>5.5.6</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.xmlgraphics</groupId>
        <artifactId>xmlgraphics-commons</artifactId>
        <version>1.5</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.xmlbeans</groupId>
        <artifactId>xmlbeans</artifactId>
        <version>3.0.1</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>4.0.0</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml-schemas</artifactId>
        <version>4.0.0</version>
    </dependency>
            
    <dependency>
        <groupId>net.sf.jasperreports</groupId>
        <artifactId>jasperreports</artifactId>
        <version>6.11.0</version>
    </dependency>
    
    <!-- 
    <dependency>
        <groupId>net.sf.jasperreports</groupId>
        <artifactId>jasperreports-fonts</artifactId>
        <version>6.11.0</version>
    </dependency>
    -->
    
    
    <dependency>
        <groupId>jasperreports-fonts</groupId>
        <artifactId>jasperreports-fonts</artifactId>
        <version>0.6.11.0</version>
    </dependency>
    

    <dependency>
        <groupId>com.lowagie</groupId>
        <artifactId>itext</artifactId>
        <version>2.1.7</version>
    </dependency>
    
    <dependency>
        <groupId>net.sf.barcode4j</groupId>
        <artifactId>barcode4j</artifactId>
        <version>2.1</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.xmlgraphics</groupId>
        <artifactId>batik-all</artifactId>
        <version>1.11</version>
        <type>pom</type>
    </dependency>
    
    <dependency>
        <groupId>com.google.zxing</groupId>
        <artifactId>core</artifactId>
        <version>2.2</version>
    </dependency>
    
    <dependency>
        <groupId>com.google.zxing</groupId>
        <artifactId>javase</artifactId>
        <version>2.2</version>
    </dependency>

    <dependency>
        <groupId>javax.xml</groupId>
        <artifactId>jaxrpc-api</artifactId>
        <version>1.1</version>
    </dependency>
    
    <dependency>
        <groupId>axis</groupId>
        <artifactId>axis</artifactId>
        <version>1.3</version>
    </dependency>
    
    <dependency>
        <groupId>com.ibm.websphere.appserver.api</groupId>
        <artifactId>com.ibm.websphere.appserver.api.json</artifactId>
        <version>1.0.22</version>
    </dependency>
    
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-core-asl</artifactId>
        <version>1.9.13</version>
    </dependency>

    
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>1.9.13</version>
    </dependency>

    
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>4.0.0</version>
    </dependency>

    
    <dependency>
        <groupId>com.itextpdf.tool</groupId>
        <artifactId>xmlworker</artifactId>
        <version>5.5.7</version>
    </dependency>

    
    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.6</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.pdfbox</groupId>
        <artifactId>pdfbox</artifactId>
        <!-- <version>2.0.25</version> -->
        <version>2.0.30</version>
    </dependency>
    
    <dependency>
        <groupId>com.google.gcm</groupId>
        <artifactId>gcm-server</artifactId>
        <version>1.0.0</version>
    </dependency>
    
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.30</version>
        <scope>provided</scope>
    </dependency>
    
    <dependency>
        <groupId>com.ibm.filenet</groupId>
        <artifactId>filenet-jace</artifactId>
        <version>1.0</version>
    </dependency>

    <dependency>
        <groupId>com.ibm.filenet</groupId>
        <artifactId>filenet-pe</artifactId>
        <version>1.0</version>
    </dependency>

    <dependency>
        <groupId>com.ibm.filenet</groupId>
        <artifactId>filenet-pe-resources</artifactId>
        <version>1.0</version>
    </dependency>
    
    <dependency>
        <groupId>com.ibm.filenet</groupId>
        <artifactId>filenet-java-api</artifactId>
        <version>1.0</version>
    </dependency>

    <dependency>
        <groupId>com.ibm.applicationservices</groupId>
        <artifactId>application.services</artifactId>
        <version>1.0</version>
    </dependency>

    
    
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>log4j-over-slf4j</artifactId>
    </dependency>
    
</dependencies>

and when trying to get a buffered image as follows:

public BufferedImage generateJasperReportPDF(JasperPrint jasperPrint, String fontName, String fontPath)
            throws IOException {
        JRPdfExporter exporter = new JRPdfExporter();
        BufferedImage bimage = null;
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        PDDocument document = null;
        try {


            exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
            exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputStream);
            exporter.exportReport();

            document = PDDocument.load(outputStream.toByteArray());
            PDFRenderer renderer = new PDFRenderer(document);
            bimage = renderer.renderImageWithDPI(0, 300, ImageType.RGB);

        } catch (Exception e) {
            log.error("Exception in generateJasperReportPDF: ", e);
        } finally {
            if (outputStream != null)
                outputStream.close();
            if (document != null)
                document.close();
        }
        return bimage;
    }

I am getting the following exception when the following line gets executed:

bimage = renderer.renderImageWithDPI(0, 300, ImageType.RGB);

Exception is:

Caused by: java.lang.LinkageError: loading constraint violation when resolving method "javax/imageio/metadata/IIOMetadata.getAsTree(Ljava/lang/String;)Lorg/w3c/dom/Node;" : loader "com/ibm/ws/classloader/CompoundClassLoader@a24fe2b5" of class "org/apache/pdfbox/filter/DCTFilter" and loader "com/ibm/oti/vm/BootstrapClassLoader@9e7c1335" of class "javax/imageio/metadata/IIOMetadata" have different types for the method signature
    at org.apache.pdfbox.filter.DCTFilter.getNumChannels(DCTFilter.java:387) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.filter.DCTFilter.decode(DCTFilter.java:95) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.cos.COSInputStream.create(COSInputStream.java:87) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.cos.COSStream.createInputStream(COSStream.java:175) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.pdmodel.common.PDStream.createInputStream(PDStream.java:243) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject.createInputStream(PDImageXObject.java:901) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.pdmodel.graphics.image.SampledImageReader.from8bit(SampledImageReader.java:507) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.pdmodel.graphics.image.SampledImageReader.getRGBImage(SampledImageReader.java:226) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject.getImage(PDImageXObject.java:514) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject.getImage(PDImageXObject.java:477) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.rendering.PageDrawer.drawImage(PageDrawer.java:1116) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.contentstream.operator.graphics.DrawObject.process(DrawObject.java:67) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.contentstream.PDFStreamEngine.processOperator(PDFStreamEngine.java:958) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.contentstream.PDFStreamEngine.processStreamOperators(PDFStreamEngine.java:531) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.contentstream.PDFStreamEngine.processStream(PDFStreamEngine.java:506) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.contentstream.PDFStreamEngine.processPage(PDFStreamEngine.java:150) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.rendering.PageDrawer.drawPage(PageDrawer.java:288) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.rendering.PDFRenderer.renderImage(PDFRenderer.java:355) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.rendering.PDFRenderer.renderImage(PDFRenderer.java:272) ~[pdfbox-2.0.30.jar:2.0.30]
    at org.apache.pdfbox.rendering.PDFRenderer.renderImageWithDPI(PDFRenderer.java:258) ~[pdfbox-2.0.30.jar:2.0.30]

UPDATE: When inspecting Websphere Class loader viewer I found that the class IIOMetadata exists only once

 <class>
      <name>javax.imageio.metadata.IIOMetadata</name>
      <interface>false</interface>
   </class>
  • The classloader order is as follows:

enter image description here


Solution

  • The problem is almost certainly duplicate visibility to the DOM class mentioned in the method signature, org/w3c/dom/Node. Given the description of the problem and the details in the exception text, I believe the following pattern is occurring:

    1. The DCTFilter class is loaded from the parent-last application class loader. It references IIOMetadata and presumably calls the getAsTree() method on that class, which means it must also reference Node.
    2. When dependencies are loaded, DCTFilter's class loader is used to load them. The ImageIO libraries are not packaged in the application (given your confirmation that they're loaded only once), and are found by the system class loader. The DOM classes are presumably packaged in the application, so Node is found in the application.
    3. When the IIOMetadata class is linked and its dependencies loaded, the XML classes are found locally in the JDK, so a second instance of Node is found there.
    4. DCTFilter now has visibility to two separate versions of org/w3c/dom/Node - directly, to the copy in the application, and indirectly, through IIOMetadata to the copy in the JDK. This is illegal, and the LinkageError is thrown.

    The simplest solution is to remove the XML libraries from the application - JAXP has long been included in the JDK, and there's essentially never a reason that an application needs to bring its own version of this API. Removing the jar(s) containing the DOM classes should resolve that specific error.

    A larger question may be why you're utilizing parent-last class loader delegation in the first place. While it is supported for some application packaging setups, it is basically the only way to end up with an error like this one, and usually an application is better off using the server's copy of the Java EE (and, in this case, SE) APIs than it is trying to bring its own. Unless you have a specific technical reason why you're using that configuration, the best solution might be to switch the class loader delegation back to the default.