Start Process From Grid Data

Introduction

In this guide, you will learn how to automatically start a process instance for each row of data captured in a grid within a Joget form. The process definition to be started is "travel_approver_process", and the data will be pulled from the grid based on a matching batch record ID in gda_batch. This technique is particularly useful in scenarios where each grid row represents a separate transaction or approval that needs to be processed individually.

How does it work?

The solution involves capturing the grid data upon form submission and using BeanShell scripting to start a process instance for each row. The process is initiated within the Post Form Submission Processing phase, which can handle data creation and updates, depending on your specific requirements.

This is the form to capture the grid data.

When you submit this form, you’ll start a new process instance for each row in the grid.

You’ll use the process definition travel_approver_process to initiate these process instances.

SQL Query to Retrieve Grid Data

The grid data is retrieved by matching the current batch record ID in gda_batch and list down records from gda_travel. The following SQL query is used to fetch the relevant data:

SELECT * FROM app_fd_gda_travel WHERE c_batch = '#form.gda_batch.id#'

Post form submission processing

In the batch form, you can use Post-Form Submission Processing to capture the event of Data Creation or both data creation and update, whichever suits your own use case, and execute bean shell Java code to achieve this.

Bean shell Java code to iterate through grid data and start a process instance for each row.

import org.joget.workflow.model.service.WorkflowManager;
import org.joget.apps.app.service.AppUtil;
import org.joget.apps.app.service.AppService;
import org.joget.workflow.model.WorkflowAssignment;
import org.joget.workflow.util.WorkflowUtil;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.joget.workflow.model.WorkflowProcess;
import org.joget.workflow.model.WorkflowProcessResult;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.joget.commons.util.LogUtil;
 
//define process to start
String processDefKey = "travel_approver_process";
 
//utility bean
WorkflowManager workflowManager = (WorkflowManager) AppUtil.getApplicationContext().getBean("workflowManager");
AppService appService = (AppService) AppUtil.getApplicationContext().getBean("appService");
  
//get processDefId
WorkflowProcess processDef = appService.getWorkflowProcessForApp(appDef.getId(), appDef.getVersion().toString(), processDefKey);
String processDefId = processDef.getId();
 
//get foreign key
String batchId = "#form.gda_batch.id#";
 
Connection con = null;
 
try {
    // retrieve connection from the default datasource
    DataSource ds = (DataSource)AppUtil.getApplicationContext().getBean("setupDataSource");
    con = ds.getConnection();
   
    // execute SQL query
    if(!con.isClosed()) {
        PreparedStatement stmt = con.prepareStatement("SELECT * FROM app_fd_gda_travel WHERE c_batch = ?");
        stmt.setObject(1, batchId);
        ResultSet rs = stmt.executeQuery();
        while (rs.next()) {
            LogUtil.info(appDef.toString(), "Processing Batch " + batchId + " - Record: " + rs.getObject("id"));
            Map variables = new HashMap();
            //variables.put("batch", batchId);
            WorkflowProcessResult result = workflowManager.processStart(processDefId, null, variables, "admin", rs.getObject("id"), false);
            LogUtil.info(appDef.toString(), "Processing Batch " + batchId + " - Record: " + rs.getObject("id") + " - Status: " + result.getProcess().getInstanceId());
        }
    }
} catch(Exception e) {
    LogUtil.error(appDef.toString(), e, "Error in creating approval process for batch " + batchId);
} finally {
    //always close the connection after used
    try {
        if(con != null) {
            con.close();
        }
    } catch(SQLException e) {/* ignored */}
}

In the code you'll use LogUtil.info to log information. When you check the server log, you'll see output similar to the following example:

INFO 25 Jan 2021 12:18:43 {id=gridDataApproval, version=1, published=true} - Processing Batch 6f0abea4-bb36-4064-96d0-7c90ea9daed6 - Record: 1841e8e6-71b3-4388-84f8-0d39da7ee8ee
INFO 25 Jan 2021 12:18:43 org.joget.workflow.shark.WorkflowAssignmentManager - [processId=3639_gridDataApproval_travel_approver_process, processDefId=gridDataApproval#1#travel_approver_process, participantId=travel_approver, next user=[admin]]
INFO 25 Jan 2021 12:18:43 {id=gridDataApproval, version=1, published=true} - Processing Batch 6f0abea4-bb36-4064-96d0-7c90ea9daed6 - Record: 1841e8e6-71b3-4388-84f8-0d39da7ee8ee - Status: 3639_gridDataApproval_travel_approver_process
INFO 25 Jan 2021 12:18:43 {id=gridDataApproval, version=1, published=true} - Processing Batch 6f0abea4-bb36-4064-96d0-7c90ea9daed6 - Record: ba92fc7a-e477-431a-ba4e-8fe8e70cbf8b
INFO 25 Jan 2021 12:18:43 org.joget.workflow.shark.WorkflowAssignmentManager - [processId=3640_gridDataApproval_travel_approver_process, processDefId=gridDataApproval#1#travel_approver_process, participantId=travel_approver, next user=[admin]]
INFO 25 Jan 2021 12:18:43 {id=gridDataApproval, version=1, published=true} - Processing Batch 6f0abea4-bb36-4064-96d0-7c90ea9daed6 - Record: ba92fc7a-e477-431a-ba4e-8fe8e70cbf8b - Status: 3640_gridDataApproval_travel_approver_process

Once tested to be working, you may consider commenting them out to minimize unnecessary printouts to the server log.

Note:
This app's process is generated using Process Enhancement Plugin DX, but this is not mandatory or needed for this article.

Download sample app

Download the demo app for Start Process From Grid Data:
Created by Julieth Last modified by Aadrian on Dec 13, 2024