You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 13 Next »

Problem Statement

In this article, we will walkthough the thought process on designing a solution for the following business use case:-

  1. Visitor would request for demo by submitting a form in the Joget app.
  2. Upon submission of the form, fields will be validated to make sure that all mandatory fields are filled up.
  3. 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.

  4. The main objective is to ensure successful delivery of data with the external system.

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.

Designing Solution

We will design the app and discuss where best to invoke the external API.

Preparing the Form and Userview

  1. We will start with desiging the form itself. The form itself is quite simple, with just 3 fields and all of them made mandatroy.

    Figure 2

  2. In the userview, we are making use of the Form Menu and link it to the form we have just designed.

    Figure 3

    Configure "Action to Perform After Form Saved" to redirect to a "HTML Page" to show form submitted message (e.g. Form submitted. Thank you!).

  3. Do not forget to create a CRUD menu too so that we can browse through all the submissions easily using Generate CRUD.

    Figure 4

  4. At this point of time, there's no integration yet with the external CRM.

What Happens on Form Submission?

When end user hits on the Submit button, the following will take place.

  1. Form Validation - Joget would iterate through each and every form element and invoking the validator (if configured).

    Figure 5

    If all validations pass, then it will move to the next step, else, end user will be redirected back to the same form with validation errors displayed like what is shown in the screenshot below.

    Figure 6

  2. Form Store - Since validations have passed, Joget will now proceed to the next step, form data will be passed to the store binder.

    Figure 7

    By default, the load/store binder is Workflow Form Binder where it will load and store form data into the table name declared in the form properties. In this case, the table name is "demo_request".
  3. Since we are using Workflow Form Binder, this would also mean that we are saving the form data locally in Joget's database.

With what we have learned so far, this can be presented using the following diagram.


Figure 8

Invoke Restful API Call

There are many ways to do it. Here's a list.

Method 1 - JSON Tool

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.

Method 2 - Bean Shell Code

  1. We can also write Bean Shell code. Here's a quick sample code to make http get call.

    Bean Shell code to make restful API calls sample
    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:-

    1. Bean Shell for Process Tool
    2. Bean Shell Validator
    3. Bean Shell Form Binder 


Method 3 - JSON Tool from Bean Shell Code

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. 

Call JSON Tool plugin from Bean Shell code
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);

Possible Integration Points to Invoke Restful API Call

Method 1 - Post Form Submission Processing and JSON Tool

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 PluginJSON Tool is one such candidate.

Figure 9

  • Upon form submission, form fields will be validated, with its form data stored, then, the "Post Form Submission Processing" will be triggered.
  • Response time of form submission will now include complete execution of the JSON Tool.
  • Imagine that the external JSON API takes longer than expected to respond, the end user will be kept waiting.
  • Depending on the feature of the API call, we would assume that it would return a response to indicate successful execution. For example:-

    Sample JSON Call Response
    { "success" : "true" }
  • By using this integration point, there's no way to redirect the user to other place/menu when error occurs.

This is to sum things up so far.


Summary
Pros
  1. Quickest
  2. Easiest to Configure
Cons
  1. Increased wait time. Response time includes JSON Tool's turnaround time.
  2. No guarantee of successful JSON call to external system.

Read on to see how we can improve.

Method 2 - Post Form Submission Processing and JSON Tool with Multi Tools

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
  1. Quickest
  2. Easiest to Configure
Cons
  1. No guarantee of successful JSON call to external system.

Method 3 - Workflow Process with JSON Tool

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.

Sample JSON Call Response
{ "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.

As this design expects a "true/false" response from the JSON Tool itself, when the external API service is unresponsive, it may not even return anything at all and we will need to wait for it to time out by itself (i.e. 60 seconds).


Summary
Pros
  1. Handles JSON call error and prompt user to submit again to try
Cons
  1. Increased wait time. Response time includes JSON Tool's turnaround time.
  2. Form submission only work end to end when external API service is working.

Method 4 - Form Validator and Form Store Binder

Triggering the JSON call from these 2 plugin types are not feasible but we will explain as part of knowledge sharing.

As the JSON Tool plugin is not a form validator nor form store binder type of plugin, we will need to use the workaround shared earlier, which is writing the bean shell code from scratch or calling the JSON Tool plugin programmatically.

Why Form Validator?

Form Validator Plugin expects a true/false to be returned. We may try to avoid the need of designing a process flow and achieve the same JSON result checking by making the JSON call through the validator plugin. The problem that would arise from this appraoch are:-

  1. Same form content may get submitted repetitively as other form fields' validators may kick in too (i.e. mandatory field checking).
  2. If the external API system becomes unresponsive, the Joget app will stop working.
  3. Increased wait time. Response time includes JSON Tool's turnaround time.

Why Form Store Binder?

To avoid calling the API repetitively, let's move down to the next layer, store binder.

By calling the JSON API within the Form Store Binder Plugin, we will need to explore on how to handle events such as when JSON API is not being responsive. In this type of plugin, it won't be expecting a true/false to be returned like the validator plugin though.

We can try to throw an exception instead in the Bean Shell code that we are writing.

Figure 12

This approach suffers from the following issues:-

  1. If the external API system becomes unresponsive, the Joget app will stop working.
  2. Error message is not friendly.
  3. Increased wait time. Response time includes JSON Tool's turnaround time.

Method 5






  • No labels