Skip to main content

Concatenating BIRT reports via servlet

I've been using BIRT a bit and in our project we generate alot of PDFs and have found BIRT to be the beswt product there is for that.  One thing BIRT does NOT allow you to do is to combine reports.  The below is my Servlet based solution for that which correctly renumbers the pages  It borrows the concatenation from Abhi on Java.

I also bought IText in Action  A must have for the serious developer of PDF's in Java.

I've stripped out the company specific part of this code, but have not tried compiling this version.  it should be pretty damn close to what you need though.  Ask if you have any questions.

Of course this code is completely free to use and is released under the Academic Free License

**********************************




import javax.servlet.*;
import javax.servlet.http.*;

import com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;


import java.io.*;
import java.net.URL;
import java.util.*;

public class PDFServlet extends HttpServlet {

    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       response.setContentType("application/pdf"); // Code 1
       List<InputStream> pdfs = new ArrayList<InputStream>();
       String prefix=http://myBirtServer?__report=report/";
       String params="&oid="+request.getParameter("oid")+"&__format=pdf";
       String [] URLs={
                "myReport1.rptdesign",
                "myReport2.rptdesign",
                "myReport3.rptdesign",
                "myReport4.rptdesign",
                "myReport5.rptdesign",
                "myReport6.rptdesign"
       };
       for(int x=0;x<URLs.length;x++){
         URL u1=new URL(prefix+URLs[x]+params);
         System.out.println(u1);  
         InputStream in=u1.openStream();
         pdfs.add(in);
       }
       concatPDFs(pdfs,response.getOutputStream(),true);

    }

/**
* Method written by Abhi
*/ 
public static void concatPDFs(List<InputStream> streamOfPDFFiles, OutputStream outputStream, boolean paginate, String watermark) {
        Document document = new Document(PageSize.LETTER.rotate());
        try {
            List<InputStream> pdfs = streamOfPDFFiles;
            List<PdfReader> readers = new ArrayList<PdfReader>();
            int totalPages = 0;
            Iterator<InputStream> iteratorPDFs = pdfs.iterator();
            int x = 0;
            // Create Readers for the pdfs.
            while (iteratorPDFs.hasNext()) {
                System.out.println((++x) + " through the loop1");
                try {
                    InputStream pdf = iteratorPDFs.next();
                    PdfReader pdfReader = new PdfReader(pdf);
                    readers.add(pdfReader);
                    totalPages += pdfReader.getNumberOfPages();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            // Create a writer for the outputstream
            PdfWriter writer = PdfWriter.getInstance(document, outputStream);
            if (!STR.isEmpty(watermark)) {
                writer.setPageEvent(new Watermark(watermark));
            }
            document.open();
            BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
            PdfContentByte cb = writer.getDirectContent(); // Holds the PDF
            // data

            PdfImportedPage page;
            int currentPageNumber = 0;
            int pageOfCurrentReaderPDF = 0;
            Iterator<PdfReader> iteratorPDFReader = readers.iterator();

            // Loop through the PDF files and add to the output.
            while (iteratorPDFReader.hasNext()) {
                PdfReader pdfReader = iteratorPDFReader.next();

                // Create a new page in the target for each source page.
                while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
                    document.newPage();
                    pageOfCurrentReaderPDF++;
                    currentPageNumber++;
                    page = writer.getImportedPage(pdfReader, pageOfCurrentReaderPDF);
                    cb.addTemplate(page, 0, 0);

                    // Code for pagination.
                    if (paginate) {
                        cb.beginText();
                        cb.setFontAndSize(bf, 9);
                        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, "" + currentPageNumber + " of " + totalPages, 520, 5, 0);
                        cb.endText();
                    }
                }
                pageOfCurrentReaderPDF = 0;
            }
            outputStream.flush();
            document.close();
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (document.isOpen())
                document.close();
            try {
                if (outputStream != null)
                    outputStream.close();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }

    /**
     * Inner class to add a watermark to every page.
     */
    static class Watermark extends PdfPageEventHelper {

        private String watermark;

        public Watermark(String wm) {
            watermark = wm;
        }

        Font FONT = new Font(Font.FontFamily.HELVETICA, 52, Font.BOLD, new GrayColor(0.75f));

        public void onEndPage(PdfWriter writer, Document document) {
            ColumnText.showTextAligned(writer.getDirectContentUnder(),
                    Element.ALIGN_CENTER, new Phrase(watermark, FONT),
                    421, 297.5f, writer.getPageNumber() % 2 == 1 ? 45 : -45);
        }
    }

    

}

Comments

Ashwini Verma said…
Great tip on concatenating BIRT reports via servlet. Can you also submit a link to your article on BIRT Exchange devshare (http://www.birt-exchange.org/org/devshare/) so more BIRT developers can benefit from it?
Dan Fishman said…
Done.

Popular posts from this blog

 In software engineering, accumulating code behind a release wall is akin to gathering water behind a dam. Just as a dam must be built higher and stronger to contain an increasing volume of water, the more code we delay releasing, the more resources we must allocate to prevent a catastrophic flood—major bugs or system failures—while also managing the inevitable trickles—minor issues and defects. Frequent, smaller releases act like controlled spillways, effectively managing the flow of updates and reducing the risk of overwhelming both the system and the team. The ideal of ci/cd may not be achievable for all teams, but smaller and faster is always better.

Preventing accidental large deletes.

Instructions for Developers on Using the safe_delete Stored Procedure To enhance safety and auditability of delete operations within our databases, we have implemented a controlled deletion process using a stored procedure named safe_delete . This procedure relies on a temporary table ( temp_delete_table ) that lists complete records intended for deletion, not just their IDs. This approach helps prevent accidental deletions and provides a traceable audit log of delete actions. Why We Are Doing This Controlled Deletions : Centralizing delete operations through a stored procedure reduces the risk of erroneous or unauthorized deletions. Auditability : Using a temporary table to store complete records before deletion allows for an in-depth review and verification process, enhancing our ability to confirm and audit delete operations accurately. Security : Restricting direct delete permissions and channeling deletions through a specific proced...

October is Cyber Security Month

The President has declared October as Cybersecurity month.  It's not a bad idea -- just like you change the batteries in your smoke detectors once a year, maybe you should review your electronic vulbnerabilities? My top ten security tips: 1) Change your passwords.  You've had them too long, you use the same password in too many places.  Somewhere someone has hacked a site that has your username and password in plain text.  Now they are getting ready to try that username/password somewhere else.  Beat them to the punch. 2) Use a safe browser.  That means anything that's not Internet Explorer.   I prefer chrome. 3) Use 2 step verification for your email account.  If your email doesn't provide 2 step authentication consider switching. 4) Get a free credit report  and review it.  You are entitled to one free report a year.   BE VERY CAREFUL!  There are man scam sites that offer free credit reports.  Go through the s...