-2

I am try to export a PDF based on an Dynamic Jasper Report, using gradle setting.

build.gradle:

compile (group: 'net.sf.jasperreports', name: 'jasperreports', version: '6.18.1')
    implementation group: 'ar.com.fdvs', name: 'DynamicJasper', version: '5.3.3'
    implementation group: 'org.apache.poi', name: 'poi', version: '4.1.1'
    // compile group: 'com.lowagie', name: 'itext', version:'2.1.7.js9'
    runtime files('libs/itext-2.1.7.js9.jar')

The Java code below, always exports an blank PDF page, if I export to CSV (from Japser), I can see the report generated with the correct fields. How do I fix to have the PDF correctly generated? Thanks in advance.

   private void setupPdfExport(String format, HttpServletResponse response, ActivePatientsData data, ReportCriteriaFormSupport support, String currencySymbol, ReportCriteriaForm reportCriteriaForm, PortalSecurityPrinciple principle) throws Exception {

        String csvFileName = "Active_patients."+format;
//        response.setContentType(format.equals("pdf")?"application/pdf":
//                format.equals("xsls")? "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" : "application/vnd.oasis.opendocument.spreadsheet");
        response.setContentType("application/octet-stream");
        String headerKey = "Content-Disposition";
        String headerValue = String.format("attachment; filename=\"%s\"", csvFileName);
        response.setHeader(headerKey, headerValue);


        List<List<String>> outputRows = getCsv(false, data, support, reportCriteriaForm, principle, codesToNames);


        List<String> headers = createHeadings(data, false);



        FastReportBuilder drb = new FastReportBuilder();
        String[] columnNames = headers.toArray(new String[0]);


        Style headerStyle = new Style();
        Font font = new Font(10, "Arial", true, false, false);
        headerStyle.setFont(font);
        headerStyle.setHorizontalAlign(HorizontalAlign.CENTER);
        headerStyle.setVerticalAlign(VerticalAlign.TOP);
        headerStyle.setBorder(Border.PEN_1_POINT());
        headerStyle.setBackgroundColor(Color.WHITE);
        headerStyle.setBorderColor(Color.BLACK);
        headerStyle.setTextColor(Color.BLACK);
        headerStyle.setTransparency(Transparency.OPAQUE);

        drb      .setDetailHeight(30)
                .setReportName("Active Patients")
                .setTitle("Active Patients")
                .setSubtitle("This report was generated at " + new Date())
                .setPageSizeAndOrientation(Page.Page_A4_Landscape())
                .setWhenNoData("No Data", headerStyle)
                .setUseFullPageWidth(true)
                .setDetailHeight(15)        //defines the height for each record of the report
                .setMargins(30, 20, 30, 15)     //define the margin space for each side (top, bottom, left and right)
                .setDefaultStyles(headerStyle, headerStyle, headerStyle, headerStyle)
        ;


//        drb.setTemplateFile(file.getAbsolutePath(), true, true, true, true);

        for(int i=0; i<columnNames.length; i++){
            drb.addColumn(columnNames[i],"COLUMN_"+i, String.class.getName(), 70,false );
        }


        List<Map<String, String>> dataRows = new LinkedList<>();
        for(int j=0; j<outputRows.size(); j++){
            List<String> row = outputRows.get(j);
            Map<String, String> dataMap = new HashMap<>();
            for(int i=0; i<columnNames.length; i++){
                dataMap.put("COLUMN_"+i, row.get(i));
            }
            dataRows.add(dataMap);
        }

        DynamicReport dr = drb.build();
JasperPrint jasperPrint = DynamicJasperHelper.generateJasperPrint(dr, new ClassicLayoutManager(), new JRBeanCollectionDataSource(dataRows), params);

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

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        if (format.equals("pdf")) {
            JRPdfExporter exporter = new JRPdfExporter();

            exporter.setExporterInput(new SimpleExporterInput(jasperPrint));


            SimplePdfReportConfiguration reportConfig
                    = new SimplePdfReportConfiguration();
            reportConfig.setSizePageToContent(false);
            reportConfig.setForceLineBreakPolicy(true);

            SimplePdfExporterConfiguration exportConfig
                    = new SimplePdfExporterConfiguration();
            exportConfig.setMetadataAuthor("Our Company");
            exportConfig.setEncrypted(false);
            exportConfig.setAllowedPermissionsHint("PRINTING");

            exporter.setConfiguration(reportConfig);
            exporter.setConfiguration(exportConfig);
            exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(out));
            exporter.exportReport();
            out.close();
    } 
    // ... Also code in if blocks for XLS 
    
        byte[] binData = out.toByteArray();
        OutputStream out1 = response.getOutputStream();
        out1.write(binData);
        out1.close();
        response.setContentLength(binData.length);
}
Dr BDO Adams
  • 416
  • 1
  • 5
  • 13
  • 3
    The code looks good. Maybe you should decouple the web/http code from the report logic to troubleshoot in a more slightly isolated way. Say, refactor this logic so that this report generation method becomes a service which does not know of the web/http at all, it receives business logic params and only returns a byteArray, then troubleshoot in isolation (maybe a test) – Dj Mamana Mar 18 '22 at 12:43

1 Answers1

1

File download is corrupt. When I write the output directly to a file via fileOutputStream the above code works, and produces a report table.

For corrupt downloads, see here, How to return binary data instead of base64 encoded byte[] in spring mvc rest controller

Dr BDO Adams
  • 416
  • 1
  • 5
  • 13