JBPM is a flexible Business Process Management (BPM) Suite. It is lightweight, fully open-source and written in Java. It allows to model, execute, and monitor business processes throughout their life cycle.
Recently I started prototyping the idea of using it as a solution to meet the workflow needs of a proprietary application. Ultimately, my plan is to build a Docker image to hold the jBPM application, which will act as a black box responding to RESTful API calls from my core application.
Without getting into the sensitive information for my application, for this article, I am going to use the jBPM Workbench Showcase Docker image provided by JBoss. Once a container is started from this image, a demo environment can be used to get a feel of how jBPM functions.
The Sample Process Flow: Human Resources Example
Most corporate employees are familiar with the hiring process. So, which employees, Departments and Systems are required to Hire a new Developer in your company? Trying to answering these questions will help us to define your business process. The following figure, represents how does this process works for a company. We can clearly see that three Departments are involved: Human Resources, IT and Accounting teams are involved. When we look at the process flow, it appears as shown below:
The process diagram is self explanatory, but just in case and to avoid confusions this is what is supposed to happen for each instance of the process that is started a particular candidate:
- The Human Resources Team perform the initial interview to the candidate to see if he/she fits the profile that the company is looking for.
- The IT Department perform a technical interview to evaluate the candidate skills and experience.
- Based on output of the Human Resources and IT teams, the accounting team create a Job Proposal which includes the yearly salary for the candidate. The proposal is created based on the output of both of the interviews (Human Resources and Technical).
- As soon as the proposal has being created it is automatically sent to the candidate via email.
If the candidate accept the proposal, a new meeting is created with someone from the Human Resource team to sign the contract.
- If everything goes well, as soon as the process is notified that the candidate was hired, the system will automatically post a tweet about the new Hire using the twitter service connector.
As you can see Jack, John and Katy will be performing the tasks for this example instance of the business process, but any person inside the company that have those Roles will be able to claim and interact with those tasks.
Starting the process
At the highest level, a Process Model is created, like below:
Once the model is ready, the model is versioned and deployed. Process Models contain versions, so that the instances of that model can be tracked back to a given state or point in time.
The deployed flow is referred to as a Process Definition. From there, Process Instances can be created and the workflow steps become Tasks within jBPM.
To put things into perspective with our example, the Process Model (shown above) was deployed as a Process Flow called Hiring with a version of 1.0. In jBPM, the deployment is referred to as org.jbpm:HR:1.0. Below, is a screenshot from the jBPM Workbench:
If desired, the following RESTful API call could have been used to perform the deployment:
With the Process Definition in place, the application server is ready to create Process Instances. If the admin user started a process to hire Marc, the following API call would be executed:
Performing Tasks Via The RESTful API
The use of the RESTful API allows the jBPM server to act as a black box. Meaning, the application server can process workflow events from an external source without the need to maintain knowledge of the inner workings. This way, the main application doesn't have to include the workflow engine logic, it merely needs to have the ability to interact to jBPM through API calls.
As our Process is in a wait state now, we can check the Task list to see Tasks with the following
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <task-summary-list-response> <task-summary> <id>5</id> <name>HR Interview</name> <subject>Candidate: Marc</subject> <description>Candidate: Marc</description> <status>Ready</status> <priority>0</priority> <skipable>true</skipable> <created-on>2017-06-04T20:53:16.190Z</created-on> <activation-time>2017-06-04T20:53:16.190Z</activation-time> <process-instance-id>2</process-instance-id> <process-id>hiring</process-id> <process-session-id>2</process-session-id> <deployment-id>org.jbpm:HR:1.0</deployment-id> <quick-task-summary>false</quick-task-summary> <parent-id>-1</parent-id> </task-summary> </task-summary-list-response>
If the Task is assigned to a Group (which is the case for us), we would need to claim it at first:
which will return:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <response> <status>SUCCESS</status> <url>/jbpm-console/rest/task/5/claim</url> </response>
After that, we just need to start it:
Here is the response:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <response> <status>SUCCESS</status> <url>/jbpm-console/rest/task/5/start</url> </response>
Now the Task has been started and you can check it also from the Web console:
Last step will be completing the Task. Just as for the Start Process, we can pass a Map of attributes to the complete action:
This will return:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <response> <status>SUCCESS</status> <url>/jbpm-console/rest/task/5/complete</url> </response>
Great, now the HR department completed it task (HR interview), and now is time for the IT interview, accounting and so on ... the workflow is pretty much the same to claim, start and complete tasks for each department. you can play with if you've tine.
Once you complete the process, you can still query for information about your processes through the "history" REST calls. For example, to return the list of all process instances history records here is the GET you need:
If you need the process history records for a particular instance then you can issue the following: