Using Jasper Reports to generate dynamic Images

Problem Statement:
Generate images with dynamic data

Solution proposed:

Use Jasper Reports to generate dynamic images

Why?
Jasper is a reporting tool used to generate reports in any format - PNG , JPEG, PDF, Excel etc. We will be making use of its image generation component.

We had earlier decided to use Java AWT to create our own images, but then it was difficult for design team to give exact specifications. They wanted a tool to easily define image components like logos, text, input fields etc. Jasper came in handy because it has a Jasper Studio which is perfect for designing.

Feature: To create visiting cards.
Lets keep it simple - we just add name and designation.

Softwares Used

Jasper Studio (9.3.1 final): http://community.jaspersoft.com/project/jaspersoft-studio

Jasper Reports Java API (jasperreports-6.3.1.jar): http://community.jaspersoft.com/project/jasperreports-library/releases

Design image

Let me call our jasper JRXML as a template.

Clearing up clutter

Open "Source" tab in main workarea and remove all the child tags of except . Here we will place our components.

Setting up name placeholder

Drag and drop "Text Field" from "Palette" view into workarea. Position it according to what you want. 
Click on text field and this pops "Properties" view for Text Field. In this go to "Text Field" tab.
Near "Expression" text box is an icon. Click it. This opens "Expressions editor". Select "Parameters" on left window. Select "REPORT_PARAMETERS_MAP" in second window. Double click "get" in third window. This will create an expression on top window. Make that read as $P{REPORT_PARAMETERS_MAP}.get( "name" )
It should look like below:

So now "name" becomes our placeholder. Let me call it "template key".

Setting up designation label

Drag and drop "Static Text" component from "Palette" into work area. Position it properly.
Click on it to open "Properties" view. 
Open "Static text" tab in "Properties".
In Text field box, write "Designation". This is what we would like to see on visiting card.

Setting up designation placeholder

Do same as we did for name place holder. Mention template key as 
$P{REPORT_PARAMETERS_MAP}.get( "designation" )

Save this JRXML.

So on workarea, image looks like
 And source JRXML looks like
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.3.1.final using JasperReports Library version 6.3.1  -->
<!-- 2017-02-10T01:46:35 -->
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="visiting_card" pageWidth="300" pageHeight="200" columnWidth="260" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="8acaa693-649a-48da-845d-992da9f3b4c6">
    <detail>
        <band height="160" splitType="Stretch">
            <staticText>
                <reportElement x="0" y="90" width="100" height="30" uuid="89272bdc-07f8-485c-bcc4-5551232296c7"/>
                <textElement>
                    <font size="16"/>
                </textElement>
                <text><![CDATA[Designation:]]></text>
            </staticText>
            <textField>
                <reportElement x="0" y="31" width="260" height="29" uuid="37cdb745-6f42-4a33-9d3c-8e712df95ef1"/>
                <textElement>
                    <font size="16"/>
                </textElement>
                <textFieldExpression><![CDATA[$P{REPORT_PARAMETERS_MAP}.get( "name" )]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="100" y="90" width="160" height="20" uuid="5dff3cdf-2e28-4175-9160-a6ea009cfe69"/>
                <textElement>
                    <font size="16"/>
                </textElement>
                <textFieldExpression><![CDATA[$P{REPORT_PARAMETERS_MAP}.get( "designation" )]]></textFieldExpression>
            </textField>
        </band>
    </detail>
</jasperReport>

Save it as visiting_card.jrxml

Java code to convert JRXML into image 

Quickstart pom.xml 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.castlight.jasper</groupId>
    <artifactId>JasperLearning</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>JasperLearning</name>

    <dependencies>
        <dependency>
            <groupId>net.sf.jasperreports</groupId>
            <artifactId>jasperreports</artifactId>
            <version>6.4.0</version>
        </dependency>
    </dependencies>
</project>

Java code:

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import net.sf.jasperreports.engine.DefaultJasperReportsContext;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperPrintManager;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class VisitingCard {

   public static void main(String[] args) throws Exception {
      JasperReport jasperReport = JasperCompileManager.compileReport("visiting_card.jrxml");
      JRDataSource jrDataSource = new JRBeanCollectionDataSource(Arrays.asList(new Object()));
     
      Map templateMap = new HashMap();
      templateMap.put("name", "Harshvardhan Singh");
      templateMap.put("designation", "Principal Engineer");
     
      JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, templateMap, jrDataSource);
      generateImage("visiting_card.png", jasperPrint);

   }
  
   private static void generateImage(String outputImagePath, JasperPrint print) throws IOException {
      File file = new File(outputImagePath);
      OutputStream ouputStream = null;
      try {
         ouputStream = new FileOutputStream(file);
         DefaultJasperReportsContext ctx = DefaultJasperReportsContext.getInstance();
         JasperPrintManager printManager = JasperPrintManager.getInstance(ctx);

         BufferedImage rendered_image = null;
         rendered_image = (BufferedImage) printManager.printPageToImage(print, 0, 10f);
         ImageIO.write(rendered_image, "png", ouputStream);


      } catch (Exception e) {
         e.printStackTrace();
      } finally {
         ouputStream.close();
      }
   }

}

Notice that I set name and designation parameters

Card generated looks like




Note: True power of Jasper Reports is much much more than creating dynamic images. But combination of Jasper Studio and Jasper Reports java library make it a powerful tool.

Comments