Recently, I got a requirement from one of the clients to generate PDF report. The traditional way to generate PDF report is using Jasper reports(jrxml). In my previous projects I had used iReport to generate PDF using .jrxml but it is a bit time consuming and hectic process. I will show you an easy and convenient way of generating PDF report. We can use phantomJS to render the PDF using the html output. We first need to install phatomjs on ubuntu using the following command:


sudo apt-get install phantomjs

Once it is installed you can download rasterize.js from the following location:

PhantomJS Github link
rasterize.js is responsible for rendering the PDF from HTML content. I used the following configuration of rasterize.js. You can edit it as per your requirement:

 

"use strict";
var page = require('webpage').create(),
    system = require('system'),
    address, output, size;

if (system.args.length < 3 || system.args.length > 5) {
    console.log('Usage: rasterize.js URL filename [paperwidth*paperheight|paperformat] [zoom]');
    console.log('  paper (pdf output) examples: "5in*7.5in", "10cm*20cm", "A4", "Letter"');
    console.log('  image (png/jpg output) examples: "1920px" entire page, window width 1920px');
    console.log('                                   "800px*600px" window, clipped to 800x600');
    phantom.exit(1);
} else {
    address = system.args[1];
    output = system.args[2];
    page.viewportSize = { width: 540, height: 1500 };
    if (system.args.length > 3 && system.args[2].substr(-4) === ".pdf") {
        size = system.args[3].split('*');
        page.paperSize = size.length === 2 ? { width: size[0], height: size[1], margin: '0px' }
                                           : { format: system.args[3], orientation: 'portrait', margin: '1cm' };
    } else if (system.args.length > 3 && system.args[3].substr(-2) === "px") {
        size = system.args[3].split('*');
        if (size.length === 2) {
            pageWidth = parseInt(size[0], 10);
            pageHeight = parseInt(size[1], 10);
            page.viewportSize = { width: pageWidth, height: pageHeight };
            page.clipRect = { top: 600, left: 600, width: pageWidth, height: pageHeight };
        } else {
            console.log("size:", system.args[3]);
            pageWidth = parseInt(system.args[3], 10);
            pageHeight = parseInt(pageWidth * 3/4, 10); // it's as good an assumption as any
            console.log ("pageHeight:",pageHeight);
            page.viewportSize = { width: pageWidth, height: pageHeight };
        }
    }
   
        page.zoomFactor = 1.5;
    
    page.open(address, function() {
        setTimeout(function() {
        	try {
 page.dpi=300;
        		page.render(output);
    	        phantom.exit();
        	} catch(e) {
        		console.log('Error happened: ' + e.toString());
        		phantom.exit();
        	}
        }, 3000);
    });
}

You can place rasterize.js in your desired location.
To render and download the PDF I used the following java code:


String pathToPhantomJS = "/usr/bin/phantomjs" //phantom js path
String pathToRasterizeJS = "/home/vivek/Desktop/rasterize.js" //path to your rasterize.js
String paperSize = "A4"
String url = "URL_HERE" //url of your web page which you want to convert into pdf
File outputFile = File.createTempFile("fileName", ".pdf") //file in which you want to save your pdf
Process process = Runtime.getRuntime().exec(pathToPhantomJS + " " + pathToRasterizeJS + " " + url + " " + outputFile.absolutePath + " " + paperSize);
int exitStatus = process.waitFor(); 
if (exitStatus != 0) {
log.error("EXIT-STATUS - " + process.toString());
}
response.contentType = "application/pdf"
response.setHeader("Content-Disposition", "attachment; filename=sample.pdf");
response.outputStream << outputFile.bytes
response.outputStream.flush()
response.outputStream.close()

Once PDF is downloaded you can check the preview and change the rasterize.js to adjust the viewport size and zoomfactor if needed.