Overview of Workflow Customizations

Define a new business process and/or create custom JAR files, to customize a workflow.

Define a New Business Process

For more information, see the Workflow Web-based Modeller.

Create Custom JAR Files

This section contains information about the requirements, resources, and steps for creating custom JAR files.

Required Resources
  • Java 8 is required if you want to create your own action, listener, or validator classes that will be packed in a JAR file.
  • The Workflow Service Public Repository helps you to create the customizations. Use the Out-of-the-box (OOTB) process definitions which are available on every tenant. For more information, see Workflow Service Public Repository.

Custom Workflow

There are two main types of tasks that are used in the workflow:
  1. User tasks
  2. Service tasks

User tasks represent steps in the workflow that will show up in the Inbox and require a user's action, such as data validation or profile approval.

Service tasks are steps in the workflow that are not displayed in the UI and do some programmatic action. These steps invoke a Java class that is written to do actions. Examples of such actions are deleting a profile, merging profiles, or editing attributes.

Roles and Security

Roles

Workflow requires users to have the workflow user role (ROLE_WORKFLOW) enabled.

All workflows are public, but if you are a workflow assignee you can take action on a workflow. Workflows can be applied to Profiles and Potential Matches. You can configure the workflow owner and assignee to receive email notifications on when tasks are assigned, approved, or rejected.

Workflow Management

You can use the Workflow Web-based Modeler to define and modify the business processes. You can import an existing BPMN XML file or create process definitions through the Workflow Web-based Modeler user interface and deploy the process definition to a specific tenant.

Workflow Service Public Repository

The Workflow Service Public Repository is available at: https://bitbucket.org/reltio-ondemand/workflow. This repository contains the following items:

  • Public API for Workflow Custom JARs
  • Source code of default Reltio service task delegates (Approve Change Request, Delete Entity, etc.)
  • Default process definitions that are available on every tenant
  • Samples of new/customized process definitions with Java source code of additional classes

Review the Readme files in the repository for information about using these resources.

Creating Custom JAR Files - Steps

