2

I'm looking at an issue in a mature commercial product.

In a nutshell, we are using part of the Apache POI library to read in a Word .DOC or .DOCX file, and convert it into XSL-FO so that we can do token replacements. We then use FOP – embedded into the Java program - to convert the FO data into a PDF for printing. The catch is, all this is being done on the client inside a Java applet running inside Internet Explorer.

Originally we were using FOP 0.93, which worked reasonably well. However, it was not able to utilise the fonts inside the DOC file when generating the PDF and would map everything to Times, which one of the customers did not like. In theory it could be made to work by adding some kind of font metrics data, but that would require a relatively complex definition for every font it was likely to encounter and we can’t predict what the client is liable to use outside of the MS core fonts set.

To fix this, FOP was upgraded to 1.0, which added support for autodetecting the fonts from the operating system. This worked, but we noticed that the image processing had stopped working and the letterheads had disappeared. What appears to have happened is that the image loader inside FOP was rewritten at some point between 0.93 and 0.95 so that instead of using Jimi and JAI it now uses ImageIO. The earlier implementation worked fine, but the new code doesn’t like being run as an applet.

Images are embedded in URIs in the FO data so we get an error like this: 2014-09-30 17:00:10,607 ERROR [org.apache.fop.apps.FOUserAgent] Image not available. URI: data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAALQAAABSCAIAAABysmn6AAA... ...ggg==. Reason: org.apache.xmlgraphics.image.loader.ImageException: The file format is not supported. No ImagePreloader found for data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAALQAAABSCAIAAABysmn6AAAA...

When run through a test harness, the correct output is generated, but when run as an applet inside the browser we get the above error which makes me suspect that the browser applet security is jamming the ImageIO plugin loader somehow.

The guts of the FOP transformation, i.e. the bit which is triggering the error is this:

// Step 4: Setup JAXP using identity transformer
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(); // identity transformer

transformer.transform(src, res);

...which is all being run inside a PrivilegedAction block since in FOP 1.0 it needed file I/O access to manage the font cache.

Running the standalone FOP 0.93 and 1.0 programs under linux and using strace shows that it is writing out temporary files for the image data, but both 0.93 and 1.0 do similar things, so it shouldn’t be that by itself, especially since it should have permission to create temp files already.

I've tried different versions of the JRE since some builds a few years back apparently had security issues with the ImageIO library, but to no avail.

Any ideas?

Thanks,

Joseph Morris
  • 181
  • 1
  • 6

3 Answers3

16

In case anyone else has something similar, this turned out to be caused by the way the project was being built in Maven.

Fop 1.0 and above use the xml-graphics-commons library to facilitate the image rendering. As mentioned in the question, this uses a plugin registry which is configured using the following files inside the JAR:

META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageConverter
META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory
META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader

...each of these contains a list of the image decoders which will be supported.

The problem is that xml-graphics-common ships these files with a sensible list of defaults, while FOP also has a conflicting set of defaults, which for some weird reason disable all of the image decoders, and that one was taking priority.

To solve the problem, I made sure that my maven pom.xml file imported xml-graphics-common before FOP, so that its defaults took precedence, and at that point everything sprang to life.

I am still not sure why the code was working correctly as a standalone test program, but I suspect it was the way the classpath was being handled being different to it running in plugin mode.

Joseph Morris
  • 181
  • 1
  • 6
  • 2
    Thank you. We are using maven shade plugin and the solution for me was to add a transformer to the shade plugin configuration ` META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader ` – DominikM Nov 27 '15 at 09:19
  • Thank you! You saved my day. – Oni1 May 07 '19 at 06:05
1

Just been struggling with this one. If you're using the maven-shade-plugin to create an uber jar, use the ServicesResourceTransformer to merge all the services configuration:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>2.2</version>
  <executions>
    <execution>
      <!-- snip -->
      <configuration>
        <transformers>
          <!-- snip -->
          <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
        </transformers>
      </configuration>
    </execution>
  </executions>
</plugin>
Kynx
  • 11
  • 1
0

In my case the plugin registry loaded ImagePreloaders from both the plugin files and mixed them together. Yet the error still appeared. I was inserting an SVG file into a PDF file. The root cause was incorrect version of org.apache.xmlgraphics:batik-svg-dom. The 1.7 version was required by the org.apache.xmlgraphics:fop:1.1, however, the 1.8 version was on the classpath.

There is a key difference between the two versions: the org.apache.fop.image.loader.batik.PreloaderSVG class needs org.apache.batik.dom.svg.SAXSVGDocumentFactory from the version 1.7 on the classpath. If it gets org.apache.batik.anim.dom.SAXSVGDocumentFactory from the 1.8 version it does not work as expected.

This SO question: Where has org.apache.batik.dom.svg.SVGDOMImplementation gone? was helpful to me when resolving this issue.

Jiri Patera
  • 3,032
  • 1
  • 18
  • 14