Search code examples
javajasper-reportsrestful-url

Java Restful API return PDF file with Jasper


I have a Restful API (JAX-RS) and I need return a PDF file using the JasperReport library.

But when I run the URL in browser the Jasper generation method gives null in FacesContext.getCurrentInstance().getExternalContext() line. Can I catch the external context by HttpServletRequest?

Can anybody help me?

Bellow my "RestClass"

@Path("/Integracao")
public class Integracao {

@GET
@Path("/teste")
public void teste(){
    TrCboServiceImpl cS = new TrCboServiceImpl();
    List datasource = null;
    try {
        datasource = cS.listAll();
    } catch (ServiceException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    AbstractApplicationBean aab = new AbstractApplicationBean() {       
        @Override
        public boolean useMultiempresaService() {               
            return false;
        }
    }; 


    try {
        aab.gerarJasper("RelTrCbo", TipoRelatorioEnum.PDF.getType(), datasource, new HashMap<>());
    } catch (Exception e) {
        e.printStackTrace();
    }
}
}

and my generator jasper

public void gerarJasper(String name, String type, List data, Map params) throws IllegalArgumentException, RuntimeException, Exception {

    boolean found = false;
    for (int i = 0; i < VALID_TYPES.length; i++) {
        if (VALID_TYPES[i].equals(type)) {
            found = true;
            break;
        }
    }
    if (!found) {
        throw new IllegalArgumentException("Tipo solicitado '" + type + "' inválido");
    }

    // Procurar recurso de design de relatório compilado
    // NullPointerException OCCURS HERE!!!
    ExternalContext econtext = FacesContext.getCurrentInstance().getExternalContext();

    InputStream stream = econtext.getResourceAsStream(PREFIX + name + SUFFIX);
    if (stream == null) {
        throw new IllegalArgumentException("O relatório '" + name + "' não existe");
    }

    FacesContext fc = FacesContext.getCurrentInstance(); 
    ServletContext context = (ServletContext)fc.getExternalContext().getContext();
    String path = context.getRealPath(File.separator) + "resources/jasper" + File.separator;
    String logo = context.getRealPath(File.separator) + "resources/imagens" + File.separator;
    params.put("SUBREPORT_DIR", path);
    params.put("LOGO_DIR", logo);                

    JRDataSource ds = new JRBeanArrayDataSource(data.toArray());
    JasperPrint jasperPrint = null;
    try {
        jasperPrint = JasperFillManager.fillReport(stream, params, ds);
    } catch (RuntimeException e) {
        throw e;
    } catch (Exception e) {
        throw new FacesException(e);
    } finally {
        try {
            stream.close();
        } catch (IOException e) {
        }
    }

    JRExporter exporter = null;
    HttpServletResponse response = (HttpServletResponse) econtext.getResponse();
    FacesContext fcontext = FacesContext.getCurrentInstance();
    try {
        response.setContentType(type);
        if ("application/pdf".equals(type)) {
            exporter = new JRPdfExporter();
            exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
            exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, response.getOutputStream());
        } else if ("text/html".equals(type)) {
            exporter = new JRHtmlExporter();
            exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
            exporter.setParameter(JRExporterParameter.OUTPUT_WRITER, response.getWriter());

            HttpServletRequest request = (HttpServletRequest) fcontext.getExternalContext().getRequest();
            request.getSession().setAttribute(ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, jasperPrint);
            exporter.setParameter(JRHtmlExporterParameter.IMAGES_MAP, new HashMap());

            exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, request.getContextPath() + "/image?image=");
        }else if("application/xlsx".equals(type)){
            exporter = new JRXlsxExporter();
            exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
            exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, response.getOutputStream());
        }else if("application/docx".equals(type)){
            exporter = new JRDocxExporter();
            exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
            exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, response.getOutputStream());
        } else if("application/rtf".equals(type)){
            exporter = new JRRtfExporter();
            exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
            exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, response.getOutputStream());
        }
    } catch (RuntimeException e) {
        throw e;
    } catch (Exception e) {
        throw new FacesException(e);
    }

    try {
        exporter.exportReport();
    } catch (RuntimeException e) {
        throw e;
    } catch (Exception e) {
        throw new FacesException(e);
    }
    fcontext.responseComplete();
}

Solution

  • I solved the problem!!! I need import iReport, barbecue-1.5, barcode4j-2.0, jasperserver-ireport-plugin-2.0.1, jdt-compiler-3.1.1 jars in lib folder on my project (Restful API)

    below my code

    @Path("/Integracao")
    public class Integracao {
    
    @Context
    private HttpServletRequest httpServletRequest;
    
    @GET
    @Path("/gerarPdf")
    public Response geraPDF(@QueryParam("relatorio") String arquivoJrxml,
                            @QueryParam("autorizacao") String autorizacao){
    
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        Map fillParams = new HashMap(); 
        fillParams.put("IMPRAUTORIZACAO", autorizacao);
        PdfGenerator pdf = new PdfGenerator();
        byte[] bytes= pdf.generateJasperReportPDF(httpServletRequest, arquivoJrxml, outputStream, fillParams);
    
        String nomeRelatorio= arquivoJrxml + ".pdf";
        return Response.ok(bytes).type("application/pdf").header("Content-Disposition", "filename=\"" + nomeRelatorio + "\"").build();
    }
    

    }

    and my util class

    public class PdfGenerator {
    
    public byte[]  generateJasperReportPDF(HttpServletRequest httpServletRequest, String jasperReportName, ByteArrayOutputStream outputStream, Map parametros) {
        JRPdfExporter exporter = new JRPdfExporter();
        try {
            String reportLocation = httpServletRequest.getRealPath("/") +"resources\\jasper\\" + jasperReportName + ".jrxml";
    
            InputStream jrxmlInput = new FileInputStream(new File(reportLocation)); 
            //this.getClass().getClassLoader().getResource("data.jrxml").openStream();
            JasperDesign design = JRXmlLoader.load(jrxmlInput);
            JasperReport jasperReport = JasperCompileManager.compileReport(design);
            //System.out.println("Report compiled");
    
            //JasperReport jasperReport = JasperCompileManager.compileReport(reportLocation);
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parametros, HibernateUtils.currentSession().connection()); // datasource Service
    
            exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);   
            exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputStream);
            exporter.exportReport();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("Error in generate Report..."+e);
        } finally {
        }
        return outputStream.toByteArray();
    }
    }