To create custom JAR files:

  1. Customize the Listener.
    1. Create a new Java file. For example, CustomTaskStartEventListener.java.
    2. Implement the WorkflowTaskListener interface to create listeners of specific user tasks.
    3. Implement the WorkflowExecutionListener interface to create listeners of specific service tasks. Examples of implementations can be found in the workflow-custom folder of the Workflow Service Public Repository.

      Business Process Model and Notation (BPMN), which is the standard language for process applications. For more information, see Business Process Model and Notation

    4. Open the BPMN diagram in Workflow Modeler. For more information, see the Workflow Web-based Modeler.
    5. Change the classpath of the listener implementation. Select a task to be modified, open the Listeners tab, and edit the Java Class attribute value:

      Example:

      <userTask> 
          ... 
              <activiti:taskListener event="create" class="com.reltio.workflow.activiti.service.CustomTaskStartEventListener">
          ...
      </userTask>
    6. Publish the updated BPMN diagram.
  2. Customize the validator.
    1. Create a new Java file (for example CustomPotentialMatchTaskValidator.java). You can create a new file from a copy of one of the example validator files.
    2. Open the BPMN diagram in the Workflow Modeler. (See the Workflow Web-based Modeler topic for more information .)
    3. Change the classpath of the validator implementation. Select a task to be modified, open the Form tab, and edit the Default Value of the Validator form field.
      Example:
      <userTask>
       ...
        <activiti:formProperty id="validator" name="Validator" type="string" writable="false" 
      default="com.reltio.workflow.activiti.service.validator.CustomPotentialMatchTaskValidator">
      ...
      </userTask>
    4. Publish the updated BPMN diagram. For details see Workflow Configuration Guide.

      Example

      By default, PotentialMatchTaskValidator service task logs errors and info messages using the Logger mechanism. Suppose we need to get log info output also to the console. For this purpose, we create a new Java class (e.g. CustomPotentialMatchTaskValidator) as a copy of the out-of-the-box class PotentialMatchTaskValidator. In the CustomPotentialMatchTaskValidator class, we add SOUT statements for errors and info messages:
      
      <scope>provided</scope>
      public boolean doValidate(TaskValidationInfo taskInfo) throws InvalidTaskException 
      {
        ("Validating task with objectURIs "+taskInfo.getObjectUris()); // Customization (SOUT statement added)
        if (isCoupleOfObjectUris(taskInfo.getObjectUris())) {
          boolean isMerged = false;
          //Check if already merged
          try {
            isMerged = isAlreadyMerged(taskInfo);
          } catch (InvalidUriException ex) {
            logger.error(ex.getMessage(), ex);
            throw new InvalidTaskException(ex.getMessage());
          } catch (ReltioInvalidRequestException ex) {
            logger.error(ex.getMessage(), ex);              
            throw new InvalidTaskException("Invalid task as object uris is invalid: " + taskInfo.getObjectUris());
          }
          if (isMerged) 
           {
            ("Invalid Task"); // Customization (SOUT statement added)
            logger.info("Invalid task as the entities are already merged: " + taskInfo.getObjectUris());
            throw new InvalidTaskException("Invalid task as the entities are already merged: " + taskInfo.getObjectUris());
          }
        } else 
         {
          ("Invalid Task"); // Customization (SOUT statement added)
          logger.info("Invalid task as there are not 2 uris : " + taskInfo.getObjectUris());
          throw new InvalidTaskException("Invalid task as there are not 2 uris : " + taskInfo.getObjectUris());
        }
        ("Valid Task"); // Customization (SOUT statement added)
        return true;
      }

      Result:

      In CustomPotentialMatchTaskValidator, the logging mechanism is extended with log info output to the console.

  3. Customize the service task.
    1. Create a new Java file (for example, CustomDeleteInsteadOfMerge.java) for custom Service Task implementation. Out-of-the-box service task implementations are:
    2. Build a JAR file.
    3. Deploy the JAR file. For details see Custom JAR Deployment.
    4. Open the BPMN diagram in the Workflow Modeler.
    5. Change the classpath of the service task implementation. Select the service task to be modified, open the Main config tab, and edit the Java Class field value.
      Example:
      <serviceTask id="MergeService" 
                  name="Merge Service" 
                  activiti:class="com.reltio.workflow.activiti.service.CustomDeleteInsteadOfMerge">
      </serviceTask>
    6. Publish the updated BPMN diagram.

      Example:

      By default, the Merge service task merges two entities by their objectURIs. If we need a service task that will delete both such entities, we create a new Java class (for example: CustomDeleteInsteadOfMerge) as a copy of the out-of-the-box class Merge. In the Merge class, we get two entities and merge them using the POST {TenantURL}/{entityURI1}/sameAs?URI='{entityURI2}' API:
      
      <scope>provided</scope>
      String objectUrisStr = (String) delegateExecution.getEngineServices().getRuntimeService().getVariable(delegateExecution.getProcessInstanceId(), Constants.OBJECTURIS);
      List<String> objectURIs = Arrays.asList(StringUtils.split(objectUrisStr,","));
      String entityURI1 = objectURIs.get(0);
      String entityURI2 = objectURIs.get(1);
       
      // Merging entities
      String url = Utility.generateTenantUrl(EnvironmentURL,tenantId) + "/" + entityURI1 + "/sameAs?URI=" + entityURI2;
      logger.debug(url);
      String responseJson = reltioService.invokeApi(accessToken, url, Constants.POST, "");
      ObjectMapper objectMapper = new ObjectMapper();
      Map<String,String> responseMap = objectMapper.readValue(responseJson, Map.class);
      if(responseMap.containsKey("severity")) {
        logger.error((String) responseMap.get("errorMessage"));
        // throw new Exception((String) responseMap.get("errorMessage"));
        throw new Exception(responseJson);
        } logger.debug(responseJson);
      In the new CustomDeleteInsteadOfMerge class, we get two entities and delete them one by one using the DELETE {TenantURL}/{entity object URI} API:
      
      <scope>provided</scope>
      String objectUrisStr = (String) delegateExecution.getEngineServices().getRuntimeService().getVariable(delegateExecution.getProcessInstanceId(), Constants.OBJECTURIS);
      List<String> objectURIs = Arrays.asList(StringUtils.split(objectUrisStr,","));
      String entityURI1 = objectURIs.get(0);
      String entityURI2 = objectURIs.get(1);
       
      //Deleting entities
      for(String objectURI: objectURIs){
        String url = EnvironmentURL+"/reltio/api/" + tenantId + "/" + objectURI;
        String responseJson = reltioService.invokeApi(accessToken,url,Constants.DELETE,"");
        ObjectMapper objectMapper = new ObjectMapper();
        ReltioResponse reltioResponse = objectMapper.readValue(responseJson, ReltioResponse.class);
        if(reltioResponse.getStatus()==null || !reltioResponse.getStatus().equals(Constants.SUCCESS)) {
          logger.error(reltioResponse.getErrorCode().toString() + ": "+reltioResponse.getErrorMessage());
          // throw new Exception(reltioResponse.getErrorCode().toString() + ": "+reltioResponse.getErrorMessage());
          throw new Exception(responseJson);
        }
      }

      Result:

      In CustomDeleteInsteadOfMerge, the logic is now customized so that the two entities are deleted one by one (instead of being merged, as in Merge).

  4. Ensure that the Unit/Integration tests cover at least 70% of your code.
  5. Ensure that your JAR file does not contain unused code.
  6. Build a JAR file with all the shaded dependencies (any 3rd party libraries) except the workflow SDK, included in it. For more information on shaded dependencies, see http://maven.apache.org/plugins/maven-shade-plugin/examples/includes-excludes.html.
  7. Request a review of the JAR file by the Reltio Engineering team. You need to provide the JAR file, BPMN file, and logs from local debugging for the review. The logs from local debugging is usually found in C:\Users\username\Downloads\apache-tomcat-9.0.31\apache-tomcat-9.0.31\logs.
    Note: The review process takes 1 business day and usually, only 1 round of review is required. Please plan the deployment schedule accordingly.
  8. Deploy the JAR file. For details see Custom JAR Deployment.

