Joget DX 8 Stable Released
The stable release for Joget DX 8 is now available, with a focus on UX and Governance.
In this article, we will walkthough the thought process on designing a solution for the following business use case:-
Upon successful validation of data, the form data will be shared with external system (i.e. CRM software) for further processing through the use plugins (i.e. JSON Tool) or Bean Shell code. More on this later on.
This is an example on how the form would look like.
Figure 1
The only external factor that may be outside of the Joget platform's control would be the external integration with the CRM software. We will walkthrough a few scenarios on how best to design for this business use case with UI/UX kept in mind.
We will design the app and discuss where best to invoke the external API.
When end user hits on the Submit button, the following will take place.
With what we have learned so far, this can be presented using the following diagram.
Figure 8
There are many ways to do it. Here's a list.
The easiest, no-code approach is to make use of JSON Tool plugin itself. The JSON Tool itself is a Process Tool & Post Form Submission Processing Plugin. This means that we can invoke it from within a process flow or from submission of form.
We can also write Bean Shell code. Here's a quick sample code to make http get call.
import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import java.io.IOException; import org.joget.commons.util.LogUtil; try{ String jsonUrl = "http://localhost:8080/jw/web/json/workflow/assignment/list/count?packageId=crm"; String name = "header1"; String value = "value1"; CloseableHttpClient client = null; CloseableHttpClient client = HttpClients.createDefault(); HttpRequestBase request = null; request = new HttpGet(jsonUrl); request.setHeader(name, value); HttpResponse response = client.execute(request); } catch (Exception ex) { LogUtil.error(getClass().getName(), ex, ""); } finally { try { if (request != null) { request.releaseConnection(); } if (client != null) { client.close(); } } catch (IOException ex) { LogUtil.error(getClass().getName(), ex, ""); } }
We can execute this piece of code from various plugin types giving us the flexibility on where/when we want to invoke it. The only disadvantage compared to the former is that we need to maintain the custom coding ourselves instead of configuring through a plugin. These are the plugin types relevant to our solution to call the code from:-
We can only combine the both methods together by triggering the JSON process tool plugin in a beanshell code too. Here's a quick sample code written to be used in Bean Shell for Process Tool. Note that each plugin type would inject different variables for the Bean Shell code to consume.
import java.util.Map; import java.util.HashMap; import javax.servlet.http.HttpServletRequest; import org.joget.apps.app.model.AppDefinition; import org.joget.apps.app.service.AppPluginUtil; import org.joget.apps.app.service.AppUtil; import org.joget.plugin.base.ApplicationPlugin; import org.joget.plugin.base.Plugin; import org.joget.plugin.base.PluginManager; import org.joget.plugin.property.model.PropertyEditable; import org.joget.workflow.model.WorkflowAssignment; public Object execute(AppDefinition appDef, HttpServletRequest request, WorkflowAssignment workflowAssignment) { String jsonUrl = "http://localhost:8080/jw/web/json/workflow/assignment/list/count?packageId=crm"; //Reuse Email Tool to send separated email to a list of users; Plugin plugin = pluginManager.getPlugin("org.joget.apps.app.lib.JsonTool"); ApplicationPlugin jsonTool = (ApplicationPlugin) plugin; Map propertiesMap = new HashMap(); propertiesMap.put("pluginManager", pluginManager); propertiesMap.put("appDef", appDef); propertiesMap.put("request", request); propertiesMap.put("workflowAssignment", workflowAssignment); //configure json tool plugin propertiesMap.put("jsonUrl", jsonUrl); propertiesMap.put("requestType", ""); //empty is for GET call propertiesMap.put("multirowBaseObject", ""); propertiesMap.put("debugMode", ""); propertiesMap.put("formDefId", "request"); propertiesMap.put("headers", new Object[]{}); List fieldMappings = new ArrayList(); Map fieldMapping = new HashMap(); fieldMapping.put("jsonObjectName", "total"); fieldMapping.put("field", "day"); fieldMappings.add(fieldMapping); //repeat this code to add more row // fieldMapping = new HashMap(); // fieldMapping.put("jsonObjectName", "jsonAttrName"); // fieldMapping.put("field", "formFieldId"); // fieldMappings.add(fieldMapping); propertiesMap.put("fieldMapping", fieldMappings.toArray()); //set properties and execute the tool ((PropertyEditable) jsonTool).setProperties(propertiesMap); jsonTool.execute(propertiesMap); return null; } //call execute method with injected variable return execute(appDef, request, workflowAssignment);
By using Post Form Submission Processing in Form, and "Method 1 JSON Call" earlier, this is the easiest and quickest method. This allows us to invoke any Process Tool & Post Form Submission Processing Plugin. JSON Tool is one such candidate.
Figure 9
Depending on the feature of the API call, we would assume that it would return a response to indicate successful execution. For example:-
{ "success" : "true" }
This is to sum things up so far.
Summary | |
---|---|
Pros |
|
Cons |
|
Read on to see how we can improve.
To avoid the waiting time for JSON Tool to finish executing, we can place it under Multi Tools instead.
Figure 10
Set the "Run Mode" such that it would execute the process tool (JSON Tool) in a new thread.
Summary | |
---|---|
Pros |
|
Cons |
|
With what we have learned so far, there's still 1 con that we are trying to solve. Let's try to put the form within a process flow in a diagram as below.
Figure 11
By using a process flow, we can check the content of the returned JSON call to see if it matches the intended content. For example, we are expecting this reply and have it mapped to a workflow variable.
{ "success" : "true" }
By doing so, we would be able to redirect back to the same form again and prompting the end user to submit the form again. The potential customer (end user) may not be able to complete the submission process when the external API is not reliable and sees the same form repetitively. This would lead to confusing UI presentation and frustrating user experience.
Summary | |
---|---|
Pros |
|
Cons |
|