I've been using Itext for a while now. It's a great framework for generating PDF's. It's quite simple to use and you can produce fancy PDF's with it.
Usually I've been using it in a web context, for producing reports of some kind.
The project home page is http://www.lowagie.com/iText/, it's very well documented, it has lot's of examples and it has a great mailling list.
The only draw back is if you want to do something too complex you will have to buy the book or do a lot of research in the mailing lists. In the book you will find the techniques for doing it right and also you will support the framework author (Bruno Lowagie).
Ok, first of all, check out the download on the web site. Add the JAR to you lib or classpath and read some examples at the kick start "learn by example" section.
My focus here is not to teach you how to build PDF's but some techniques and code samples for doing tasks that I struggle for a solution. And remember, the code showed here is just an example.
So let's go:
Create a header/footer with some images and page numbers like "X page of Y" and add it to all the pages of your document.
Well for doing this you have in the API the PdfPageEvent iterface or PdfPageEventHelper object that you can implement or extend. For me it's best to extend the PdfPageEventHelper and just override the desired methods. Check the javadocs! Instanciate your object with the disared arguments (logo header, resorce bundle, etc...) that you will need.
writer.setPageEvent(new MyPdfPageEvent(resources, headerLeft, headerRight, false));
Now comes the tricky part: How do I create the total page for every page if the pdf is not rendered yet? For that, Itext have a Template objec. You need to instanciate it in onOpenDocument method somehow like this:
public void onOpenDocument(PdfWriter writer, Document document) { total = writer.getDirectContent().createTemplate(100, 100);
total.setBoundingBox(new Rectangle(-20, -20, 100, 100)); }
Now we want to add the "page X of Y" string to every page:
public void onEndPage(PdfWriter writer, Document document) { String text = resources.getString("pei.export.pdf.footer.page.number") + " " + writer.getPageNumber() + " " + resources.getString("pei.export.pdf.footer.page.of") + " ";
float footerBase = document.bottom() - 30;
float textSize = 8;
float adjust = 2;
PdfContentByte cb = writer.getDirectContent();
cb.beginText();
cb.setFontAndSize(helv, 6);
cb.setTextMatrix(document.right() - textSize - adjust, footerBase);
cb.showText(text);
cb.endText();
cb.addTemplate(total, document.right() - adjust, footerBase);
//important to control pdf errors
cb.sanityCheck(); }
And now for finishing you need to add the total pages template after render the document like this:
public void onCloseDocument(PdfWriter writer, Document document) { total.beginText();
total.setFontAndSize(helv, 6);
total.setTextMatrix(0, 0);
total.showText(String.valueOf(writer.getPageNumber() - 1));
total.endText(); }
Easy but triky... You can try to add headers logo also onOpenDocument method showed above like this:
headerRight= Image.getInstance(logoPath);
cb.addImage(headerRight, 150, 0, 0, headerRight.getHeight() / headerRight.getWidth() * 150, document.right() - 150, headerBase);
The PageEventHelper class also have other methods for control other document events like onStartPage, onChapter, onChapterEnd etc... Do it your way!