Perform Local Debugging

Customers and partners developing custom Java classes for listeners, validators, and service tasks can benefit from the capability to debug Workflow Adapter custom classes on a local machine with the Hub running in the Reltio Connected Cloud. This section contains information about how to enable local debugging and information about how to debug a custom listener class locally.

Enabling Local Debugging

To enable local debugging, you must configure the environment to set up the Workflow Adapter locally.

For more information, see Setting Up the Reltio Workflow Adapter. After you configure the environment, you can perform local debugging through the UI or through the API.

API

You can perform local debugging through Workflow API requests executed against the locally installed Workflow Adapter. For more information, see the Workflow API.

User Interface (UI)

You can perform local debugging through the UI configured to work with the locally installed Workflow Adapter. Complete the following steps to enable local debugging through the UI.

  1. Set up HTTPS on the local machine.
  2. Complete the following steps to configure the path to the Workflow Adapter in the UI configuration per tenant to work with the Workflow Adapter on the local machine.
    1. Navigate to https://bitbucket.org/reltio-ondemand/reltio-ui-configuration/src.
    2. Drill down to folder {Environment}/plugins{TenantFolder}.
      Note: The TenantFolder can be found in the {Environment}/tenants.json by {TenantID}, "folder" field value.
    3. In com.reltio.plugins.workflow.json, specify a local path for workflowPath.

      Example:

      {
         ...
          "extensions": [
              {
                  "point": "com.reltio.plugins.ui.configuration",
                  "id": "com.reltio.plugins.workflow.configuration",
                  "workflowPath": "https://localhost:8080",
                  "stepsColors" :{
                  },
                  "enabled": true
              },
             ...
          ]
      }
    Note: Because the Hub requires HTTPS for connections, make sure the path contains https://. Ensure that you have the HTTPS protocol enabled on your local machine. Be aware that this change of UI configuration will affect all other customers of the UI for the tenant.
  3. Verify that the Hub is configured with the localhost. In your browser, open a network activity monitoring tool (for example, in Google Chrome which is available in Developer Tools > Network) and find the Request URL value for Workflow.

    Example:

    Example: Debugging a Custom Listener Class Locally

    In this example, we are going to create a custom listener and debug it on a local machine. Suppose we have a Delete Profile Review Workflow and a user task assigned as illustrated in the figure below:

    When a task reviewer changes the assignee (for example reassigns the task to another user), the Listener on assignment of task can send out an email notification. The out-of-the-box implementation of this listener TaskAssignmentEventListener sends an email notification to the new assignee.

Local Debugging Process

  1. In your Java IDE, open the Workflow project, go to Java sources (bpms > activiti > src > main > java) and open TaskAssignmentEventListener.java (classpath: com.reltio.workflow.activiti.service.TaskAssignmentEventListener).
  2. Set a breakpoint on taskAssignmentEvent (notice the breakpoint icon in the gutter area of the editor) and run the application.

  3. In the Hub, reassign the Recommend for Delete task to a different user.
  4. In the IDE, wait for the breakpoint hit. If the execution continues, we will observe the out-of-the-box behavior, such as an email notification sent to the assignee.
  5. Stop the application.
  6. Edit TaskAssignmentEventListener.java and add taskAssignmentEvent2 where email notification addressee is owner.

  7. Run the application.
    Note: It may take about one minute for the application to restart.
  8. In the Hub, reassign the Recommend for Delete task to a different user.
  9. In the IDE, wait for the breakpoint hit. When the breakpoint is hit, continue execution.
  10. Check the mailboxes of the assignee and task owner to verify that they both have received the email notification.

Related Video