Skip to main content
Redhat Developers  Logo
  • Products

    Platforms

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat AI
      Red Hat AI
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • View All Red Hat Products

    Featured

    • Red Hat build of OpenJDK
    • Red Hat Developer Hub
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat OpenShift Local
    • Red Hat Developer Sandbox

      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Secure Development & Architectures

      • Security
      • Secure coding
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • Product Documentation
    • API Catalog
    • Legacy Documentation
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

Running an event-driven health management business process through end user scenarios: Part 2

April 14, 2020
Maurizio Carioli
Related topics:
JavaEvent-Driven

Share:

    If you read the first article in this series, then you already set up the example application you'll need for this article. If you have not set up the population health management application, you should do that before continuing. In this article, we'll run a few business processes through our event- and business-process-driven application to test it out.

    The happy-path scenario

    The most important thing you can learn from this article is how to wire the user interface (UI) together with the back end of a business application driven by a jBPM business process. Wiring these components together is not well-documented, and might take trial and error to get right.

    If you are a business-process developer, you can easily validate a business-process scenario by running it through jBPM Business Central. Doing that won't help you much if you are a UI developer, however, and need to build or customize a user-facing business application.

    In this case of the population health management application, the business process you developed drives one or possibly several applications where the end-user is a family doctor, pharmacist, or insurance agent. Each of them needs to access member records.

    Your task is to wire the front-end application used by each of these parties to a single business process running in the jBPM process server, also known as the KieServer. This server uses a REST API to expose a variety of operations. For the purpose of this article, calls to the KieServer REST API will use basic authentication. In real life, it is more likely that you would use a stronger authentication mechanism, such as OAuth implemented in Keycloak.

    For the remainder of this article, I will use the cURL command to demonstrate how to call a REST API from an example end-user application UI. The cURL command is available from both the Linux command-line interface (CLI) and a Windows PowerShell. The particular way that you call a REST API when you develop or customize the UI for end-user applications will vary.

    You can quickly get some basic information about the server by running:

    curl --user kieserver:secret \
    --location --request GET 'http://localhost:8080/kie-server/services/rest/server?Accept=application/json' \
    --header 'Accept: application/json'
    

    The response will be, for example:

    {
      "type": "SUCCESS",
      "msg": "Kie Server info",
      "result": {
        "kie-server-info": {
          "id": "sample-server",
          "version": "7.33.0.Final",
          "name": "sample-server",
          "location": "http://localhost:8080/kie-server/services/rest/server",
          "capabilities": [
            "KieServer",
            "BRM",
            "BPM",
            "CaseMgmt",
            "BPM-UI",
            "BRP",
            "DMN",
            "Swagger",
            "Prometheus"
          ],
          "messages": [
            {
              "severity": "INFO",
              "timestamp": {
                "java.util.Date": 1580476689750
              },
              "content": [
                "Server KieServerInfo{serverId='sample-server', version='7.33.0.Final', name='sample-server', location='http://localhost:8080/kie-server/services/rest/server', capabilities=[KieServer, BRM, BPM, CaseMgmt, BPM-UI, BRP, DMN, Swagger, Prometheus]', messages=null', mode=DEVELOPMENT}started successfully at Fri Jan 31 08:18:09 EST 2020"
              ]
            }
          ],
          "mode": "DEVELOPMENT"
        }
      }
    }
    

    Notice the list of the server's capabilities.

    Now, get the list of deployment units on this server (also known as Kie containers, which are not to be confused with OCS containers or Docker containers:

    curl --user kieserver:secret \
    --location --request GET 'http://localhost:8080/kie-server/services/rest/server/containers' \
    --header 'Accept: application/json'
    

    The responses are the PHM-Model and PHM-Processes containers:

    {
      "type": "SUCCESS",
      "msg": "List of created containers",
      "result": {
        "kie-containers": {
          "kie-container": [
            {
              "container-id": "PHM-Processes_1.0.0-SNAPSHOT",
              "release-id": {
                "group-id": "com.health-insurance",
                "artifact-id": "PHM-Processes",
                "version": "1.0.0-SNAPSHOT"
              },
              "resolved-release-id": {
                "group-id": "com.health-insurance",
                "artifact-id": "PHM-Processes",
                "version": "1.0.0-SNAPSHOT"
              },
              "status": "STARTED",
              "scanner": {
                "status": "DISPOSED",
                "poll-interval": null
              },
              "config-items": [
                {
                  "itemName": "KBase",
                  "itemValue": "",
                  "itemType": "BPM"
                },
                {
                  "itemName": "KSession",
                  "itemValue": "",
                  "itemType": "BPM"
                },
                {
                  "itemName": "MergeMode",
                  "itemValue": "MERGE_COLLECTIONS",
                  "itemType": "BPM"
                },
                {
                  "itemName": "RuntimeStrategy",
                  "itemValue": "PER_PROCESS_INSTANCE",
                  "itemType": "BPM"
                }
              ],
              "messages": [
                {
                  "severity": "INFO",
                  "timestamp": {
                    "java.util.Date": 1580477082631
                  },
                  "content": [
                    "Container PHM-Processes_1.0.0-SNAPSHOT successfully created with module com.health-insurance:PHM-Processes:1.0.0-SNAPSHOT."
                  ]
                }
              ],
              "container-alias": "PHM-Processes"
            },
            {
              "container-id": "PHM-Model_1.0.0-SNAPSHOT",
              "release-id": {
                "group-id": "com.health-insurance",
                "artifact-id": "PHM-Model",
                "version": "1.0.0-SNAPSHOT"
              },
              "resolved-release-id": {
                "group-id": "com.health-insurance",
                "artifact-id": "PHM-Model",
                "version": "1.0.0-SNAPSHOT"
              },
              "status": "STARTED",
              "scanner": {
                "status": "DISPOSED",
                "poll-interval": null
              },
              "config-items": [
                {
                  "itemName": "KBase",
                  "itemValue": "",
                  "itemType": "BPM"
                },
                {
                  "itemName": "KSession",
                  "itemValue": "",
                  "itemType": "BPM"
                },
                {
                  "itemName": "MergeMode",
                  "itemValue": "MERGE_COLLECTIONS",
                  "itemType": "BPM"
                },
                {
                  "itemName": "RuntimeStrategy",
                  "itemValue": "SINGLETON",
                  "itemType": "BPM"
                }
              ],
              "messages": [
                {
                  "severity": "INFO",
                  "timestamp": {
                    "java.util.Date": 1580476858851
                  },
                  "content": [
                    "Container PHM-Model_1.0.0-SNAPSHOT successfully created with module com.health-insurance:PHM-Model:1.0.0-SNAPSHOT."
                  ]
                }
              ],
              "container-alias": "PHM-Model"
            }
          ]
        }
      }
    }
    

    The response contains a lot of information for each Kie container but right now you only need the names. In the REST API calls to the PHM-Processes Kie container that follow, use the alias PHM-Processes. There is no need to use the full container id PHM-Processes_1.0.0-SNAPSHOT.

    Assume that a certain trigger for a given member is received on a data stream, like Apache Kafka, by the PHM business application's data integration layer. (In this case, the integration component is Apache Camel.) As shown in Figure 1, a Camel event-driven consumer is subscribed to a channel in the Kafka stream. Whenever a trigger event is received, Camel starts a Trigger process instance in jBPM.

    High level architecture of the PHM application.
    Figure 1: High level architecture of the PHM application.
    Figure 1: The PHM application's high-level architecture.">

    In my view, a BPM should orchestrate business activities such as human tasks, decision tasks, and services that are immediately ancillary to such business tasks. Data integration should not be the job of the BPM and is best left to tools specifically designed for that purpose. Let Camel do the heavy lifting and let jBPM focus on what is real business logic as opposed to technical data operations. The goal is to have a scalable, robust, agile PHM solution not cramming every function into one swiss-knife tool.

    Now, start the Trigger process. In real life, Camel will react to the trigger by starting the Trigger process in jBPM with the following REST API, where you only need to pass the member id and the trigger id:

    curl --user kieserver:secret \
    --location --request POST 'http://localhost:8080/kie-server/services/rest/server/containers/PHM-Processes/processes/PHM-Processes.Trigger/instances' \
    --header 'Content-Type: application/json' \
    --data-raw '{
         "pMemberId": "123",
         "pTriggerId": "R383"
    }'
    

    The response will be the process instance id.

    Now put your business process developer hat back on. Go to Business Central, find the Manage section, and click process instances, as shown in Figure 2.

    Business Central - Manage - process instances.
    Figure 9: Business Central - Manage - process instances.
    Figure 2: Go to Business Central to manage your process instances.">

    Here, you will see three process instances. In addition to the Trigger process instance, you will see the two Task process instances that do not have a predecessor (Figure 3).

    Business Central - Manage - Process instances
    Figure 10: Business Central - Manage - Process instances.

    Click on the Trigger process instance and look through the information available. If you are a business process developer, you will find the process diagram shown in Figure 4 useful when quickly debugging or testing. It shows where process execution is in a waiting state (red) and which activities or nodes have been completed (grey).

    Trigger process instance diagram
    Figure 12: Trigger process instance diagram.

    However, the most powerful tools available to test and debug jBPM business processes and Drools business rules are the event-listener interfaces. No process should be deployed without them—check out this printout of events captured by the custom event listeners at the start of the Trigger process.

    What is captured and how it is displayed is entirely up to you. Typically you would store this tracing data into a database so that you can easily extract reports from it when needed.

    Now, put your user interface developer hat back on. Peter is the family physician for the insurance member whose trigger is being processed. Peter has logged into the application on his office PC or perhaps on his smartphone or tablet. You need to know the tasks Peter is a potential owner of through the REST API:

    curl --user Peter:secret \
    --location --request GET 'http://localhost:8080/kie-server/services/rest/server/containers/PHM-Processes/forms/tasks/1?lang=en&type=ANY&marshallContent=true' \
    --header 'Accept: application/json'
    

    Since you are building a custom UI (or integrating with an already existing UI) you don't need most of the information in the response. What you need is just the list of variables submitted by the form:

                "properties": [
                    {
                        "name": "answer",
                        "typeInfo": {
                            "type": "BASE",
                            "className": "java.lang.String",
                            "multiple": false
                        },
                        "metaData": {
                            "entries": []
                        }
                    },
                    {
                        "name": "na",
                        "typeInfo": {
                            "type": "BASE",
                            "className": "java.lang.Boolean",
                            "multiple": false
                        },
                        "metaData": {
                            "entries": []
                        }
                    },
                    {
                        "name": "naText",
                        "typeInfo": {
                            "type": "BASE",
                            "className": "java.lang.String",
                            "multiple": false
                        },
                        "metaData": {
                            "entries": []
                        }
                    }
                ]
    

    Then, you can submit the variables' values by first defining the task's output with this REST API, where (as an example) you only submit the answer variable:

    curl --user Peter:secret \
    --location --request PUT 'http://localhost:8080/kie-server/services/rest/server/containers/PHM-Processes/tasks/1/contents/output' \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --data-raw '{
    	"answer": "Hello."
    }'
    

    Then complete the task with the REST API:

    curl --user Peter:secret \
    --location --request PUT 'http://localhost:8080/kie-server/services/rest/server/containers/PHM-Processes/tasks/1/states/completed' \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --data-raw ''
    

    Peter's task needs to be hard-closed. That is, according to our customer requirements, merely completing the task within the BPM system is not sufficient to consider the task closed. A signal from an external system must be received to actually close the task. The external system must be programmed to use the following REST API to send the appropriate signal:

    curl --user externalsystem:secret \
    --location --request POST 'http://localhost:8080/kie-server/services/rest/server/containers/PHM-Processes/processes/instances/4/signal/hard_close' \
    --header 'Content-Type: application/json' \
    --data-raw '{}'
    

    Hard closing Peter's task will start two more task processes that have Peter's task as the predecessor. The other actors in the scenario are the insurance member Mary, the pharmacist Robert, and the insurance channel worker Charlie.

    You can repeat the steps that you followed by playing Peter for each of the other actors. I will not describe these steps for you here. Bear in mind that according to the data provided by the Get the Data service, only Charlie's task requires hard-closing. The other two tasks can be soft-closed, they do not need a signal from an external system to be considered closed.

    This completes the "Happy Path Scenario."

    The reminder scenario

    In this scenario, Charlie fails to take action within the period of time passed in the attribute Task. A reminderInitiation and a reminder email is sent as a result. In fact, an email should be sent with a frequency given by the attribute Task.reminderFrequency. The Task object with all its attributes is provided for each task by the Get the Data service. The email should stop after the task is completed.

    The email is sent by a custom work item handler. In the PHM-Processes project's deployment descriptor, you can see that the parameters of EmailWorkItemHandler are system environment variables:

    This is because you don't want the email server credentials to be written there for security reasons. You have to set the system environment variables DEMO_SMTP_SERVER, DEMO_SMTP_PORT, DEMO_SMTP_USER, and DEMO_SMTP_PWD to the corresponding values for the email server that you will be using. For example, you could use a mock server such as mailtrap.io.

    Now, go to the REST API project that provides the mock Get the Data service, open the app.js file, find the data for Charlie's task, and change the value of the attributes reminderInitiation and reminderFrequency to the values below:

        {
          task: {
            id: 58,
            origId: 'B143',
            suppressed: false,
            suppressionPeriod: '',
            expirationDate: '2020-12-31T12:00:00.000Z',
            close: 'HARD',
            reminderInitiation: 'PT60S',
            reminderFrequency: 'R/PT60S',
            escalationTimer: 'P90D',
            description: 'Getting Community Info'
          },
          assignment: {
            actor: 'Charlie',
            channel: 'CCN',
            escalationActor: 'Marc',
            escalationChannel: 'CCN'
          },
          reminder: {
            address: 'charlie@healthinsurance.com',
            body: 'XYZ',
            from: 'PHM@healthinsurance.com',
            subject: 'Reminder'
          }
        }
    

    The initial period of time is now 60 seconds instead of 15 days, and the frequency is 60 seconds instead of 15 days. This configuration will make it easier to test that the reminder is being sent. If you don't like these values just use whatever suits you.

    After a few minutes, Charlie's email inbox will be full of reminder messages as shown in Figure 5.

    Charlie's email inbox
    Figure 5: Charlie's email inbox.
    Figure 5: The results in Charlie's email inbox.

    Now have Charlie complete the task and check that the email barrage has stopped. Of course, you might as well follow what happens in Business Central updating the diagrams of Charlie's Task and Reminder subprocesses.

    The escalation scenario

    By now, you should know how to run this scenario. Just change the escalation timer value to 60 seconds and see what happens. Bear in mind that this scenario depends on a task hard close and not on task completion, like the previous scenario.

    Conclusions

    By now, hopefully, you should have gained a solid understanding of how the example business process works, learned how to validate whether your implementation is correct or not, and learned how to wire the business application's user interface driven by the business process.

    Last updated: June 29, 2020

    Recent Posts

    • Cloud bursting with confidential containers on OpenShift

    • Reach native speed with MacOS llama.cpp container inference

    • A deep dive into Apache Kafka's KRaft protocol

    • Staying ahead of artificial intelligence threats

    • Strengthen privacy and security with encrypted DNS in RHEL

    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Products

    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2025 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue