Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

In this tutorial, we will follow the guideline of for developing a plugin to develop our Download PDF Datalist Action plugin. Please also refer to the very first tutorial How to develop a Bean Shell Hash Variable for more details steps.

...

When the plugin is used for multiple datalist rows (whole list action), a zip file containing all the generated PDFs of every selected rows will be prompted for download when the button is clicked.

5.

...

Are there any resources/API that can be reused?

To develop the PDF Download Datalist Action plugin, we can reuse the methods in FormPdfUtil to generate a form as PDF. We can also refer to the source code of the Datalist Form Data Delete Action plugin as well. Other than that, we can refer to the Export Form Email Tool on what kind of plugin properties options we can provide in the plugin as the Export Form Email Tool are using the methods in FormPdfUtil as well.

...

The following tutorial is prepared with a Macbook Pro and the Joget Source Code is version 5.0.0. Please refer to the Guideline for developing a plugin article for other platform commands.

...

Code Block
languagebash
cd joget/plugins/
~/joget/jw-community/5.0.0/wflow-plugin-archetype/create-plugin.sh org.joget.tutorial download_pdf_datalist_action 5.0.0-SNAPSHOT

Then, the shell script will ask us to key in a version number for the plugin and ask us for a confirmation before it generates the maven project.

...

Code Block
languagejava
    public DataListActionResult executeAction(DataList dataList, String[] rowKeys) {
        // only allow POST
        HttpServletRequest request = WorkflowUtil.getHttpServletRequest();
        if (request != null && !"POST".equalsIgnoreCase(request.getMethod())) {
            return null;
        }
        
        // check for submited rows
        if (rowKeys != null && rowKeys.length > 0) {
            try {
                //get the HTTP Response
                HttpServletResponse response = WorkflowUtil.getHttpServletResponse();
                if (rowKeys.length == 1) {
                    //generate a pdf for download
                    singlePdf(request, response, rowKeys[0]);
                } else {
                    //generate a zip of all pdfs
                    multiplePdfs(request, response, rowKeys);
                }
            } catch (Exception e) {
                LogUtil.error(getClassName(), e, "Fail to generate PDF for " + ArrayUtils.toString(rowKeys));
            }
        }
        
        //return null to do nothing
        return null;
    }
    
    /**
     * Handles for single pdf file
     * @param request
     * @param response
     * @param rowKey
     * @throws IOException 
     * @throws javax.servlet.ServletException 
     */
    protected void singlePdf(HttpServletRequest request, HttpServletResponse response, String rowKey) throws IOException, ServletException {
        byte[] pdf = getPdf(rowKey);
        writeResponse(request, response, pdf, rowKey+".pdf", "application/pdf");
    }
    
    /**
     * Handles for multiple files download. Put all pdfs in zip.
     * @param request
     * @param response
     * @param rowKeys 
     * @throws java.io.IOException 
     * @throws javax.servlet.ServletException 
     */
    protected void multiplePdfs(HttpServletRequest request, HttpServletResponse response, String[] rowKeys) throws IOException, ServletException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(baos);
        
        try {
            //create pdf and put in zip
            for (String id : rowKeys) {
                byte[] pdf = getPdf(id);
                zip.putNextEntry(new ZipEntry(id+".pdf"));
                zip.write(pdf);
                zip.closeEntry();
            }
 
            zip.finish();
            writeResponse(request, response, baos.toByteArray(), getLinkLabel() +".zip", "application/zip");
        } finally {
            baos.close();
            zip.flush();
        }
    }
    
    /**
     * Generate PDF using FormPdfUtil
     * @param id
     * @return 
     */
    protected byte[] getPdf(String id) {
        AppDefinition appDef = AppUtil.getCurrentAppDefinition();
        String formDefId = getPropertyString("formDefId");
 
        Boolean hideEmptyValueField = null;
        if (getPropertyString("hideEmptyValueField").equals("true")) {
            hideEmptyValueField = true;
        }
        Boolean showNotSelectedOptions = null;
        if (getPropertyString("showNotSelectedOptions").equals("true")) {
            showNotSelectedOptions = true;
        }
        Boolean repeatHeader = null;
        if ("true".equals(getPropertyString("repeatHeader"))) {
            repeatHeader = true;
        }
        Boolean repeatFooter = null;
        if ("true".equals(getPropertyString("repeatFooter"))) {    
            repeatFooter = true;
        }
        String css = null;
        if (!getPropertyString("formatting").isEmpty()) {
            css = getPropertyString("formatting");
        }
        String header = null; 
        if (!getPropertyString("headerHtml").isEmpty()) {
            header = getPropertyString("headerHtml");
            header = AppUtil.processHashVariable(header, null, null, null);
        }
        String footer = null; 
        if (!getPropertyString("footerHtml").isEmpty()) {
            footer = getPropertyString("footerHtml");
            footer = AppUtil.processHashVariable(footer, null, null, null);
        }
        
        return FormPdfUtil.createPdf(formDefId, id, appDef, null, hideEmptyValueField, header, footer, css, showNotSelectedOptions, repeatHeader, repeatFooter);
    }
    
    /**
     * Write to response for download
     * @param response
     * @param bytes
     * @param filename
     * @param contentType
     * @throws IOException 
     */
    protected void writeResponse(HttpServletRequest request, HttpServletResponse response, byte[] bytes, String filename, String contentType) throws IOException, ServletException {
        OutputStream out = response.getOutputStream();
        try {
            String name = URLEncoder.encode(filename, "UTF8").replaceAll("\\+", "%20");
            response.setHeader("Content-Disposition", "attachment; filename="+name+"; filename*=UTF-8''" + name);
            response.setContentType(contentType+"; charset=UTF-8");
            
            if (bytes.length > 0) {
                response.setContentLength(bytes.length);
                out.write(bytes);
            }
        } finally {
            out.flush();
            out.close();
            
            //simply fowardforward to a 
            request.getRequestDispatcher(filename).forward(request, response);
        }
    }

...

Code Block
languagejava
    public void start(BundleContext context) {
        registrationList = new ArrayList<ServiceRegistration>();
        //Register plugin here
        registrationList.add(context.registerService(DownloadPdfDatalistAction.class.getName(), new DownloadPdfDatalistAction(), null));
    }

 

f. Build it and test

...

Let's build our plugin. Once the building process is done, we will find a "download_pdf_datalist_action-5.0.0.jar" file created under "download_pdf_datalist_action/target" directory.

...