PDF generation AGAIN

That perpetual nut of PDF generation rose again recently with a new client, this time with a twist, they did not want to worry about any licences and had taken particular umbrage at the new iText licence,

This lead to a search for a good library that i could distribute to client apps, simply, without nasty yearly surprises, also I wanted the generation its self to be quick and make sense for any future developer who has to maintain.

Had i been wanting to convert existing good looking documents to PDF and the client being amenable to a licence, I would have chosen http://pd4ml.com/ which even has a plug in agent for notes (a rarity), but the royalty free requirement lead me to http://pdfjet.com/

This turns out to be very simple to use and nice and powerful, but best of all when you buy a licence (~$290) its a developer licence rather than a client licence meaning I can reuse it multiple times vastly increasing its worth to me (it should be noted that there is a free version , and once you are sure you want to use the paid version, its just a case of swapping out a jar file.

There are lots of nice examples for the using this lib at http://pdfjet.com/java/by-example.html but here is a Domino one as it has its own quirks, this is just simple agent with the PDFjet.jar imported as an archive, an image (logo.jpg) imported as a resource and the security settings to be able to write to the file system.

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Vector;
import com.pdfjet.*;
import lotus.domino.*;
public class JavaAgent extends AgentBase {
    public String createdFileName;
    public String createdFileNameAndLocation;
    public Session session;
    public void NotesMain() {
        try {
            session = getSession();
            AgentContext agentContext = session.getAgentContext();
            Document sourcedoc = agentContext.getDocumentContext();         
            //generate the file name for the pdf [
            createdFileName = "demo.pdf";
            // ] generate the file name for the pdf
            // get a safe place to save the temp file from the notes ini file 
            // this includes handling escape charters [ 
            String writeDirectory = session.getEnvironmentString("Directory", true);
            createdFileNameAndLocation = writeDirectory.replaceAll("\\", "\\\\") + "\" + createdFileName;
            FileOutputStream fos = new FileOutputStream(createdFileNameAndLocation);
            // ] get a safe place to save the temp file from the notes ini file
            // create the pdf and generate its content based on its template [
            PDF pdf = new PDF(fos);
            pdf = TemplateDemo(pdf, sourcedoc);
            pdf.flush();
            // ] create the pdf and generate its content based on its template
            //Save the pdf back to the document [ 
            RichTextItem bodyAttachments = null;
            if (sourcedoc.hasItem("Attachments")) {
                bodyAttachments =(RichTextItem)sourcedoc.getFirstItem("Attachments"); 
            } else {
                bodyAttachments = sourcedoc.createRichTextItem("Attachments");                
            }
            bodyAttachments.embedObject(EmbeddedObject.EMBED_ATTACHMENT, null, createdFileNameAndLocation, createdFileName);
            if (sourcedoc.save()) {
                System.out.println("attachment saved back to document");
            }
            // ] Save the pdf back to the document
            fos.close();
            //delete the temp file [
            File f = new File(createdFileNameAndLocation);
            f.delete();
            //] delete the temp file
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //i prefer to move the layout into different functions to keep the code as clean as possible
    public PDF TemplateDemo(PDF pdf, Document sourcedoc) throws Exception {
        String Title = sourcedoc.getItemValueString("Title");
        pdf.setTitle(Title);
        pdf.setSubject(Title);
        pdf.setAuthor("London Developer Coop");
        Font f1 = new Font(pdf, "Helvetica");
        Font f2 = new Font(pdf, "Helvetica-Bold");
        Font f3 = new Font(pdf, "Helvetica-Bold");
        //this picks up an image from a file stored in side the Domino Java agent [
        InputStream logoStream = getClass().getClassLoader().getResourceAsStream("Logo.jpg");
        if (logoStream == null) {
            System.out.println("stream empty");
        }
        Image logoImage = new com.pdfjet.Image(pdf, logoStream, 1); // the '1' parmeter means its expecting a jpg  
        // ] see below the code for other methods
        Page page = new Page(pdf, Letter.PORTRAIT);
        f1.setSize(12);
        f2.setSize(16);
        f3.setSize(14);
        //3 item header 'text,text,image' Header [
        logoImage.setPosition(502, 40);
        logoImage.scaleBy(0.5);
        logoImage.drawOn(page);
        Paragraph t1p1 = new Paragraph();
        t1p1.setAlignment(Align.CENTER);
        t1p1.add(new TextLine(f2, "I am a test document"));
        TextColumn columnt1 = new TextColumn(f1);
        columnt1.addParagraph(t1p1);
        columnt1.setPosition(0, 50);
        columnt1.setSize(150, 100);       
        columnt1.drawOn(page);
        Paragraph t2p1 = new Paragraph();
        t2p1.setAlignment(Align.CENTER);
        t2p1.add(new TextLine(f2, Title));
        TextColumn columnt2 = new TextColumn(f1);
        columnt2.addParagraph(t2p1);
        columnt2.setPosition(151, 50);
        columnt2.setSize(300, 100);       
        columnt2.drawOn(page);
        // ] Header
        //chunk of text[
        //I personally prefer getting data values for display via evaluate as they are easy to handle and return nice strings
        Vector v = null;
        v = session.evaluate("CollaborationDate", sourcedoc);
        Paragraph parm1b = new Paragraph();
        parm1b.setAlignment(Align.LEFT);
        parm1b.add(new TextLine(f1, v.firstElement().toString() ));
        TextColumn columnm1b = new TextColumn(f1);
        columnm1b.addParagraph(parm1b);
        columnm1b.setPosition(130, 100);
        columnm1b.setSize(450, 100);       
        columnm1b.drawOn(page);
        // ] chuck of text
        return pdf;
    }
}

In the code above I’m getting the image from an image file included as a resource in the agent itself, for those brave enough to need to get it from the notes design and not allowed to pick it up as a URL, I point you to this article from LEkkimWorld

Anyway. yell if ive missed anything.

Old Comments
————
##### Mark Myers(14/06/2011 00:24:02 GDT)
@Mike good link!! i read the full article that @sean linked to which describes the reason for the licence change (all perfectly normal reasons), thankfully as the pdfjet licence is a developer one, and i have made the investment I can keep using it and keep up to date

has anyone else had issues with different generators/versions being barred (one of my main client officially does not allow ANY open source on their site (dispute having Apache all over the place))
##### Rotary Club Jersey(13/06/2011 22:28:23 GDT)
You could always use an older version of iText, back in the days before they changed the license?
##### Sean Cull(13/06/2011 19:39:37 GDT)
they liked your article so much they raised the price to USD 297 !
{ Link }
##### sean cull(13/06/2011 20:00:39 GDT)
more on the itext changes including comments from the creator of itext. :
{ Link }
##### Stephan H. Wissel(13/06/2011 20:27:05 GDT)
Did you try Apache PDFBox?
##### Mike Brown(14/06/2011 00:03:06 GDT)
You can get older versions of iText from the OpenLogic Exchange site. iText 2.1.7 appears to be the last one before the licence was changed:

{ Link }

That one is covered under the LGPL v2 and the MPL 1.1, which means you’re pretty well free to use them without paying fees or disclosing the source code for your app… I think! (I’m no expert.)

Incidentally, this is the version that you *have* to use if you’re still on Domino 7 anyway.

##### Mark Myers(13/06/2011 23:42:16 GDT)
@sean , thanks for the correction Emoticon , and the link to the info on the licence change

@Stephen, I had a look at PDFBox (Apache is always a good place to start for anything) but decided against it on the grounds of PDFjet’s simplicity, the fact that it did EVERYTHING I wanted (with 14 good examples) and the nice documentation package that I could attach to the db for future devs, also PDFBox had a long period of near stagnation (which it is now making up for) while PDFJet as a commercial application is updated regularly (such as support for QR code barcodes, PNG images with alpha transparency etc etc which i already have a use for for another client)

@Rotary Club Jersey, yeah, the clients no itext was very flat so i did not think that was a good idea.

Leave a Reply

Your email address will not be published. Required fields are marked *