Wednesday, May 9, 2012

PDF file download dialog with JAX-RS

Below I will show how to display PDF file download dialog to the user using REST JAX-RS.

My implementation below will NOT create PDF file in user's directory until the user choose "save as" in the dialog box. To achieve this, I used ByteArrayInputStream class.

 

ByteArrayOutputStream baos = new ByteArrayOutputStream();

//This is just PDF generation API
JasperExportManager.exportReportToPdfStream(jasperPrint, baos);
                
byte[] entity = baos.toByteArray();
                
return Response.ok(entity)
        .header("Content-Disposition", "attachment; filename=MyAwesomeJasperReportDownload.pdf")
        .type("application/pdf")
        .build();

Jasper Report - how to write Java code without query

I've seen many article talking about how to write Java code to generate Jasper Report using SQL query.

But in some occasion you don't want to write SQL exposing table names etc other than your application code.

In my project I get data from database and the data is processed (modified) to output in PDF.

Below is example of not using database connection.


 

//------- import ---------
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRMapCollectionDataSource;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.view.JasperViewer;


//------emitted some code ----------

public static void main(String[] args) {
        
       
        try {
            
            File jrxmlFile = new File("C:\\Users\\m-tak\\report2.jrxml");

            if(jrxmlFile.exists()) {

                //jrxml compile
                JasperReport jasperReport = JasperCompileManager.compileReport(jrxmlFile.getAbsolutePath());
                
                
                //detail section
                List<Map<String, ?> list = new ArrayList<Map<String, ?>();
                
                Random rd = new Random();
                for(int j = 0; j < 10; j++) {
                    Map<String, Object> map2 = new HashMap<String, Object>();
                    map2.put("listItem", rd.nextInt());
                    map2.put("listItem2", new StringBuilder().append(rd.nextInt()).append("foobar"));
                    list.add(map2);
                }
                
                JRMapCollectionDataSource dataSource = new JRMapCollectionDataSource(list);
                
                
                Map params = new HashMap();
                params.put("orderNumber", "12345");
                params.put("payment", "6789");
                params.put("other", "something");
                

                JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params, dataSource);
                JasperViewer.viewReport(jasperPrint, false);
                
            }
        }
        catch(Exception e) {
            System.out.println("-------------------- PDF exception ");
            System.out.println(e);
        }
        System.out.println("DONE");
        
}


First of all let me explain what data we need to prepare.

  • 1. Map of data used as parameter. i.e "params"
  • 2. List which contains Map used as field. i.e "dataSource"
  • Note: Map used in 1 and 2 are of different Map so don't confuse them.



     
     
    JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params, dataSource);
     
    
    


    The code below prepares the params. It's just simple Map with ordinary key/value pair.

    
    Map params = new HashMap();
    params.put("orderNumber", "12345");
    params.put("payment", "6789");
    params.put("other", "something");
    
    


    Next we need List contains Map for dataSource. At the end, the List is passed to JRMapCollectionDataSource.

    List<Map<String, ?> list = new ArrayList<Map<String, ?>();
                    
    Random rd = new Random();
    for(int j = 0; j < 10; j++) {
        Map<String, Object=""> map2 = new HashMap<String, Object>();
        map2.put("listItem", rd.nextInt());
        map2.put("listItem2", new StringBuilder().append(rd.nextInt()).append("foobar"));
        list.add(map2);
    }
                    
    JRMapCollectionDataSource dataSource = new JRMapCollectionDataSource(list);
    


    Finally it's time to pass params and fields (dataSource) to JasperFillManager and JasperViewer will display the PDF view.

    JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params, dataSource);
    JasperViewer.viewReport(jasperPrint, false);