This is my first question here, i hope i'm doing it right. Sorry for my bad English in advance :)
I am using JSF 2.0 (Eclipse IDE) and i'm trying to generate some PDF files using Apache FOP 1.0.
I was able to make simple PDF files using instructions on Apache Fop site , but i can't insert any image from my application folder. My folder structure is like this: In my application WebContent i have (among else) pdf_transform/xslt/transformFile.xsl, and pdf_transform/xslt/logo.jpg
In transformFile.xsl i have
<fo:block><fo:external-graphic src="url('logo.jpg')"/></fo:block>
but when i clik 'showPDF' button in my servlet, i get PDF file without image (everything else is there), and this messages in console:
SEVERE: The Source that was returned from URI resolution didn't contain an InputStream for URI: logo.jpg Nov 18, 2010 5:16:49 PM org.apache.fop.events.LoggingEventListener processEvent SEVERE: Image not found. URI: logo.jpg. (No context info available)
I tried to use 'logo.jpg' instead of url('logo.jpg'), putting image on various places inside WebContent folder and using different navigation("./logo.jpg") but it didnt work.
It works fine if i set absolute path (for example "d:/fop/images/logo.jpg") but i need resurces whitin my application.
While searching, i found that this is related to fopFactory.setURIResolver() and/or userAgent.setBaseURL(). Tried something with that, but didnt succeed.
I am new to both JSF and FOP, and this image situation has been bothering me quite a while. Can someone help me with this, or at least direct me to some tutorial on "how to configure FOP for relative path use"?
EDIT: I don't want any absolute paths and app should work independently of its location on computer (to be publishable). My search tells me it has something to do with configuring FOP, but i don't know how to do it :)
Thanks in advance.
P.S. This is method which is called to display PDF:
public void printExchangeRateList(ActionEvent event) {
BufferedOutputStream output = null;
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
String path = externalContext.getRealPath("/");
try {
response.reset();
response.setHeader("Content-Type", "application/pdf");
output = new BufferedOutputStream(response.getOutputStream(), 10240);
File xsltfile = new File(path+"/pdf_transform/xslt/transformFile.xsl");
FopFactory fopFactory = FopFactory.newInstance();
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
try {
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, output);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer(new StreamSource(xsltfile));
Source src = new DOMSource(makeXML()); // my method
Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(src, res);
} finally {
if (output != null) output.close();
/*try {
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
}
} catch (Exception e) {
// TODO Auto-generated catch block
}
facesContext.responseComplete();
}
i found solution to my problem. I thought i tried that, but it seems i made some little mistake back then. Anyway, with the following code
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
String basePath = externalContext.getRealPath("/");
FopFactory fopFactory = FopFactory.newInstance();
fopFactory.setBaseURL(basePath);
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
foUserAgent.setBaseURL(fopFactory.getBaseURL());
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, output); // for some output
you can access your images (and other resources) from your xslt file using relative path starting from your application's WebContent folder. In my case, i can access logo.jpg like this
<fo:external-graphic src="url('pdf_transform/xslt/logo.jpg')"/>
Took me time to figure out this, i don't get it why no examples with such basic thing on the net (or i can't find them :)
Note: In FOP 2.0 there is no setBaseURL()
method. Instead you pass the base URL as a parameter to FopFactory.newInstance()
. Many of the other setters have been moved to FopFactoryBuilder.
If you have access to the web url for the pictures you can use that as well when generating reports, ie http://localhost/images/logo.jpg .
But while I still had images locally on the web server, I included the path to the application in the XML file and used it like this:
<xsl:variable name="base_path" select="base-path"/>
<xsl:variable name="logo" select="companies/company/logo"/>
<fo:external-graphic src="url({$base_path}{logo})"/>
Where the XML structure might be something like this:
<?xml version="1.0" encoding="UTF-8"?>
<base-path>/path/to/app/</base-path>
<companies>
<company>
<logo>images/company1.jpg</logo>
</company>
<company>
<logo>images/company2.jpg</logo>
</company>
</companies>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With