2

I'm trying to generate PDF with Apache FOP 2.2 and got some problem I'm using full URI like
file:///Users/mac/Desktop/image.png.
and here is part of myTemplate.

<fo:block>
      <fo:external-graphic content-height="scale-to-fit"  content-width="46.0mm"scaling="non-uniform"  src="(here I put the upper URI)"/>
</fo:block>`.    
I also got fop_config.xml in resources folder than looks like   
`<fop version="1.0">
    <renderers>
        <renderer mime="application/pdf">
            <auto-detect/>
<fonts>
<---! here are my fonts --->
</fonts>
        </renderer>
    </renderers>
</fop>

and my script

 val fopFactory = FopConfParser(File("fop_config.xml"))
            .fopFactoryBuilder
            .build()
        val foUserAgent = fopFactory.newFOUserAgent()
        val outStream = BufferedOutputStream(FileOutputStream(File("my_pdf.pdf")))
        outStream.use { out ->
            val fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out)
            val transformer = TransformerFactory.newInstance().newTransformer()
            val src = StreamSource(StringReader(myTemplate))
            val res = SAXResult(fop.defaultHandler)
            transformer.setParameter("versionParam", "2.0")
            transformer.transform(src, res)
        }

Im using Kotlin, but it does not matters. I'm rendering fine via IDEA, but when I create fat Jar with shadowJar Gradle plugin I've got
SEVERE: Image not found. URI: file:///Users/mac/Desktop/image.png. (No context info available)

Why I can't use URI inside of fatJar and how I can fix it?

UPD

I discovered that my problem connected with ImagePreloader. exception

org.apache.xmlgraphics.image.loader.ImageException: The file format is not supported. No ImagePreloader found for file:///Users/mac/Desktop/image.png

But it is only inside of Jar! How it can be?

Ivan
  • 63
  • 1
  • 1
  • 10
  • 1
    An entry in a .jar file is not a File. It’s just a portion of the zip-compressed bytes that make up the .jar file. You need to use [Class.getResourceAsStream](https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/lang/Class.html#getResourceAsStream%28java.lang.String%29) instead of File to read bundled data. – VGR Mar 01 '20 at 22:19
  • @VGR I don't want to read the data, I just want to put URI in template and make Apache FOP do all the job – Ivan Mar 02 '20 at 11:03
  • 1
    Then use [Class.getResource](https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/lang/Class.html#getResource%28java.lang.String%29) (not getResourceAsStream) to get a valid URL. An entry in a .jar file cannot be a `file:` URL. – VGR Mar 02 '20 at 14:26
  • @VGR Got it, but my file is outside my jar and there are located in same folder – Ivan Mar 02 '20 at 18:08
  • @VGR I've updated question, check it, please – Ivan Mar 04 '20 at 11:22
  • 1
    If you’re going to write code that works with files, you should learn what a *current directory* is, and what a *relative filename* is. Each process has its own current directory, and in most cases you cannot safely make any assumptions about what that will be. That is why it’s better to include fop_config.xml in your .jar, so you can access it with Class.getResource without being affected by the current directory. – VGR Mar 04 '20 at 12:47
  • @VGR Thank you for your help. I've tried different stuff and at last I realized that the problem was in fop dependencies. I'll write the answer asap – Ivan Mar 04 '20 at 13:10

1 Answers1

2

At last I found out that the problem was in dependencies.
For some reason xmlgraphics-commons cannot resolve ImagePreloader if it is downloaded as transitive dependency of fop.
The solution was just change Gradle script from :

compile('org.apache.xmlgraphics:fop:2.1')

to:

compile('org.apache.xmlgraphics:xmlgraphics-commons:2.1')
    compile('org.apache.xmlgraphics:fop:2.1') {
        exclude group:'org.apache.xmlgraphics', module: 'xmlgraphics-commons'
    }
Ivan
  • 63
  • 1
  • 1
  • 10