🧩 Ensure Approver Roles Stay Unique in Joget (BeanShell Validator)

java dev.to

1. Why This Matters

If the same user is selected for multiple approval roles, approvals lose segregation and audits become weak.

This validator blocks duplicate user selections at form submission time.

2. Where to Use in Joget

  • Form Builder: add this as a Custom Validator on each approver-related field.
  • Suitable fields: dropdown, select box, or user picker fields storing usernames.
  • Not for Workflow Builder or API Builder: this is pre-submission form validation.

3. Configuration You Must Set

Update these field IDs to match your form:

  • reviewer
  • authorizer
  • approver

Attach the same validator script to each of these fields so each selected value is checked against the other roles.

4. Production-Ready Validator Code

import org.joget.apps.form.model.Element;
import org.joget.apps.form.model.Form;
import org.joget.apps.form.model.FormData;
import org.joget.apps.form.service.FormUtil;
import java.util.Arrays;

public boolean validate(Element element, FormData formData, String[] values) {
    try {
        String reviewerFieldName = "reviewer";
        String authorizerFieldName = "Authorizer";
        String approverFieldName = "Approver";

        Form form = FormUtil.findRootForm(element);

        Element reviewerElement = FormUtil.findElement(reviewerFieldName, form, formData);
        Element authorizerElement = FormUtil.findElement(authorizerFieldName, form, formData);
        Element approverElement = FormUtil.findElement(approverFieldName, form, formData);

        if (values != null && reviewerElement != null && authorizerElement != null && approverElement != null) {
            String[] reviewerValues = FormUtil.getElementPropertyValues(reviewerElement, formData);
            String[] authorizerValues = FormUtil.getElementPropertyValues(authorizerElement, formData);
            String[] approverValues = FormUtil.getElementPropertyValues(approverElement, formData);

            String elementId = FormUtil.getElementParameterName(element);
            String selectedValue = values[0];

            if (selectedValue == null || selectedValue.trim().isEmpty()) {
                formData.addFormError(elementId, "Approver cannot be blank");
                return false;
            }

            if (selectedValue.equals(reviewerValues[0])
                    || Arrays.asList(authorizerValues).contains(selectedValue)
                    || selectedValue.equals(approverValues[0])) {
                formData.addFormError(elementId, "Approver must be unique");
                return false;
            }
        } else {
            return false;
        }

        return true;
    } catch (Exception e) {
        return false;
    }
}

return validate(element, formData, values);
Enter fullscreen mode Exit fullscreen mode

5. Quick Validation Checklist

  • Select the same user in two roles: form must fail with duplicate error.
  • Select different users across roles: form must submit.
  • Leave a required role empty: form must show empty-field error.

6. Security and Publishing Note

  • Keep sample field IDs generic when sharing publicly.
  • Do not publish real usernames, emails, internal group names, or environment-specific IDs.

7. Final Note

This validator is small but high impact: it enforces role separation before workflow execution and prevents approval design mistakes early.

Follow-up topic: Dynamic multi-level approver uniqueness (including grid or multi-select fields).

Source: dev.to

arrow_back Back to Tutorials