Re: AW: Using Turbine's tools for assembling PDF output (using FOP): how to?
Steve Yokanovich <[email protected]>
| Newsgroups | gmane.comp.jakarta.turbine.user |
|---|---|
| Message-ID | <[email protected]> |
We have a solution that sounds similar. We are not a high volume site so
I am not sure how scalable this is since it creates a new Fop with
each request. We extended VelocityOnlyLayout to create a PdfLayout:
public class PdfLayout extends VelocityOnlyLayout {
FopFactory fopFactory = FopFactory.newInstance();
TransformerFactory tFactory = TransformerFactory.newInstance();
Log logger = LogFactory.getLog(PdfLayout.class);
public void doBuild(RunData data) throws Exception {
/* Screen string will store the XSL-FO */
String screenString = "";
/*
* First, generate the screen and put the results into a string
*/
ConcreteElement results = ScreenLoader.getInstance().eval(data,
data.getScreen());
if (results != null)
screenString = results.toString();
/**
* Get the response object and set content type for PDF
*/
HttpServletResponse response = data.getResponse();
ByteArrayOutputStream out = new ByteArrayOutputStream();
/**
* Get a reader and instantiate the PDF Driver
*/
StringReader reader = new StringReader(screenString);
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out);
try {
/**
* Render the document and write to the response
*/
Source source = new StreamSource(reader);
Result res = new SAXResult(fop.getDefaultHandler());
Transformer transformer = tFactory.newTransformer();
transformer.transform(source, res);
byte[] byteContent = out.toByteArray();
response.setContentType("application/pdf");
response.setContentLength(byteContent.length);
response.getOutputStream().write(byteContent);
response.getOutputStream().flush();
} catch (IllegalArgumentException e) {
logger.error(e.getMessage());
e.printStackTrace();
} catch (TransformerException e) {
// Attempt to send the XSL-FO back to the browser for
troubleshooting.
response.setContentType("text/xml");
PrintWriter writer = response.getWriter();
writer.print(screenString.toString());
writer.flush();
out.close();
logger.error("FOP Exception in PDFLayout "+
e.getMessage());
} finally {
out.close();
}
}
}
Here is our PdfScreen:
/**
* This screen incorporates the security function (isAuthorized)
* from VelocitySecureScreen, the only difference being the
getLayout method, which returns PdfLayout if the user is authenticated.
* See PdfLayout for the actual rendering of the PDF document
*/
public class PdfScreen extends VelocitySecureScreen {
public String getLayout(RunData data) {
boolean ok = false;
String rv = null;
try {
ok = this.isAuthorized(data);
} catch (Exception e) {
}
if (ok) {
rv = "PdfLayout";
} else {
rv = "LoginLayout";
data.setLayoutTemplate("/Login.vm");
}
return rv;
}
}
Now whenever we need a PDF we extend PdfScreen and create the xsl-fo
template.
Let me know if this is what you were looking for.
Steve Yokanovich
Alexander Zimmer wrote:
> Thank you both for your answers.
> Anyway, I just would like to stress that the conversion FO->PDF and the streaming (via a RawScreen-like Screen) is not a problem and is already solved.
> What I do not know (yet) is, how I can use Velocity plus all the nice Turbine pull tools for the Velocity template to assemble the FO input, such a template would look just like this (as you can see, a valid FO file, except the VTL sequences, which should be taken care of by Velocity):
> <?xml version="1.0" encoding="UTF-8"?>
> <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
> <fo:layout-master-set>
> <fo:simple-page-master master-name="simpleA4" page-height="29.7cm" page-width="21cm" margin-top="2cm" margin-bottom="2cm" margin-left="2cm" margin-right="2cm">
> <fo:region-body/>
> </fo:simple-page-master>
> </fo:layout-master-set>
> <fo:page-sequence master-reference="simpleA4">
> <fo:flow flow-name="xsl-region-body">
> <fo:block>Hello World, my name is $!{name}!</fo:block>
> #foreach ($entry in $names)
> <fo:block>Next name: $entry.Firstname $entry.Lastname</fo:block>
> #end
> </fo:flow>
> </fo:page-sequence>
> </fo:root>
> How can I use template functionality? The problem involved are:
> 1. I want to use the Velocity engine and capture its output in a String/ByteArray. The output will be a valid FO file.
> 2. I want to be able to use all (at least: some) pull tools Turbine provides for screen templates
> I think that I've solved the other problems (how to do the streaming, how to convert into PDF, ...).
> I try to dive into the VelocityOnlyLayout (as Peter Courcoux pointed out), but if you have additional clues for me, I would be very happy to hear from you!
>
> Cheers,
> Alex
>
>
> -----Ursprüngliche Nachricht-----
> Von: Jeffery Painter [mailto:[email protected]]
> Gesendet: Freitag, 18. Jänner 2008 15:21
> An: Alexander Zimmer
> Betreff: Re: Using Turbine's tools for assembling PDF output (using FOP): how to?
>
>
> I haven't looked at this stuff in quite some time, but I had posted
> a PdfScreen that might give you a start on how to do things.
>
> http://kiasoft.com/opensource/PdfScreen.java
>
> I was using it with the iText library back in the day, but I believe your
> options are more varied now.
>
> http://www.lowagie.com/iText/
>
> good luck!
>