Getting Started
Introduction and getting started with jBPM
1. Overview
1.1. What is jBPM?
jBPM is a flexible Business Process Management (BPM) Suite. It is light-weight, fully open-source (distributed under Apache License 2.0) and written in Java. It allows you to model, execute, and monitor business processes and cases throughout their life cycle.
A business process allows you to model your business goals by describing the steps that need to be executed to achieve those goals, and the order of those goals is depicted using a flow chart. This process greatly improves the visibility and agility of your business logic. jBPM focuses on executable business processes, which are business processes that contain enough detail so they can actually be executed on a BPM jBPM engine. Executable business processes bridge the gap between business users and developers as they are higher-level and use domain-specific concepts that are understood by business users but can also be executed directly.
Business processes need to be supported throughout their entire life cycle: authoring, deployment, process management and task lists, and dashboards and reporting.
The core of jBPM is a light-weight, extensible workflow engine written in pure Java that allows you to execute business processes using the latest BPMN 2.0 specification. It can run in any Java environment, embedded in your application or as a service.
On top of the jBPM engine, a lot of features and tools are offered to support business processes throughout their entire life cycle:
-
Pluggable human task service based on WS-HumanTask for including tasks that need to be performed by human actors.
-
Pluggable persistence and transactions (based on JPA / JTA).
-
Case management capabilities added to the jBPM engine to support more adaptive and flexible use cases
-
Web-based process designer to support the graphical creation and simulation of your business processes (drag and drop).
-
Web-based data modeler and form modeler to support the creation of data models and task forms
-
Web-based, customizable dashboards and reporting
-
All combined in one web-based Business Central application, supporting the complete BPM life cycle:
-
Modeling and deployment - author your processes, rules, data models, forms and other assets
-
Execution - execute processes, tasks, rules and events on the core runtime engine
-
Runtime Management - work on assigned task, manage process instances, etc
-
Reporting - keep track of the execution using Business Activity Monitoring capabilities
-
-
Eclipse-based developer tools to support the modeling, testing and debugging of processes
-
Remote API to jBPM engine as a service (REST, JMS, Remote Java API)
-
Integration with Maven, Spring, OSGi, etc.
BPM creates the bridge between business analysts, developers and end users by offering process management features and tools in a way that both business users and developers like. Domain-specific nodes can be plugged into the palette, making the processes more easily understood by business users.
jBPM supports case management by offering more advanced features to support adaptive and dynamic processes that require flexibility to model complex, real-life situations that cannot easily be described using a rigid process. We bring control back to the end users by allowing them to control which parts of the process should be executed; this allows dynamic deviation from the process.
jBPM is not just an isolated jBPM engine. Complex business logic can be modeled as a combination of business processes with business rules and complex event processing. jBPM can be combined with the Drools project to support one unified environment that integrates these paradigms where you model your business logic as a combination of processes, rules and events.
1.2. Overview of jBPM
This figure gives an overview of the different components of the jBPM project.
-
The core engine is the heart of the project and allows you to execute business processes in a flexible manner. It is a pure Java component that you can choose to embed as part of your application or deploy it as a service and connect to it through the web-based UI or remote APIs.
-
An optional core service is the human task service that will take care of the human task life cycle if human actors participate in the process.
-
Another optional core service is runtime persistence; this will persist the state of all your process instances and log audit information about everything that is happening at runtime.
-
Applications can connect to the core engine through its Java API or as a set of CDI services, but also remotely through a REST and JMS API.
-
-
Web-based tools allow you to model, simulate and deploy your processes and other related artifacts (like data models, forms, rules, etc.):
-
The process designer allows business users to design and simulate business processes in a web-based environment.
-
The data modeler allows non-technical users to view, modify and create data models for use in your processes.
-
A web-based form modeler also allows you to create, generate or edit forms related to your processes (to start the process or to complete one of the user tasks).
-
Rule authoring allows you to specify different types of business rules (decision tables, guided rules, etc.) for combination with your processes.
-
All assets are stored and managed by the Guvnor repository (exposed through Git) and can be managed (versioning), built and deployed.
-
-
The web-based management console allows business users to manage their runtime (manage business processes like start new processes, inspect running instances, etc.), to manage their task list and to perform Business Activity Monitoring (BAM) and see reports.
-
The Eclipse-based developer tools are an extension to the Eclipse IDE, targeted towards developers, and allows you to create business processes using drag and drop, test and debug your processes, etc.
Each of the component is described in more detail below.
1.3. jBPM engine in jBPM
The jBPM engine implements the Business Process Management (BPM) paradigm in jBPM. BPM is a business methodology that enables modeling, measuring, and optimizing processes within an enterprise.
In BPM, a repeatable business process is represented as a workflow diagram. The Business Process Model and Notation (BPMN) specification defines the available elements of this diagram. The jBPM engine implements a large subset of the BPMN 2.0 specification.
With the jBPM engine, business analysts can develop the diagram itself. Developers can implement the business logic of every element of the flow in code, making an executable business process. Users can execute the business process and interact with it as necessary. Analysts can generate metrics that reflect the efficiency of the process.
The workflow diagram consists of a number of nodes. The BPMN specification defines many kinds of nodes, including the following principal types:
-
Event: Nodes representing something happening in the process or outside of the process. Typical events are the start and the end of a process. An event can throw messages to other processes and catch such messages. Circles on the diagram represent events.
-
Activity: Nodes representing an action that must be taken (whether automatically or with user involvement). Typical events are a task, which represents an action taken within the process, and a call to a sub-process. Rounded rectangles on the diagram represent activities.
-
Gateway: A branching or merging node. A typical gateway evaluates an expression and, depending on the result, continues to one of several execution paths. Diamond shapes on the diagram represent gateways.
When a user starts the process, a process instance is created. The process instance contains a set of data, or context, stored in process variables. The state of a process instance includes all the context data and also the current active node (or, in some cases, several active nodes).
Some of these variables can be initialized when a user starts the process. An activity can read from process variables and write to process variables. A gateway can evaluate process variables to determine the execution path.
For example, a purchase process in a shop can be a business process. The content of the userās cart can be the initial process context. At the end of execution, the process context can contain the payment confirmation and shipment tracking details.
Optionally, you can use the BPMN data modeler in Business Central to design the model for the data in process variables.
The workflow diagram is represented in code by an XML business process definition. The logic of events, gateways, and sub-process calls are defined within the business process definition.
Some task types (for example, script tasks and the standard decision engine rule task) are implemented in the engine. For other task types, including all custom tasks, when the task must be executed the jBPM engine executes a call using the Work Item Handler API. Code external to the engine can implement this API, providing a flexible mechanism for implementing various tasks.
The jBPM engine includes a number of predefined types of tasks. These types include a script task that runs user Java code, a service task that calls a Java method or a Web Service, a decision task that calls a decision engine service, and other custom tasks (for example, REST and database calls).
Another predefined type of task is a user task, which includes interaction with a user. User tasks in the process can be assigned to users and groups.
The jBPM engine uses the KIE API to interact with other software components. You can run business processes as services on a KIE Server and interact with them using a REST implementation of the KIE API. Alternatively, you can embed business processes in your application and interact with them using KIE API Java calls. In this case, you can run the jBPM engine in any Java environment.
Business Central includes a user interface for users executing human tasks and a form modeler for creating the web forms for human tasks. However, you can also implement a custom user interface that interacts with the jBPM engine using the KIE API.
The jBPM engine supports the following additional features:
-
Support for persistence of the process information using the JPA standard. Persistence preserves the state and context (data in process variables) of every process instance, so that they are not lost in case any components are restarted or taken offline for some time. You can use an SQL database engine to store the persistence information.
-
Pluggable support for transactional execution of process elements using the JTA standard. If you use a JTA transaction manager, every element of the business process starts as a transaction. If the element does not complete, the context of the process instance is restored to the state in which it was before the element started.
-
Support for custom extension code, including new node types and other process languages.
-
Support for custom listener classes that are notified about various events.
-
Support for migrating running process instances to a new version of their process definition
The jBPM engine can also be integrated with other independent core services:
-
The human task service can manage user tasks when human actors need to participate in the process. It is fully pluggable and the default implementation is based on the WS-HumanTask specification. The human task service manages the lifecycle of the tasks, task lists, task forms, and some more advanced features like escalation, delegation, and rule-based assignments.
-
The history log can store all information about the execution of all the processes in the jBPM engine. While runtime persistence stores the current state of all active process instances, you need the history log to ensure access to historic information. The history log contains all current and historic states of all active and completed process instances. You can use the log to query for any information related to the execution of process instances for monitoring and analysis.
1.4. Business Central
The Business Central web-based application covers the complete life cycle of BPM projects starting at authoring phase, going through implementation, execution and monitoring. It combines a series web-based tools into one configurable solution to manage all assets and runtime data needed for the business solution.
It supports the following:
-
A repository service to store your business processes and related artifacts, using a Git repository, which supports versioning, remote Git access (as a file system) and access via REST.
-
A web-based user interface to manage your business processes, targeted towards business users; it also supports the visualization (and editing) of your artifacts (the web-based editors like designer, data and form modeler are integrated here), but also categorisation, build and deployment, etc..
-
Collaboration features which enable multiple actors (for example business users and developers) to work together on the same project.
1.4.1. Process Designer
The web-based jBPM Designer allows you to model your business processes in a web-based environment. It is targeted towards business users and offers a graphical editor for viewing and editing your business processes (using drag and drop), similar to the Eclipse plugin. It supports round-tripping between the Eclipse editor and the web-based designer. It also supports simulation of processes.
1.4.2. Data Modeler
Processes almost always have some kind of data to work with. The data modeler allows non-technical users to view, edit or create these data models.
Typically, a business process analyst or data analyst will capture the requirements for a process or application and turn these into a formal set of interrelated data structures. The new Data Modeler tool provides an easy, straightforward and visual aid for building both logical and physical data models, without the need for advanced development skills or explicit coding. The data modeler is transparently integrated into Business Central. Its main goals are to make data models first class citizens in the process improvement cycle and allow for full process automation through the integrated use of data structures (and the forms that will be used to interact with them).
1.4.3. Process Management
Business processes and all its related runtime information can be managed through Business Central. It is targeted towards process administrators users and its main features include:
-
Process definitions management: view the entire list of process currently deployed into a Kie Server and its details.
-
Process instances management: the ability to start new process instances, get a filtered list of process instances, visually inspect the state of a specific process instances.
-
Human tasks management: being able to get a list of all tasks, view details such as current assignees, comments, activity logs as well as send reminders and forward tasks to different users and more.
-
Execution Errors management: allows administrators to view any execution error reported in the Kie Server instance, inspect its details including stacktrace and perform the error acknowledgement.
-
Jobs management: possibility to view currently scheduled and schedule new Jobs to run in the Kie Server instance.
For more details around the entire management section please read the process management chapter.
1.4.4. Task Inbox
As often part of any process execution, human involvement is needed to review, approve or provide extra information. Business Central provides a Task Inbox section where any user potentially involved with these task can manage its workload. In there, users are able to get a list of all tasks, complete tasks using customizable task forms, collaborate using comments and more.
1.4.5. Business Activity Monitoring
As of version 6.0, jBPM comes with a full-featured BAM tooling which allows non-technical users to visually compose business dashboards. With this brand new module, to develop business activity monitoring and reporting solutions on top of jBPM has never been so easy!
Key features:
-
Visual configuration of dashboards (Drag’n’drop).
-
Graphical representation of KPIs (Key Performance Indicators).
-
Configuration of interactive report tables.
-
Data export to Excel and CSV format.
-
Filtering and search, both in-memory or SQL based.
-
Data extraction from external systems, through different protocols.
-
Granular access control for different user profiles.
-
Look’n’feel customization tools.
-
Pluggable chart library architecture.
Target users:
-
Managers / Business owners. Consumer of dashboards and reports.
-
IT / System architects. Connectivity and data extraction.
-
Analysts / Developers. Dashboard composition & configuration.
To get further information about the new and noteworthy BAM capabilities of jBPM please read the chapter Business Activity Monitoring.
1.5. Eclipse Developer Tools
The Eclipse-based tools are a set of plugins to the Eclipse IDE and allow you to integrate your business processes in your development environment. It is targeted towards developers and has some wizards to get started, a graphical editor for creating your business processes (using drag and drop) and a lot of advanced testing and debugging capabilities.
It includes the following features:
-
Wizard for creating a new jBPM project
-
A graphical editor for BPMN 2.0 processes
-
The ability to plug in your own domain-specific nodes
-
Validation
-
Runtime support (so you can select which version of jBPM you would like to use)
-
Graphical debugging to see all running process instances of a selected session, to visualize the current state of one specific process instance, etc.
2. Getting Started
We recommend taking a look at our Getting Start page as a starting point for getting a full environment up and running with all the components you need in order to design, deploy, run and monitor a process. Alternatively, you can also take a quick tutorial that will guide you through most of the components using a simple example available in the Installer Chapter. This will teach you how to download and use the installer to create a demo setup, including most of the components. It uses a simple example to guide you through the most important features. Screencasts are available to help you out as well.
If you like to read more information first, the following chapters first focus on the core jBPM engine (API, BPMN 2.0, etc.). Further chapters will then describe the other components and other more complex topics like domain-specific processes, flexible processes, etc. After reading the core chapters, you should be able to jump to other chapters that you might find interesting.
You can also start playing around with some examples that are offered in a separate download. Check out the Examples chapter to see how to start playing with these.
After reading through these chapters, you should be ready to start creating your own processes and integrate the jBPM engine with your application. These processes can be started from the installer or be started from scratch.
2.1. Downloads
Latest releases can be downloaded from jBPM.org. Just pick the artifact you want:
-
server: single zip distribution with jBPM server (including WildFly, Business Central, jBPM case management showcase and service repository)
-
bin: all the jBPM binaries (JARs) and their transitive dependencies
-
src: the sources of the core components
-
docs: the documentation
-
examples: some jBPM examples, can be imported into Eclipse
-
installer: the jBPM Installer, downloads and installs a demo setup of jBPM
-
installer-full: full jBPM Installer, downloads and installs a demo setup of jBPM, already contains a number of dependencies prepackaged (so they don’t need to be downloaded separately)
Older releases are archived at http://downloads.jboss.org/jbpm/release/.
Alternatively, you can also use one of the many Docker images available for use at the Download section.
2.2. Community
Here are a lot of useful links part of the jBPM community:
-
jBPM Setup and jBPM Usage user forums and mailing lists
-
A JIRA bug tracking system for bugs, feature requests and roadmap
Please feel free to join us in our IRC channel at chat.freenode.net#jbpm. This is where most of the real-time discussion about the project takes place and where you can find most of the developers most of their time as well. Don’t have an IRC client installed? Simply go to http://webchat.freenode.net/, input your desired nickname, and specify #jbpm. Then click login to join the fun.
2.3. Sources
2.3.1. License
The jBPM code itself is using the Apache License v2.0.
Some other components we integrate with have their own license:
-
The new Eclipse BPMN2 plugin is Eclipse Public License (EPL) v1.0.
-
The legacy web-based designer is based on Oryx/Wapama and is MIT License
-
The Drools project is Apache License v2.0.
2.3.2. Source code
jBPM now uses git for its source code version control system. The sources of the jBPM project can be found here (including all releases starting from jBPM 5.0-CR1):
The source of some of the other components can be found here:
2.3.3. Building from source
If you’re interested in building the source code, contributing, releasing, etc. make sure to read this README.
2.4. Getting Involved
We are often asked "How do I get involved". Luckily the answer is simple, just write some code and submit it :) There are no hoops you have to jump through or secret handshakes. We have a very minimal "overhead" that we do request to allow for scalable project development. Below we provide a general overview of the tools and "workflow" we request, along with some general advice.
If you contribute some good work, don’t forget to blog about it :)
2.4.1. Sign up to jboss.org
Signing to jboss.org will give you access to the JBoss wiki, forums and JIRA. Go to https://www.jboss.org/ and click "Register".
2.4.2. Sign the Contributor Agreement
The only form you need to sign is the contributor agreement, which is fully automated via the web. As the image below says "This establishes the terms and conditions for your contributions and ensures that source code can be licensed appropriately"
2.4.3. Submitting issues via JIRA
To be able to interact with the core development team you will need to use JIRA, the issue tracker. This ensures that all requests are logged and allocated to a release schedule and all discussions captured in one place. Bug reports, bug fixes, feature requests and feature submissions should all go here. General questions should be undertaken at the mailing lists.
Minor code submissions, like format or documentation fixes do not need an associated JIRA issue created.
2.4.4. Fork GitHub
With the contributor agreement signed and your requests submitted to JIRA you should now be ready to code :) Create a GitHub account and fork any of the Drools, jBPM or Guvnor repositories. The fork will create a copy in your own GitHub space which you can work on at your own pace. If you make a mistake, don’t worry blow it away and fork again. Note each GitHub repository provides you the clone (checkout) URL, GitHub will provide you URLs specific to your fork.
2.4.5. Writing Tests
When writing tests, try and keep them minimal and self contained. We prefer to keep the DRL fragments within the test, as it makes for quicker reviewing. If there are a large number of rules then using a String is not practical so then by all means place them in separate DRL files instead to be loaded from the classpath. If your tests need to use a model, please try to use those that already exist for other unit tests; such as Person, Cheese or Order. If no classes exist that have the fields you need, try and update fields of existing classes before adding a new class.
There are a vast number of tests to look over to get an idea, MiscTest is a good place to start.
2.4.6. Commit with Correct Conventions
When you commit, make sure you use the correct conventions. The commit must start with the JIRA issue id, such as DROOLS-1946. This ensures the commits are cross referenced via JIRA, so we can see all commits for a given issue in the same place. After the id the title of the issue should come next. Then use a newline, indented with a dash, to provide additional information related to this commit. Use an additional new line and dash for each separate point you wish to make. You may add additional JIRA cross references to the same commit, if it’s appropriate. In general try to avoid combining unrelated issues in the same commit.
Don’t forget to rebase your local fork from the primary branch and then push your commits back to your fork.
2.4.7. Submit Pull Requests
With your code rebased from primary branch and pushed to your personal GitHub area, you can now submit your work as a pull request. If you look at the top of the page in GitHub for your work area there will be a "Pull Request" button. Selecting this will then provide a gui to automate the submission of your pull request.
The pull request then goes into a queue for everyone to see and comment on. Below you can see a typical pull request. The pull requests allow for discussions and it shows all associated commits and the diffs for each commit. The discussions typically involve code reviews which provide helpful suggestions for improvements, and allows for us to leave inline comments on specific parts of the code. Don’t be disheartened if we don’t merge straight away, it can often take several revisions before we accept a pull request. Luckily GitHub makes it very trivial to go back to your code, do some more commits and then update your pull request to your latest and greatest.
It can take time for us to get round to responding to pull requests, so please be patient. Submitted tests that come with a fix will generally be applied quite quickly, where as just tests will often way until we get time to also submit that with a fix. Don’t forget to rebase and resubmit your request from time to time, otherwise over time it will have merge conflicts and core developers will general ignore those.
2.5. What to do if I encounter problems or have questions?
You can always contact the jBPM community for assistance.
IRC: #jbpm at chat.freenode.net
jBPM Setup Google Group - Installation, configuration, setup and administration discussions for Business Central, Eclipse, runtime environments and general enterprise architectures.
jBPM Usage Google Group - Authoring, executing and managing processes with jBPM. Any questions regarding the use of jBPM. General API help and best practices in building BPM systems.
Visit our website for more options on how to get help.
Legacy jBPM User Forum - serves as an archive; post new questions to one of the Google Groups above
3. Getting started with process services in jBPM
As a business rules and processes developer, you can use Business Central in jBPM to design business processes to meet specific business requirements. jBPM provides sample projects in Business Central that contain business assets for reference purposes. This document describes how to create a new mortgage process project, data objects, and business process to familiarize yourself with Business Central and the process designer.
You will then refer to the Mortgage_Process sample project included in Business Central to review the sample project’s business rules, decision tables, and forms. You will build and deploy the Mortgage_Process sample project and execute the project’s defined functionality.
-
Red Hat JBoss Enterprise Application Platform 7.4 is installed. For details, see the Red Hat JBoss Enterprise Application Platform 7.4 Installation Guide.
-
jBPM is installed and configured with KIE Server. For more information, see Installing and configuring jBPM on Red Hat JBoss EAP 7.4.
-
jBPM is running and you can log in to Business Central with the
developer
role. For more information, see Planning a jBPM installation.
3.1. Overview
Business Central enables you to automate your business processes. A business process is a diagram that describes the order in which a series of steps must be executed and consists of predefined nodes and connections. Each node represents one step in the process while the connections specify how to transition from one node to another.
For example, a bank offers a housing mortgage loan service. Using Business Central, the housing mortgage department of the bank creates a complete business process for the mortgage loan.
When a customer wants to buy a new property using credit, the following steps occur:
-
The customer contacts a broker at the bank who assists in filing for a mortgage loan.
-
The broker collects information about the property and the customer, such as the salary of the customer, social security number, the property sale price, and the requested loan amount.
-
The broker then submits a request on behalf of the customer.
Whenever a customer submits a request, a new process instance is created. This ensures consistency in the quality of evaluating each request, provides complete visibility into the status of each request, and makes the process efficient and effective.
3.2. Creating the mortgage-process project
A project is a container for assets such as data objects, business processes, guided rules, decision tables, and forms. The project that you are creating is similar to the existing Mortgage_Process sample project in Business Central.
-
In Business Central, go to Menu → Design → Projects.
jBPM provides a default space called MySpace, as shown in the following image. You can use the default space to create and test example projects.
Figure 7. Default space -
Click Add Project.
-
Enter
mortgage-process
in the Name field. -
Click Configure Advanced Options and modify the GAV fields with the following values:
-
Group ID:
com.myspace
-
Artifact ID:
mortgage-process
-
Version:
1.0.0
-
-
Click Add.
The Assets view of the project opens.
3.3. Creating users
You can create as many Business Central users as you require. User privileges and settings are controlled by the roles assigned to a user and the groups that a user belongs to. For this example, you must create two new users: Katy
who will act as the bank’s loan manager and approver, and Bill
who will act as the broker requesting the loan. For more information on creating users, see the Creating users chapter of Installing and configuring jBPM on Red Hat JBoss EAP 7.4.
In Business Central, you can use groups and roles to control permissions for a collection of users. You can create as many groups and roles as you want but a group must have at least one user.
-
For this example, the user or users working on the tasks must be assigned to one or more of the following groups and roles:
-
approver group: For the Qualify task
-
broker group: For the Correct Data and Increase Down Payment tasks
-
manager role: For the Final Approval task
-
-
Click the gear icon in the upper-right corner and click Users.
-
Click , enter
Katy
, click Next, and click Create. -
Click Yes to set a password, enter
Katy
in both fields, and click Change. -
Enter
Bill
, click Next, and click Create. -
Click Yes to set a password, enter
Bill
in both fields, and click Change. -
Click the Groups tab and click , enter
approver
, and click Next. -
Select
Katy
from the user list, and click Add selected users. -
Enter
broker
, and click Next. -
Select
Bill
from the user list, and click Add selected users. -
Click the Users tab, select
Katy
, and click Edit → Roles → Add roles. -
Select
manager
, click Add to selected roles, and click Save. -
Click the Groups tab and click Edit → Groups → Add to groups.
-
Select
approver
andkie-server
, and click Add to selected groups. -
Click Save.
-
Click the Users tab, select
Bill
from the user list, and click Edit → Roles → Add roles. -
Select
user
, and click Add to selected roles. -
Click the Groups tab, click , select
kie-server
, and click Add to selected groups. -
Click Save.
3.4. Creating the mortgage-process data objects
Data objects are the building blocks for the rule assets that you create. Data objects are custom data types implemented as Java classes in specified packages of your project. These custom data types determine what data your assets and your decision services are based on.
The mortgage process project uses the following data objects:
-
Applicant
-
Property
-
ValidationErrorDO
-
Application
3.4.1. Creating the Applicant data object
Create the Applicant data object, which contains information about the applicant. This is the basic information required to apply for the loan in this tutorial.
-
In Business Central, click the MySpace default space.
-
Click Menu → Design → Projects and click mortgage-process.
-
Click Add Asset and select Data Object.
-
Enter
Applicant
in the Data Object field of the Create new Data Object window. -
Select
com.myspace.mortgage_app
from the Package drop-down menu and click Ok. -
Enter
Applicant
in the Label field of the 'Applicant'- general properties section. -
Click +add field and input the following Applicant data object values. Click Create and continue after each addition. For the last addition, click Create.
Figure 8. Applicant data object field values -
Click Save.
3.4.2. Creating the Property data object
Create the Property data object, which contains information about the property details, such as the property age and price.
-
In Business Central, click the MySpace default space.
-
Click Menu → Design → Projects and click mortgage-process.
-
Click Add Asset and select Data Object.
-
Enter
Property
in the Data Object field of the Create new Data Object window. -
Select
com.myspace.mortgage_app
from the Package drop-down menu and click Ok. -
Enter
Property
in the Label field of the 'Property'- general properties section. -
Click +add field and input the following Property data object values. Click Create and continue after each addition. For the last addition, click Create.
Figure 9. Property data object field values -
Click Save.
3.4.3. Creating the ValidationErrorDO data object
Create the ValidationErrorDO data object, which specifies the cause of an application error.
-
In Business Central, click the MySpace default space.
-
Click Menu → Design → Projects and click mortgage-process.
-
Click Add Asset and select Data Object.
-
Enter
ValidationErrorDO
in the Data Object field of the Create new Data Object window. -
Select
com.myspace.mortgage_app
from the Package drop-down menu and click Ok. -
Enter
ValidationErrorDO
in the Label field of the 'ValidationErrorDO'- general properties section. -
Click +add field and input the following ValidationErrorDO data object values. Click Create and continue after each addition. For the last addition, click Create.
Figure 10. ValidationErrorDO data object field values -
Click Save.
3.4.4. Creating the Application data object
Create the Application data object, which contains information about the mortgage details, such as the down payment and the mortgage amount.
-
In Business Central, click the MySpace default space.
-
Click Menu → Design → Projects and click mortgage-process.
-
Click Add Asset and select Data Object.
-
Enter
Application
in the Data Object field of the Create new Data Object window. -
Select
com.myspace.mortgage_app
from the Package drop-down menu and click Ok. -
Enter
Application
in the Label field of the 'Application'- general properties section. -
Click +add field and input the following Application data object values. Click Create and continue after each addition. For the last addition, click Create.
Figure 11. Application data object field values -
Click Save.
3.5. Business processes in Business Central
A business process is a diagram that describes the order in which a series of steps must be executed using a flow chart. A business process consists of a collection of nodes that are linked to each other using connections. Each of the nodes represents one step in the overall process while the connections specify how to transition from one node to the other.
The sample Mortgage_Process contains the following predefined MortgageApprovalProcess business process.
3.5.1. Creating the business process
The following procedures guide you through the creation of tasks, connections, and gateways that make up the MortgageApprovalProcess business process. The mortgage validation business process determines whether a mortgage application contains all required data. If the specified data requirements are met, the application proceeds on to the mortgage calculation business process.
-
In Business Central, go to Menu → Design → Projects → Mortgage-Process.
-
Click Add Asset → Business Process.
-
Enter the following values:
-
Business Process:
MortgageApprovalProcess
-
Package: Select
com.myspace.mortgage_app
The Package specifies the location inside the existing project where the asset will be created. In this example, it is created in
com/myspace/mortgage_app
.
-
-
Click Ok. The diagram editor opens.
-
In the upper-right corner, click the Properties icon.
-
Scroll down and expand Process Data and click in the Process Variables section.
-
Enter the following values:
-
Name:
application
-
Data Type:
Application [com.myspace.mortgage_app]
-
3.5.1.1. Creating outgoing connections and exclusive gateways
This section shows you how to create outgoing connections, exclusive gateways, and business rule tasks. Use exclusive gateways to make decisions and react to events based on the available data.
jBPM contains a predefined selection of node types to simplify business process creation. The predefined node panel is located on the left side of the diagram editor.
-
Drag a start event node onto the canvas.
-
Create an outgoing connection from the start event to an exclusive gateway:
-
On the canvas, click the start event node and click the Create Parallel icon.
-
Hover over the icon of the parallel and click the Convert into Exclusive icon.
-
-
Create an outgoing connection from the exclusive gateway to a business rule task:
-
On the canvas, click the exclusive gateway and click the Create Task icon.
-
Hover over the icon of the task and click the Convert into Business Rule icon.
-
-
Configure the business rule task:
-
Click the business rules task.
-
If the Properties panel is not open, click the Properties icon in the upper-right corner.
-
In the Properties panel, enter
Validation
in the Name field. -
Expand Implementation/Execution, select New from the Rule Flow Group menu, and input validation.
-
In the On Exit Action field, enter the following Java expression:
System.out.println(application.getProperty());
-
Expand Data Assignments and click next to Assignments.
-
In the Validation Data I/O window, click Add and create the following assignments:
-
Data Inputs and Assignements
-
Name: application
-
Data Type: Application [com.myspace.mortgage_app]
-
Source: application
-
-
Data Outputs and Assignements
-
Name: application
-
Data Type: Application [com.myspace.mortgage_app]
-
Target: application
Figure 12. Validation Data I/O assignments
-
-
-
-
Click OK in the Validation Data I/O window.
-
Above the canvas, click Save to confirm your changes.
3.5.1.2. Defining the validation data
This section shows you how to define the validation data that determines whether the application data is correct, contains an error, or has missing information.
-
Create an outgoing connection from the Validation task to an exclusive gateway:
-
Click the Validation task and click the Create Parallel icon.
-
Hover over the icon of the parallel and click the Convert into Exclusive icon.
-
-
Create an outgoing connection from the exclusive gateway to a new business rule task:
-
Click the exclusive gateway and click the Create Task icon.
-
Drag the new task below the exclusive gateway as shown in the following image.
-
Hover over the icon of the task and click the Convert into Business Rule icon.
-
If the Properties panel is not open, click the Properties icon in the upper-right corner.
-
In the Properties panel, enter
Retract Validation
in the Name field. -
Expand Implementation/Execution, select New from the Rule Flow Group menu, and input
error
.
-
-
Configure the connection between the exclusive gateway and the business rule task:
-
Click the connection.
-
If the Properties panel is not open, click the Properties icon in the upper-right corner.
-
In the Properties panel, enter
Invalid
in the Name field. -
Expand Implementation/Execution and select Expression in the Condition Expression section.
-
From the list, select drools and enter
ValidationErrorDO()
in the Condition Expression field.
-
-
Create an outgoing connection from the Retract Validation task to a new user task:
-
Click the Retract Validation task and click the Create Task icon.
-
Drag the new task below the Validation task as shown below.
-
Hover over the icon of the task and click the Convert into User icon.
-
Click the new user task and in the Properties panel, enter
Correct Data
in the Name field. -
Expand Implementation/Execution and enter
CorrectData
in the Task Name field. -
Select New from the Groups menu, and input
broker
. -
Click next to Assignments.
-
In the Correct Data Data I/O window, click Add and create the following assignments:
-
Name: application
-
Data Type: Application [com.myspace.mortgage_app]
-
Source: application
-
Data Outputs and Assignements
-
-
Name: application
-
Data Type: Application [com.myspace.mortgage_app]
-
Target: application
Figure 13. Correct Data Data I/O assignments
-
-
Click OK in the Correct Data Data I/O window.
-
Above the canvas, click Save.
-
-
Click the Correct Data user task then click the Create sequence Flow icon and drag it back to the first exclusive gateway. Your workflow should look similar to the following diagram:
3.5.1.3. Calculating the mortgage
The mortgage calculation business process determines the applicant’s mortgage borrowing limit.
-
Return to the second exclusive gateway and create an outgoing connection to a new business rule task.
-
Click the created connection and in the Properties panel, input
Valid
in the Name field.-
Expand Implementation/Execution and select Expression in the Condition Expression section.
-
From the list, select drools and enter
not ValidationErrorDO()
in the Condition Expression field.
-
-
Click the new business rule task and in the Properties panel, input
Mortgage Calculation
in the Name field.-
Expand Implementation/Execution, select New from the Rule Flow Group menu, and input
mortgagecalculation
.
-
-
Expand Data Assignments and click next to Assignments.
-
In the Mortgage Calculation Data I/O window, click Add to create the following assignments and click Save.
Figure 14. Mortgage Calculation Data I/O assignments -
Click OK in the Mortgage Calculation Data I/O window.
-
Click an empty space on the canvas, scroll down, expand Process Data, and click next to Process Variables. Enter the following values:
-
Name:
inlimit
-
Data Type:
Boolean
-
-
Create an outgoing connection from the Mortgage Calculation task to a new user task.
-
Click the user task, enter
Qualify
in the Name field. -
Expand Implementation/Execution and enter
Qualify
in the Task Name field. -
Select New from the Groups menu, and input
approver
. -
Click next to Assignments. In the Qualify Data I/O window, click Add to create the following assignments:
Figure 15. Qualify Data I/O assignments -
Click OK in the Qualify Data I/O window.
-
Above the canvas, click Save to confirm your changes.
-
Click the Qualify user task, click the Create parallel menu icon, and convert it to an exclusive gateway.
-
Drag the new exclusive gateway below the Qualify user task.
-
Create an outgoing connection from the exclusive gateway and connect it to a new user task.
-
Click the connection and input
In Limit
in the Name field of the Properties panel. -
Expand Implementation/Execution and select Condition in the Condition Expression section.
-
Select inlimit from the Process Variable drop-down menu and select Is true from the Condition drop-down menu.
-
Click the user task, enter
Final Approval
in the Name field. -
Expand Implementation/Execution and enter
FinalApproval
in the Task Name field. -
Select New from the Groups menu, and input
manager
. -
Click next to Assignments. In the Final Approval Data I/O window, click Add to create the following assignments:
Figure 16. Final Approval Data I/O assignments -
Click OK in the Final Approval Data I/O window.
-
Above the canvas, click Save to confirm your changes.
3.5.1.4. Increasing the down payment
The Increasing the Down Payment business process checks to see if the applicant qualifies for the loan by increasing their down payment. The final result is either the final loan approval, or loan denial based on the applicant’s inability to increase the down payment.
-
Click the Final Approval user task and select Create End from the user task quick menu.
-
Move the end event below the Final Approval user task.
-
Return to the exclusive gateway that connects with the Final Approval user task. Create a second outgoing connection and connect it to a new user task.
-
Click the connection and input
Not in Limit
in the Name field of the Properties panel. -
Expand Implementation/Execution and select Condition in the Condition Expression section.
-
Select inlimit from the Process Variable drop-down menu and select Is false from the Condition drop-down menu.
-
Click an empty space on the canvas, scroll down, expand Process Data, and click next to Process Variables. Enter the following values:
-
Name:
incdownpayment
-
Data Type:
Boolean
-
-
Click the new user task and in the Properties panel, input
Increase Down Payment
in the Name field. -
Expand Implementation/Execution and enter
IncreaseDownPayment
in the Task Name field. -
Select New from the Groups menu, and input
broker
. -
Click next to Assignments. In the Increase Down Payment Data I/O window, click Add to create the following assignments:
Figure 17. Increase Down Payment Data I/O assignments -
Click OK in the Increase Down Payment Data I/O window.
-
Above the canvas, click Save to confirm your changes.
-
Click the Increase Down Payment user task, click the Create parallel menu icon, and convert it to an exclusive gateway.
-
Drag the new exclusive gateway below the Increase Down Payment user task.
-
Create an outgoing connection from the exclusive gateway to an end event.
-
Click the connection and input
Down payment not increased
in the Name field of the Properties panel. -
Expand Implementation/Execution and select Expresssion in the Condition Expression section.
-
Input return !incdownpayment; and select java from the drop-down menu.
-
Create an outgoing connection from the exclusive gateway and connect it to the first exclusive gateway.
-
Click the connection and input
Down payment increased
in the Name field of the Properties panel. -
Expand Implementation/Execution and select Expresssion in the Condition Expression section.
-
Input return incdownpayment; and select java from the drop-down menu.
-
Above the canvas, click Save to confirm your changes and save the entire business process.
3.5.2. Viewing the Mortgage_Process business rules
The goal of this chapter is to introduce you to the predefined business rules for the Mortgage_Process project. For this tutorial, you do not create and define the business rules. Instead, review the WHEN and THEN rules that are already defined in the Mortgage_Process sample project’s preconfigured business rules. For information about creating guided business rules, see Designing a decision service using guided rules.
3.5.2.1. Viewing the Validate Down Payment guided rule
Review the WHEN and THEN rules so that you understand how the conditions are set and used later when you run the process.
-
Click Menu → Design → Projects, and click Mortgage_Process.
-
From the asset list, click the right arrow to view the second page of the asset list and click the Validate Down Payment guided rule.
-
Review the Validate Down Payment guided rule’s WHEN and THEN conditions and values.
3.5.2.2. Viewing the RetractValidationErr guided rule
Review the WHEN and THEN rules so that you understand how the conditions are set and used later when you run the process.
-
Click Menu → Design → Projects, and click Mortgage_Process.
-
From the asset list, click the right arrow to view the second page of the asset list and click the RetractValidationErr guided rule.
-
Review the RetractValidationErr guided rule’s WHEN and THEN conditions and values.
3.5.3. Viewing the mortgage decision table
The goal of this chapter is to introduce you to the MortgageDecisionTable decision table. For this tutorial, you do not create and set the decision table conditions. Instead, review the values and the conditions that are already defined in the Mortgage_Process sample project’s MortgageDecisionTable Guided Decision Tables asset. For information about creating decision tables, see Designing a decision service using guided decision tables.
-
The business rules have been defined. For more information, see Viewing the Mortgage_Process business rules.
-
In Business Central, go to Menu → Design → Projects → Mortgage_Process.
-
Scroll down and click the MortgageDecisionTable Guided Decision Tables asset.
3.6. Forms in Business Central
A form is a layout definition for a page, defined as HTML, that is displayed as a dialog window to the user during process and task instantiation. Task forms acquire data from a user for both the process and task instance execution, whereas process forms take input and output from process variables.
The input is then mapped to the task using the data input assignment, which you can use inside of a task. When the task is completed, the data is mapped as a data output assignment to provide the data to the parent process instance.
3.6.1. Viewing the Mortgage_Process forms
The goal of this chapter is to introduce you to the Mortgage_Process sample project’s predefined forms which are used for collecting user data for the mortgage application business process. For this tutorial, you do not create and modify the Mortgage_Process forms. Instead, review the predefined sample forms. For information about creating forms, see Designing business processes using BPMN models.
-
In Business Central, go to Menu → Design → Projects → Mortgage_Process.
-
From the asset list, click the right arrow to view the second page of the asset list and select the Applicant form.
Figure 19. Applicant sample form -
Click Menu → Design → Projects → Mortgage_Process.
-
From the asset list, select the Property form. The Property form is shown in the following screenshot:
Figure 20. Property sample form -
Click Menu → Design → Projects → Mortgage_Process.
-
From the asset list, select the Application form. The Application form is shown in the following screenshot:
Figure 21. Application sample form -
Click the X icon in the upper-right corner to close the editor.
3.7. Deploying the MortgageApprovalProcess process application
The following chapter instructs you how to build and deploy a new instance of the Mortgage_Process application in jBPM.
-
KIE Server is deployed and connected to Business Central.
-
In Business Central, go to Menu → Design → Projects → Mortgage_Process.
-
Click Deploy.
-
If no KIE container (deployment unit) is included with the project name, a container with default values is automatically created.
-
If an older version of the project is already deployed, go to the project settings and change the project version. When finished, save the change and click Deploy. This deploys a new version of the same project with the latest changes in place, alongside the older version(s).
You can also select the Build & Install option to build the project and publish the KJAR file to the configured Maven repository without deploying to a KIE Server. In a development environment, you can click Deploy to deploy the built KJAR file to a KIE Server without stopping any running instances (if applicable), or click Redeploy to deploy the built KJAR file and replace all instances. The next time you deploy or redeploy the built KJAR, the previous deployment unit (KIE container) is automatically updated in the same target KIE Server. In a production environment, the Redeploy option is disabled and you can click Deploy only to deploy the built KJAR file to a new deployment unit (KIE container) on a KIE Server.
To configure the KIE Server environment mode, set the
org.kie.server.mode
system property toorg.kie.server.mode=development
ororg.kie.server.mode=production
. To configure the deployment behavior for a corresponding project in Business Central, go to project Settings → General Settings → Version and toggle the Development Mode option. By default, KIE Server and all new projects in Business Central are in development mode. You cannot deploy a project with Development Mode turned on or with a manually addedSNAPSHOT
version suffix to a KIE Server that is in production mode.
-
-
To review project deployment details, click View deployment details in the deployment banner at the top of the screen or in the Deploy drop-down menu. This option directs you to the Menu → Deploy → Execution Servers page.
3.8. Executing the MortgageApprovalProcess process application
Now that you have deployed the project, you can execute the project’s defined functionality. For this tutorial you input data into a mortgage application form acting as the mortgage broker. The MortgageApprovalProcess business process runs and determines whether or not the applicant has offered an acceptable down payment based on the decision rules that you defined earlier. The business process either ends the rule testing or requests that the applicant increase the down payment to proceed. If the application passes the business rule testing, the bank’s approver reviews the application and either approve or deny the loan.
-
KIE Server is deployed and connected to Business Central.
-
The Mortgage_Process application has been deployed.
-
The users working on the tasks are members of the following groups and roles:
-
approver group: For the Qualify task
-
broker group: For the Correct Data and Increase Down Payment tasks
-
manager role: For the Final Approval task
-
-
Log in to jBPM as
Bill
(the broker) and click Menu → Manage → Process Definitions. -
Click the three vertical dots in the Actions column and select Start to start to open the Application form and input the following values in to the form fields:
-
Down Payment:
30000
-
Years of amortization:
10
-
Name:
Ivo
-
Annual Income:
60000
-
SSN:
123456789
-
Age of property:
8
-
Address of property:
Brno
-
Locale:
Rural
-
Property Sale Price:
50000
-
-
Click Submit to start a new process instance. After starting the process instance, the Instance Details view opens.
-
Click the Diagram tab to view the process flow within the process diagram. The state of the process is highlighted as it moves through each task.
-
Log out of Business Central and log back in as
Katy
. -
Click Menu → Track → Task Inbox. This takes you to the Qualify form.
-
Click the three vertical dots in the Actions column and select and click Claim. The Qualify task Status is now
Reserved
. -
Click the Qualify task row to open and review the task information. Click Claim and then Start at the bottom of the form.
The application form is now active for approval or denial.
-
To approve the application, select Is mortgage application in limit? and click Complete.
-
In the Task Inbox, click anywhere in the Final Approval row to open the Final Approval task.
-
In the Final Approval row, click the three vertical dots in the Actions column and click Claim.
-
Click anywhere in the Final Approval row to open the Final Approval task. Click Start at the bottom of the form.
-
Note that the Inlimit check box is selected to reflect that that application is ready for final approval. Click Complete.
The Save and Release buttons are only used to either pause the approval process and save the instance if you are waiting on a field value, or to release the task for another user to modify. |
3.9. Monitoring the MortgageApprovalProcess process application
The following chapter shows how different bank employees, such as a system administrator or a knowledge worker, might use some of the monitoring capabilities to track an instance of the mortgage approval process.
-
KIE Server is deployed and connected to Business Central.
-
Log in to jBPM and click Menu → Manage → Process Instances.
-
In the Manage Process Instances window, you can set filters, such as State, Errors, Id, and so on.
-
Select Completed in the State filter to view all completed MortgageApprovalProcess instances.
-
Click on the completed process instance.
-
Click each of the following tabs to get a feel for what type of information is available to monitor a specific process instance:
-
Instance Details
-
Process Variables
-
Documents
-
Logs
-
Diagram
-
-
Click Menu → Track → Process Reports. This view contains a variety of charts that can help a senior process manager to gain an overview of all processes based on Type, Start Date, Running Time, and so on to assist with task reporting.
3.9.1. Filtering process instances using default or advanced filters
Business Central now provides you with default and advanced filters to help you filter and search through running process instances. You can also create custom filters using the Advanced Filters option.
3.9.1.1. Filtering process instances using default filters
Filter process instances by attributes such as State, Errors, Filter By, Name, Start Date, and Last update.
-
In Business Central, go to Menu → Manage → Process Instances.
-
On the Manage Process Instances page, click the filter icon on the left of the page to expand the Filters pane.
This pane lists the following process attributes which you can use to filter process instances:
-
State: Filter process instances based on their state (Active, Aborted, Completed, Pending, and Suspended).
-
Errors: Filter process instances by errors.
-
Filter By: Filter process instances based on Id, Initiator, Correlation Key, or Description attribute.
-
Select the required attribute.
-
Enter the search query in the text field below.
-
Click Apply.
-
-
Name: Filter process instances by definition names.
-
Definition Id: Filter process instances by process definition IDs.
-
Deployment Id: Filter process instances by process deployment IDs.
-
Parent Process Instance Id: Filter process instances by parent process instance IDs.
-
SLA Compliance: Filter process instances by SLA compliance states.
-
Start Date: Filter process instances by creation dates.
-
Last update: Filter process instances by last modified dates.
-
3.9.1.2. Filtering process instances using advanced filters
Use the Advanced Filters option to create custom process instance filters. The newly created custom filter is added to the Saved Filters pane, which is accessible by clicking on the star icon on the left of the Manage Process Instances page.
-
In Business Central, go to Menu → Manage → Process Instances.
-
On the Manage Process Instances page, on the left of the page click the Advanced Filters icon.
-
In the Advanced Filters pane, enter the name and description of the filter, and click Add New.
-
Select an attribute from the Select column drop-down list, for example, processName. The content of the drop-down changes to processName != value1.
-
Click the drop-down again and choose the required logical query. For the processName attribute, choose equals to.
-
Change the value of the text field to the name of the process you want to filter.
The name must match the value defined in the business process of the project.
-
Click Save and the processes are filtered according to the filter definition.
-
Click the star icon to open the Saved Filters pane.
In the Saved Filters pane, you can view all the saved advanced filters.
4. Getting started with case management in jBPM
As a business rules and processes developer, you can use case management assets in Business Central to create unpredictable and ad hoc case processes. Case workers or process administrators can also use Business Central for case management and execution. jBPM provides example projects with example business assets in Business Central as a reference. This document describes how to create and test an example IT orders project based on the IT_Orders sample project included in Business Central.
-
Red Hat JBoss Enterprise Application Platform 7.4 is installed. For installation information, see Red Hat JBoss Enterprise Application Platform 7.4 Installation Guide.
-
jBPM is installed and configured with KIE Server. For more information see Installing and configuring jBPM on Red Hat JBoss EAP 7.4.
-
jBPM is running and you can log in to Business Central with the
kie-server
,user
, andadmin
roles. -
You have reviewed the information in Designing and building cases for case management.
4.1. Reviewing the IT_Orders sample project
Before you create your own case management project, review the existing IT_Orders sample case management project in Business Central. This sample project contains predefined case management assets as a reference for your own case projects.
The business process application example includes features that are Technology Preview only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs), might not be functionally complete, and are not recommended for production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process. For more information about Red Hat Technology Preview support, see Technology Preview Features Support Scope. |
-
In Business Central, go to Menu → Design → Projects. If there are existing projects, you can access the samples by clicking the MySpace default space and selecting Try Samples from the Add Project drop-down menu. If there are no existing projects, click Try samples.
-
Select IT_Orders and click Ok.
The Assets view of the project opens. Select each example asset to explore how the project is designed to achieve the specified goal or workflow.
Review the orderhardware business process to help you understand the business process flow.
4.2. Creating a new IT_Orders case project
Create a new IT_Orders
project in Business Central to gain an understanding of all of the required assets and how they are used in the project.
-
Log in to Business Central and go to Menu → Design → Projects.
Business Central provides a default space called MySpace, as shown in the following image. You can use the default space to create and test example projects.
Figure 22. Default spaces -
Click the Add Project drop-down arrow and select the Case project option:
Figure 23. Case project -
In the Add Project window, enter
IT_Orders_New
in the Name field and enter a project Description.Figure 24. Add Project window -
Click Add to add the project.
The Assets view of the project opens.
4.3. Data objects
Data objects are the building blocks for the rule assets that you create. Data objects are custom data types implemented as Java objects in specified packages of your project. For example, you might create a Person
object with data fields Name
, Address
, and DateOfBirth
to specify personal details for loan application rules. These custom data types determine what data your assets and your decision services are based on.
4.3.1. Creating the ITOrderService data object
The ITOrderService
data object specifies the data type that will be used to define the IT Orders variables.
-
The IT_Orders_New project is created.
-
Click Add Asset → Data Object.
-
In the Create new Data Object wizard, enter the following values:
-
Data Object:
ITOrderService
-
Package:
com.myspace.it_orders_new
-
-
Click Ok.
-
Click next to the Package drop-down menu to specify a new package for the data object.
-
Input
org.jbpm.demo.it_orders.services
and click Add. -
Click Save, and then click Yes, Move to confirm your changes.
4.3.2. Creating the Survey data object
The Survey
data object contains data fields, such as deliveredOnTime and missingEquipment. You will use the data and values when you design your case.
-
The IT_Orders_New project is created.
-
In Business Central, go to Menu → Design → Projects and click IT_Orders_New.
-
Click Add Asset → Data Object.
-
In the Create new Data Object wizard, enter the following values:
-
Data Object:
Survey
-
Package:
com.myspace.it_orders_new
-
-
Click Ok.
-
Add the Survey data object constraints.
-
Click add field.
-
Enter the following values:
-
Id:
comment
-
Label: Leave empty
-
Type:
String
-
-
Click Create and continue, and then enter the following values:
-
Id:
deliveredOnTime
-
Label: Leave empty
-
Type:
Boolean
-
-
Click Create and continue, and then enter the following values:
-
Id:
missingEquipment
-
Label: Leave empty
-
Type:
String
-
-
Click Create and continue, and then enter the following values:
-
Id:
satisfied
-
Label: Leave empty
-
Type:
Boolean
-
-
Click Create.
-
-
Click Save to confirm your changes.
Figure 25. Survey data object details
4.4. Designing the case definition
You design cases using the process designer in Business Central. Case design is the basis of case management and sets the specific goals and tasks for each case. The case flow can be modified dynamically during run time by adding dynamic tasks or processes. In this procedure, you will create this same case definition to familiarize yourself with the case definition design process.
The IT_Orders sample project in Business Central includes the following orderhardware business process case definition.
-
You have created a new case in Business Central. For more information, see Creating a new IT_Orders case project.
-
You have created the data objects. For more information, see Data objects.
-
In Business Central, go to Menu → Design → Projects and click IT_Orders_New.
-
Click Add Asset → Case Definition.
-
In the Create new Case definition window, add the following required information:
-
Case Definition: Input
orderhardware
. This is usually the subject of the case or project that is being case managed. -
Package: Select com.myspace.it_orders_new to specify the location that the case file is created in.
-
-
Click Ok to open the process designer.
-
Define values for the case file variables that are accessible to the sub-processes, subcases, and business rules used in the case.
-
In the upper-right corner, click the Properties icon.
-
Scroll down and expand Case Management, click in the Case File Variables section, and enter the following:
Figure 27. orderhardware case file variables
The following case file variables are custom data types:
-
hwSpec: org.jbpm.document.Document (type in this value)
-
survey: Survey [com.myspace.it_orders_new] (select this value)
-
-
Click Save.
-
Define the roles involved in the case.
-
In the upper-right corner, click the Properties icon.
-
Scroll down and expand Case Management, click in the Case Roles section, and enter the following:
Figure 28. orderhardware case roles-
owner
: The employee who is making the hardware order request. The role cardinality is set to1
, which means that only one person or group can be assigned to this role. -
manager
: The employee’s manager; the person who will approve or deny the requested hardware. The role cardinality is set to1
, which means that only one person or group can be assigned to this role. -
supplier
: The available suppliers of IT hardware in the system. The role cardinality is set to2
, which means that more than one supplier can be assigned to this role.
-
-
-
Click Save.
4.4.1. Creating the Place order sub-process
Create the Place order
sub-process, which is a separate business process that is carried out by the supplier. This is a reusable process that occurs during the course of case execution as described in Designing the case definition.
-
You have created a new case in Business Central. For more information, see Creating a new IT_Orders case project.
-
You have created the data objects. For more information, see Data objects.
-
In Business Central, go to Menu → Design → Projects → IT_Orders_New.
-
From the project menu, click Add Asset → Business Process.
-
In the Create new Business Process wizard, enter the following values:
-
Business Process:
place-order
-
Package: Select
com.myspace.it_orders_new
-
-
Click Ok. The diagram editor opens.
-
Click an empty space in the canvas, and in the upper-right corner, click the Properties icon.
-
Scroll down and expand Process Data and click in the Process Variables section and enter the following:
-
Click Save.
-
Drag a start event onto the canvas and create an outgoing connection from the start event to a task and convert the new task to a user task.
-
Click the user task and in the Properties panel, input
Place order
in the Name field. -
Expand Implementation/Execution, click Add below the Groups menu, click Select → New, and input
supplier
. -
Click in the Assignments field and add the following:
For the first input assignment, select Custom for the Data Type and input
org.jbpm.document.Document
. -
Click OK.
-
Select the Skippable check box and enter the following text in the Description field:
Approved order #{CaseId} to be placed
-
Create an outgoing connection from the Place order user task and connect it to an end event.
-
Click Save to confirm your changes.
You can open the sub-process in a new editor in Business Central by clicking the Place order task in the main process and then clicking the Open Sub-process task icon.
4.4.2. Creating the Manager approval business process
The manager approval process determines whether or not the order will be placed or rejected.
-
In Business Central, go to Menu → Design → Projects → IT_Orders_New → orderhardware Business Processes.
-
Create and configure the
Prepare hardware spec
user task:-
Expand Tasks in the Object Library and drag a user task onto the canvas and convert the new task to a user task.
-
Click the new user task and click the Properties icon in the upper-right corner.
-
Input
Prepare hardware spec
in the Name field. -
Expand Implementation/Execution, click Add below the Groups menu, click Select → New, and input
supplier
. -
Input
PrepareHardwareSpec
in the Task Name field. -
Select the Skippable check box and enter the following text in the Description field:
Prepare hardware specification for #{initiator} (order number #{CaseId})
-
Click in the Assignments field and add the following:
-
Click OK.
-
-
Create and configure the manager approval user task:
-
Click the Prepare hardware spec user task and create a new user task.
-
Click the new user task and click the Properties icon in the upper-right corner.
-
Click the user task and in the Properties panel input
Manager approval
in the Name field. -
Expand Implementation/Execution, click Add below the Actors menu, click Select → New, and input
manager
. -
Input
ManagerApproval
in the Task Name field. -
Click in the Assignments field and add the following:
-
Click OK.
-
Select the Skippable check box and enter the following text in the Description field:
Approval request for new hardware for #{initiator} (order number #{CaseId})
-
Enter the following Java expression in the On Exit Action field:
kcontext.setVariable("caseFile_managerDecision", approved);
-
Click Save.
-
-
Click the Manager approval user task and create a Data-based Exclusive (XOR) gateway.
-
Create and configure the
Place order
reusable sub-process:-
From the Object Library, expand sub-processes, click Reusable, and drag the new element to the canvas on the right side of the Data-based Exclusive (XOR) gateway.
-
Connect the Data-based Exclusive (XOR) gateway to the sub-process.
-
Click the new sub task and click the Properties icon in the upper-right corner.
-
Input
Place order
in the Name field. -
Expand Data Assignments and click in the Assignments field and add the following:
-
Click OK.
-
Click the connection from the Data-based Exclusive (XOR) gateway to the sub-process and click the Properties icon.
-
Expand Implementation/Execution, select Condition, and set the following condition expressions.
-
Click the Place order user task and create an end event.
-
-
Create and configure the order rejected user task:
-
Click the Data-based Exclusive (XOR) gateway and create a new user task.
-
Drag the new task to align it below the Place order task.
-
Click the new user task and click the Properties icon in the upper-right corner.
-
Input
Order rejected
in the Name field. -
Expand Implementation/Execution and input
OrderRejected
in the Task Name field. -
Click Add below the Actors menu, click Select → New, and input
owner
. -
Click in the Assignments field and add the following:
-
Click OK.
-
Select the Skippable check box and enter the following text in the Description field:
Order #{CaseId} has been rejected by manager
-
Click the Order rejected user task and create an end event.
-
Click Save.
-
-
Click the connection from the Data-based Exclusive (XOR) gateway to the Order rejected user task and click the Properties icon.
-
Expand Implementation/Execution, select Condition, and set the following condition expressions.
-
Click Save.
Figure 29. Manager approval business process
4.5. Milestones
Milestones are a special service task that can be configured in the case definition designer by adding the milestone node to the process designer palette. When creating a new case definition, a milestone configured as AdHoc Autostart
is included on the design palette by default. Newly created milestones are not set to AdHoc Autostart
by default.
Case management milestones generally occur at the end of a stage, but they can also be the result of achieving other milestones. A milestone always requires a condition to be defined in order to track progress. Milestones react to case file data when data is added to a case. A milestone represents a single point of achievement within the case instance. It can be used to flag certain events, which can be useful for Key Performance Indicator (KPI) tracking or identifying the tasks that are still to be completed.
Milestones can be in any of the following states during case execution:
-
Active
: The condition has been defined on the milestone but it has not been met. -
Completed
: The milestone condition has been met, the milestone has been achieved, and the case can proceed to the next task. -
Terminated
: The milestone is no longer a part of the case process and is no longer required.
While a milestone is available or completed it can be triggered manually by a signal or automatically if AdHoc Autostart
is configured when a case instance starts. Milestones can be triggered as many times as required, however, it is directly achieved when the condition is met.
4.5.1. Creating the Hardware spec ready milestone
Create a HardwareSpecReady milestone that is reached when the required hardware specification document is completed.
-
In the process designer, expand Milestone in the Object Library and drag a new milestone on the canvas and place it on the right side of the Place order end event.
-
Click the new milestone and click the Properties icon in the upper-right corner.
-
Input
Hardware spec ready
in the Name field. -
Expand Implementation/Execution and select AdHoc Autostart.
-
Expand Data Assignments, click in the Assignments field, and add the following:
Click the Source column drop-down, select Constant, and input
org.kie.api.runtime.process.CaseData(data.get("hwSpec") != null)
. -
Click OK.
4.5.2. Creating the Manager decision milestone
This milestone is reached when the managerDecision
variable has been given a response.
-
In the process designer, expand Milestone in the Object Library and drag a new milestone onto the canvas below the HardwareSpecReady milestone.
-
Click the new milestone and click the Properties icon in the upper-right corner.
-
Input
Manager decision
in the Name field. -
Expand Implementation/Execution and select AdHoc Autostart.
-
Expand Data Assignments and click in the Assignments field and add the following:
Click the Source column drop-down, select Constant, and input
org.kie.api.runtime.process.CaseData(data.get("managerDecision") != null)
. -
Click OK.
4.5.3. Creating the Order placed milestone
This milestone is reached when the ordered
variable, which is part of the Place order sub-process, has been given a response.
-
In the process designer, expand Milestone in the Object Library and drag a new milestone on the canvas below the Prepare hardware spec user task.
-
Click the new milestone and click the Properties icon in the upper-right corner.
-
Input
Milestone 1: Order placed
in the Name field. -
Expand Implementation/Execution and select AdHoc Autostart.
-
Expand Data Assignments, click in the Assignments field, and add the following:
Click the Source column drop-down, select Constant, and input
org.kie.api.runtime.process.CaseData(data.get("ordered") == true)
. This means that a case variable namedordered
exists with the valuetrue
. -
Click OK.
-
Click Milestone 1: Order placed and create a new script task.
-
Click the new script task and click the Properties icon in the upper-right corner.
-
Input
Notify requestor
in the Name field. -
Expand Implementation/Execution and input
System.out.println("Notification::Order placed");
. -
Click the Notify requestor script task and create a signal end event.
-
Click the signal event and in the upper-right corner click the Properties. icon.
-
Expand Implementation/Execution, click the down arrow in the Signal field, and select New.
-
Input
Milestone 2: Order shipped
. -
Click the down arrow in the Signal Scope field, select Process Instance.
-
Click Save.
Figure 30. Order placed milestone
4.5.4. Creating the Order shipped milestone
The condition for this milestone is that a case file variable named shipped
is true
. AdHoc Autostart
is not enabled for this milestone. Instead, it is triggered by a signal event when the order is ready to be sent.
-
In the process designer, expand Milestone in the Object Library and drag a new milestone on the canvas below the Notify requestor script task.
-
Click the new milestone and click the Properties icon in the upper-right corner.
-
Input
Milestone 2: Order shipped
in the Name field. -
Expand Implementation/Execution and ensure that AdHoc Autostart is not selected.
-
Expand Data Assignments, click in the Assignments field, and add the following:
Click the Source column drop-down, select Constant, and input
org.kie.api.runtime.process.CaseData(data.get("shipped") == true)
. This means that a case variable namedshipped
exists with the valuetrue
. -
Click OK.
-
Click Milestone 2: Order shipped and create a new script task.
-
Click the new script task and click the Properties icon in the upper-right corner.
-
Input
Send to tracking system
in the Name field. -
Expand Implementation/Execution and input
System.out.println("Order added to tracking system");
. -
Click the Send to tracking system script task and create a signal end event.
-
Click the signal event and in the upper-right corner click the Properties. icon.
-
Expand Implementation/Execution, click the down arrow in the Signal field, and select New.
-
Input
Milestone 3: Delivered to customer
. -
Click the down arrow in the Signal Scope field, select Process Instance.
-
Click Save.
Figure 31. Order shipped milestone
4.5.5. Creating the Delivered to customer milestone
The condition for this milestone is that a case file variable named delivered
is true
. AdHoc Autostart
is not enabled for this milestone. Instead, it is triggered by a signal event after the order has successfully shipped to the customer.
-
In the process designer, expand Milestone in the Object Library and drag a new milestone on the canvas below the Send to tracking system script task.
-
Click the new milestone and click the Properties icon in the upper-right corner.
-
Input
Milestone 3: Delivered to customer
in the Name field. -
Expand Implementation/Execution and ensure that AdHoc Autostart is not selected.
-
Expand Data Assignments, click in the Assignments field, and add the following:
Click the Source column drop-down, select Constant, and input
org.kie.api.runtime.process.CaseData(data.get("delivered") == true)
. This means that a case variable nameddelivered
exists with the valuetrue
. -
Click OK.
-
Click Milestone 3: Delivered to customer and create a new user task.
-
Click the new user task and click the Properties icon in the upper-right corner.
-
Input
Customer satisfaction survey
in the Name field. -
Expand Implementation/Execution, click Add below the Actors menu, click Select → New, and input
owner
. -
Input
CustomerSurvey
in the Task Name field. -
Select the Skippable check box and enter the following text in the in the Description field:
Satisfaction survey for order #{CaseId}
-
Click in the Assignments field and add the following:
-
Click OK.
-
-
Click the Customer satisfaction survey user task and create an end event.
-
Click Save to confirm your changes.
Figure 32. Delivered to customer milestone
The IT Orders case can be closed after all milestone sequences are completed. However, due to the ad hoc nature of cases, the case could be reopened if, for example, the order was never received by the customer or the item is faulty. Tasks can be re-triggered or added to the case definition as required, even during run time.
4.6. Deploying and testing the IT order case project
After you create and define all components of the new IT_Orders_New
case project, deploy and test the new project.
-
You have a running KIE Server instance connected to Business Central. For more information see Installing and configuring jBPM on Red Hat JBoss EAP 7.4.
-
You have created a new case in Business Central. For more information, see Creating a new IT_Orders case project.
-
You have created the data objects. For more information, see Data objects.
-
You have created the
Place order
sub-process. For more information, see Creating the Place order sub-process. -
You have designed the
orderhardware
case definition. For more information, see Designing the case definition.
-
In Business Central, go to Menu → Design → Projects and click IT_Orders_New.
-
Click Deploy.
-
Go to Menu → Manage → Process Definitions → Manage Process Instances → New Process Instance.
-
Go to Menu → Deploy and click Execution Servers and verify that a new container is deployed and started.
-
Use the Case Management Showcase application to start a new case instance. For instructions about using the Showcase application, see Using the Showcase application for case management.
5. Business applications
5.1. Overview
Business application can be defined as an automated solution, built with selected frameworks and capabilities that implements business functions and/or business problems. Capabilities can be (among others):
-
persistence
-
messaging
-
transactions
-
business processes, business rules
-
planning solutions
Business application is more of a logical grouping of individual services that represent certain business capabilities. Usually they are deployed separately and can also be versioned individually. Overall goal is that the complete business application will allow particular domain to achieve their business goals e.g. order management, accommodation management, etc.
-
Build on any runtime (most popular options)
-
SpringBoot
-
WildFly
-
Quarkus
-
-
deployable to cloud with just single command
-
OpenShift
-
Kubernetes
-
Docker
-
-
UI agnostic
-
Doesnāt enforce any UI frameworks and let users to make their own choice
-
-
Configurable database profiles
-
to allow smooth transition from one database to another with just single parameter/switch
-
-
Generated
-
makes it really easy to start for developers so they donāt get upset with initial failures usually related to configuration
-
-
Many project
-
data model project - shared data model between business assets and service
-
business assets (kjar) project - easily importable into Business Central
-
service project - actual service with various capabilities
-
-
Configuration for
-
maven repository - settings.xml
-
database profiles
-
deployment setup
-
local
-
docker
-
OpenShift
-
-
Service project is the one that is deployable but will in most of the cases include business assets and data model projects. Data model project represents the common data structures that will be shared between service implementation and business assets. That enables proper encapsulation and promotes reuse and at the same time reduces shortcuts to make data model classes something more than they are - include too much of implementation into data models.
Business applications you build are not restricted to having only one of each project types. In order to build the solutions you need your business app can:
-
Have multiple data model projects - each service project can expose its own public data model
-
Have multiple business assets (kjar) projects - in case there is a business need for it
-
Have multiple service projects - to split services into smaller components for better manageability
-
Have UI modules - either per service (embedded in the service project) or a federated one (separate project for UI only)
-
Service projects can communicate with each other either directly or via business processes
Following diagram represents the sample business application
5.2. Create your business application
Business application can be created in multiple ways, depending on the project types you need.
5.2.1. Generate business application
The fastest and recommended way to quickly generate your business application is by using the jBPM online service: start.jbpm.org
With the online service you can:
-
generate your business app using a default (most commonly used) configuration
-
configure your business application to include specific features that you need
The generated application will be delivered as a zip archive will following structure
To provide more information about individual steps, let’s review different options that user can choose from
5.2.1.1. Capabilities
Capabilities essentially define the features that your business application will be equipped with. Available options are:
-
Business automation covers features for process management, case management, decision management and optimisation. These will be by default configured in the service project of your business application. Although you can turn them off via configuration.
-
Decision management covers mainly decision and rules related features (backed by Drools project)
-
Business optimisation covers planning problems and solutions related features (backed by OptaPlanner project)
5.2.1.2. Application information
General information about the application that is
-
name - the name that will be used for the projects generated
-
package - valid Java package name that will be created in the projects and used as group of maven projects
-
version - selected version of jBPM/KIE that should be used for service project
5.2.1.3. Project types
Selection of project types to be included in the business application
-
data model - basic maven/jar project to keep the data structures
-
business assets - kjar project that can be easily imported into Business Central for development
-
service - service project that will include chosen capabilities with all bits configured
5.2.2. Manually create business application
In case you can’t use jBPM online service to generate the application you can manually create individual projects. jBPM provides maven archetypes that can be easily used to generate the application. In fact jBPM online service uses these archetypes behind the scenes to generate business application.
Business assets project archetype
org.kie:kie-kjar-archetype:7.59.0.Final
Service project archetype
org.kie:kie-service-spring-boot-archetype:7.59.0.Final
Data model archetype
org.apache.maven.archetypes:maven-archetype-quickstart:1.3
Example that allows to generate all three types of projects
mvn archetype:generate -B -DarchetypeGroupId=org.kie -DarchetypeArtifactId=kie-model-archetype -DarchetypeVersion=7.59.0.Final -DgroupId=com.company -DartifactId=test-model -Dversion=1.0-SNAPSHOT -Dpackage=com.company.model
mvn archetype:generate -B -DarchetypeGroupId=org.kie -DarchetypeArtifactId=kie-kjar-archetype -DarchetypeVersion=7.59.0.Final -DgroupId=com.company -DartifactId=test-kjar -Dversion=1.0-SNAPSHOT -Dpackage=com.company
mvn archetype:generate -B -DarchetypeGroupId=org.kie -DarchetypeArtifactId=kie-service-spring-boot-archetype -DarchetypeVersion=7.59.0.Final -DgroupId=com.company -DartifactId=test-service -Dversion=1.0-SNAPSHOT -Dpackage=com.company.service -DappType=bpm
When generating projects from the archetypes in same directory you should end up with exactly the same structure as generated by jBPM online service.
5.3. Run your business application
Once your business application is created, the next step is to actually run it.
5.3.1. Launch application
By default business application has a single runnable project - that is the service project. The service project is equipped with two scripts (both for linux and windows)
-
launch.sh/launch.bat
-
launch-dev.sh/launch-dev.bat
the main difference between these two scripts is the target execution
-
launch.sh/bat is dedicated to start application in standalone mode, without additional requirements.
-
launch-dev.sh/bat is dedicated to start application in sort of development mode (in other words managed mode) so it will require Business Central to be available as jBPM controller.
Development mode is meant to allow people to work on the business assets projects and dynamically deploy changes to the business application without the need to restart it. At the same time it provides a complete monitoring environment over business automation capabilities (process instances, tasks, jobs, etc).
To launch your application just go into service project ({your business application name}-service) and invoke
./launch.sh clean install
for Linux/Unix
./launch.bat clean install
for Windows
the clean install
part of the command is to tell maven how to build. It will then
build projects in following order
-
Data model
-
Business assets
-
Service
the first time it might take a while as it will download all dependencies of the project. At the end of the build it will start the application and after few seconds you should see output similar to following..,
INFO o.k.s.s.a.KieServerAutoConfiguration : KieServer (id business-application-service (name business-application-service)) started initialization process
INFO o.k.server.services.impl.KieServerImpl : Server Default Extension has been successfully registered as server extension
INFO o.k.server.services.impl.KieServerImpl : Drools KIE Server extension has been successfully registered as server extension
INFO o.k.server.services.impl.KieServerImpl : DMN KIE Server extension has been successfully registered as server extension
INFO o.k.s.api.marshalling.MarshallerFactory : Marshaller extensions init
INFO o.k.server.services.impl.KieServerImpl : jBPM KIE Server extension has been successfully registered as server extension
INFO o.k.server.services.impl.KieServerImpl : Case-Mgmt KIE Server extension has been successfully registered as server extension
INFO o.k.server.services.impl.KieServerImpl : jBPM-UI KIE Server extension has been successfully registered as server extension
INFO o.k.s.s.impl.policy.PolicyManager : Registered KeepLatestContainerOnlyPolicy{interval=0 ms} policy under name KeepLatestOnly
INFO o.k.s.s.impl.policy.PolicyManager : Policy manager started successfully, activated policies are []
INFO o.k.server.services.impl.KieServerImpl : Selected startup strategy ControllerBasedStartupStrategy - deploys kie containers given by controller ignoring locally defined
INFO o.k.s.services.impl.ContainerManager : About to install containers '[]' on kie server 'KieServer{id='business-application-service'name='business-application-service'version='7.9.0.Final'location='http://localhost:8090/rest/server'}'
INFO o.k.server.services.impl.KieServerImpl : KieServer business-application-service is ready to receive requests
INFO o.k.s.s.a.KieServerAutoConfiguration : KieServer (id business-application-service) started successfully
INFO o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
INFO s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8090 (http)
INFO c.c.b.service.Application : Started Application in 14.534 seconds (JVM running for 15.193)
and you should be able to access your business application at http://localhost:8090/
5.3.2. Launch application in development mode
Development mode requires Business Central to be available, by default at http://localhost:8080/business-central. The easiest way to get that up and running is to use jBPM single distribution that can be downloaded at jbpm.org Look at the Getting Started guide to get yourself familiar with Business Central. |
Make sure you have Business Central up and running before launching your business application in development mode.
5.3.3. Import your business assets project into Business Central
Business assets projects that was just created can be easily imported into Business Central as soon as it’s a valid git repository. To make it as such
-
Go into business assets project - {your business application name}-kjar
-
Execute
git init
-
Execute
git add -A
-
Execute
git commit -m "Initial project structure"
-
Log in to Business Central and go to projects
-
Select import project and enter the following URL
file:///{path to your business application}/{your business application name}-kjar
-
Click import and confirm project to be imported
5.3.3.1. Work on your business assets
Once the business assets project is imported into Business Central you can start working on it. Just go to the project and add assets such as business process, rules, decision tables etc.
5.3.3.2. Launch business application in development mode
To launch your application just go into service project ({your business application name}-service) and invoke
./launch-dev.sh clean install
for Linux/Unix
./launch-dev.bat clean install
for Windows
this should print the first entry after the build as follows
Launching the application in development mode - requires connection to controller (Business Central)
and similar as to launching in the standalone more after couple of seconds should be able to access your business application at http://localhost:8090/
Once the application started, it should be successfully connect to jBPM controller and by that be visible in the servers perspective of Business Central.
5.3.3.3. Deploy business assets project into running business application
After adding assets to your project in Business Central you can just deploy it to a running server instance.
Click the Deploy
button on your project and in few seconds you should see the
project deployed on your business application.
You can use Process Definitions and Process Instance perspectives of Business Central to interact with your newly deployed business assets such as processes or user tasks.
5.4. Configure business application
There are several components that can be configured in the business application. Depending on selected capabilities during application generation, a number of components can differ.
Entire configuration of the business application (service project) is done via application.properties
file that is a standard way to configure SpringBoot applications. It is located under the
src/main/resources
directory of {your business application}-service folder.
5.4.1. Configuring core components
5.4.1.1. Configuring server
One of the most important configuration is actually the server itself. That is the host, port and path for the REST endpoints.
# used for server binding
server.address=localhost
server.port=8090
# used to define path for REST apis
cxf.path=/rest
5.4.1.2. Configure authentication and authorization
Business application is secured by default by protecting all REST endpoints
(URL pattern /rest/*
).
Authentication is enabled for single test user named user
with password user
.
Additionally there is a default kieserver
user that allows to easily connect to
Business Central in development mode.
Both authentication and authorization is based on Spring Security and can be
configured in DefaultWebSecurityConfig.java
that is included in the generated
service project (src/main/java/com/company/service/DefaultWebSecurityConfig.java
)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration("kieServerSecurity")
@EnableWebSecurity
public class DefaultWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/rest/*").authenticated()
.and()
.httpBasic();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("user").roles("kie-server");
auth.inMemoryAuthentication().withUser("kieserver").password("kieserver1!").roles("kie-server");
}
}
This security configuration is just starting point and should be altered for all business applications going to production like setup. |
Use Keycloak as authentication provider
Configuring business applications to use Keycloak as authentication and authorisation requires few steps
-
Install Keycloak - follow official documentation at keycloak.org
-
Configure Keycloak once started
-
Use default master realm or create new one
-
Create client named springboot-app and set its AccessType to public
-
Set Valid redirect URI and Web Origin according to your local setup - with default setup they should be set to
-
Valid Redirect URIs: http://localhost:8090/*
-
Web Origins: http://localhost:8090
-
Create realm roles that are used in the application
-
Create users used in the application and assign roles to them
-
-
Configure dependencies in service project pom.xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.keycloak.bom</groupId>
<artifactId>keycloak-adapter-bom</artifactId>
<version>${version.org.keycloak}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
....
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>
Business application includes jBPM (KIE) execution server that can be configured to be better identified
kieserver.serverId=business-application-service
kieserver.serverName=business-application-service
kieserver.location=http://localhost:8090/rest/server
kieserver.controllers=http://localhost:8080/business-central/rest/controller
-
Configure application.properties
# keycloak security setup
keycloak.auth-server-url=http://localhost:8100/auth
keycloak.realm=master
keycloak.resource=springboot-app
keycloak.public-client=true
keycloak.principal-attribute=preferred_username
keycloak.enable-basic-auth=true
-
Modify
DefaultWebSecurityConfig.java
to ensure that Spring Security will work correctly with Keycloak
import org.keycloak.adapters.KeycloakConfigResolver;
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
@Configuration("kieServerSecurity")
@EnableWebSecurity
public class DefaultWebSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
SimpleAuthorityMapper mapper = new SimpleAuthorityMapper();
mapper.setPrefix("");
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(mapper);
auth.authenticationProvider(keycloakAuthenticationProvider);
}
@Bean
public KeycloakConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
}
These are the steps to configure you business application to use Keycloak as authentication and authorisation service.
5.4.1.3. Configuring execution server
server id and server name refer to how the business application will be identified when connecting to the jBPM controller (Business Central) and thus should provide as meaningful information as possible.
location is used to inform other components that might interact with REST api where the execution server is accessible. It should not be the exact same location as defined by server.address and server.port especially when running in containers (Docker/OpenShift).
controllers allows to specify a (comma separated) list of URLs.
5.4.1.4. Configuring capabilities
In case your business application selected 'Business Automation' as the capability then there you can control which of them should actually be turned on on runtime.
# used for decision management
kieserver.drools.enabled=true
kieserver.dmn.enabled=true
# used for business processes and cases
kieserver.jbpm.enabled=true
kieserver.jbpmui.enabled=true
kieserver.casemgmt.enabled=true
# used for planning
kieserver.optaplanner.enabled=true
5.4.1.5. Configuring data source
Data source configuration is only required for business automation (meaning when jBPM is used) |
spring.datasource.username=sa
spring.datasource.password=sa
spring.datasource.url=jdbc:h2:./target/spring-boot-jbpm;MVCC=true
spring.datasource.driver-class-name=org.h2.Driver
Above configures shows the basic data source settings, next section will deal with connection pooling for efficient data access.
Depending on the driver class selected, make sure your application adds correct dependency that include the JDBC driver class or data source class. |
narayana.dbcp.enabled=true
narayana.dbcp.maxTotal=20
this configuration enables the data source connection pool (that is based on
commons-dbcp2 project) and a complete list of parameters can be found on
configuration page.
All parameters from the configuration page must be prefixed with narayana.dbcp.
5.4.1.6. Configuring JPA
jBPM uses Hibernate as the database access layer and thus needs to be properly configured
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.properties.hibernate.show_sql=false
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
JPA configuration is completely based on SpringBoot so all options for both hibernate and JPA can be found as SpringBoot configuration page |
Application with business automation capability creates entity manager factory based on persistence.xml that comes with jBPM. In case there are more entities that should be added to this entity manager factory (e.g. custom entities for the business application) they can easily be added by specifying a comma separated list of packages to scan
spring.jpa.properties.entity-scan-packages=org.jbpm.springboot.samples.entities
All entities found in that package will be automatically added to entity manager factory and thus used in the same manner as any other JPA entity in the application.
5.4.1.7. Configuring jBPM executor
jBPM executor is the backbone for asynchronous execution in jBPM. By default it is disabled, but can easily be turned on by configuration parameters.
jbpm.executor.enabled=true
jbpm.executor.retries=5
jbpm.executor.interval=0
jbpm.executor.threadPoolSize=1
jbpm.executor.timeUnit=SECONDS
-
jbpm.executor.enabled = true|false - allows to completely disable executor component
-
jbpm.executor.threadPoolSize = Integer - allows to specify thread pool size where default is 1
-
jbpm.executor.retries = Integer - allows to specify number of retries in case of errors while running a job
-
jbpm.executor.interval = Integer - allows to specify interval (by default in seconds) that executor will use to synchronize with database - default is 0 seconds which means it is disabled
-
jbpm.executor.timeUnit = String - allows to specify timer unit used for calculating interval, value must be a valid constant of java.util.concurrent.TimeUnit, by default it’s SECONDS.
5.4.1.8. Configuring distributed timers - Quartz
In case you plan to run your application in a cluster (multiple instances of it at the same time) then you need to take into account the timer service setup. Since the business application is running on top of Tomcat web container the only option for timer service for distributed setup is Quartz based.
jbpm.quartz.enabled=true
jbpm.quartz.configuration=quartz.properties
Above are two mandatory parameters and the configuration file that need to be either on the classpath or on the file system (if the path is given).
For distributed timers database storage should be used and properly configured via quartz.properties file.
#============================================================================
# Configure Main Scheduler Properties
#============================================================================
org.quartz.scheduler.instanceName = SpringBootScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.skipUpdateCheck=true
org.quartz.scheduler.idleWaitTime=1000
#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 5
#============================================================================
# Configure JobStore
#============================================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreCMT
org.quartz.jobStore.driverDelegateClass=org.jbpm.process.core.timer.impl.quartz.DeploymentsAwareStdJDBCDelegate
org.quartz.jobStore.useProperties=false
org.quartz.jobStore.dataSource=myDS
org.quartz.jobStore.nonManagedTXDataSource=notManagedDS
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=true
org.quartz.jobStore.clusterCheckinInterval = 5000
#============================================================================
# Configure Datasources
#============================================================================
org.quartz.dataSource.myDS.connectionProvider.class=org.jbpm.springboot.quartz.SpringConnectionProvider
org.quartz.dataSource.myDS.dataSourceName=quartzDataSource
org.quartz.dataSource.notManagedDS.connectionProvider.class=org.jbpm.springboot.quartz.SpringConnectionProvider
org.quartz.dataSource.notManagedDS.dataSourceName=quartzNotManagedDataSource
Data source names in quartz configuration file refer to Spring beans. Additionally
connection provider needs to be set to org.jbpm.springboot.quartz.SpringConnectionProvider
to allow integration with Spring based data sources.
|
By default Quartz requires two data sources:
-
managed data source so it can participate in transaction of the jBPM engine
-
not managed data source so it can look up for timers to trigger without any transaction handling
jBPM based business application assumes that quartz database (schema) will be collocated with jBPM tables and by that produces data source used for transactional operations for Quartz.
The other (non transactional) data source needs to be configured but it should point to the same database as the main data source.
# enable to use database as storage
jbpm.quartz.db=true
quartz.datasource.name=quartz
quartz.datasource.username=sa
quartz.datasource.password=sa
quartz.datasource.url=jdbc:h2:./target/spring-boot-jbpm;MVCC=true
quartz.datasource.driver-class-name=org.h2.Driver
# used to configure connection pool
quartz.datasource.dbcp2.maxTotal=15
# used to initialize quartz schema
quartz.datasource.initialization=true
spring.datasource.schema=classpath*:quartz_tables_h2.sql
spring.datasource.initialization-mode=always
The last three lines of the above configuration is responsible for initialising database schema automatically. When configured it should point to a proper DDL script.
5.4.1.9. Configuring different databases
Business application is generated with default H2 database - just to get started quickly and without any extra requirements. Since this default setup may not valid for production use the generated business applications come with configuration dedicated to:
-
MySQL
-
PostgreSQL
There are dedicated profiles - both Maven and Spring to get you started really fast without much work. The only thing you need to do is to alight the configuration with your databases.
MySQL configuration
spring.datasource.username=jbpm
spring.datasource.password=jbpm
spring.datasource.url=jdbc:mysql://localhost:3306/jbpm
spring.datasource.driver-class-name=com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
#hibernate configuration
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
PostgreSQL configuration
spring.datasource.username=jbpm
spring.datasource.password=jbpm
spring.datasource.url=jdbc:postgresql://localhost:5432/jbpm
spring.datasource.driver-class-name=org.postgresql.xa.PGXADataSource
#hibernate configuration
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
Once the updates to the configuration are done you can launch your application via
./launch.sh clean install -Pmysql
for MySQL on Linux/Unix
./launch.bat clean install -Pmysql
for MySQL on Windows
./launch.sh clean install -Ppostgres
for MySQL on Linux/Unix
./launch.bat clean install -Ppostgres
for MySQL on Windows
5.4.1.10. Configuring user group providers
Business automation capability supports human centric activities to be managed, to provide integration with user and group repositories there is a built in mechanism in jBPM. There are two entry points
-
UserGroupCallback
- responsible for verification if user/group exists and for collecting groups for given user -
UserInfo
- responsible for collecting additional information about user/group such as email address, preferred language, etc
Both of these can be configured by providing alternative implementation - either one of the provided out of the box or custom developed.
When it comes to UserGroupCallback
it is recommended to stick to the default one as it is based on the security
context of the application. That means whatever backend store is used for authentication and authorisation
(e.g. Keycloak) it will be used as source information for collecting user/group information.
UserInfo
requires more advanced information to be collected and thus is a separate component. Not all user/group repositories will
provide expect data especially those that are purely used for authentication and authorisation.
Following code is needed to provide alternative implementation of UserGroupCallback
@Bean(name = "userGroupCallback")
public UserGroupCallback userGroupCallback(IdentityProvider identityProvider) throws IOException {
return new MyCustomUserGroupCallback(identityProvider);
}
Following code is needed to provide alternative implementation of UserInfo
@Bean(name = "userInfo")
public UserInfo userInfo() throws IOException {
return new MyCustomUserInfo();
}
5.4.1.11. Enable Swagger documentation
Business application can easily enable Swagger based documentation for all endpoints available in the service project.
Add required dependencies to service project pom.xml
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-service-description-swagger</artifactId>
<version>3.1.11</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jaxrs</artifactId>
<version>1.5.15</version>
<exclusions>
<exclusion>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
</exclusion>
</exclusions>
</dependency>
Enable Swagger support in application.properties
kieserver.swagger.enabled=true
Swagger document can be found at http://localhost:8090/rest/swagger.json
Enable Swagger UI
To enable Swagger UI add following dependency to pom.xml of the service project.
<dependency>
<groupId>org.webjars</groupId>
<artifactId>swagger-ui</artifactId>
<version>2.2.10</version>
</dependency>
Once the Swagger UI is enabled and server is started, complete set of endpoints can be found at http://localhost:8090/rest/api-docs/?url=http://localhost:8090/rest/swagger.json
5.5. Develop your business application
Developing custom logic in business application strictly depends on your specific requirements. In this guide we will provide some common steps that developers might need to get started.
5.5.1. Data model
The data model project in your generated business application promotes the idea (and best practice in fact) of designing data models with reuse in mind. At the same time it avoids putting too much in the model (which usually happens when model is colocated with the service itself).
Data model project should be seen as the API of the business application or one of its services. In case of application that is composed of several services it’s recommended that each service exposes its own data model (API).
That API then can be used by both service project and the business assets project.
Generated application model is not added as dependency to service nor business assets projects. |
5.5.2. Business assets development
Business assets are usually developed in Business Central, where developers can create different assets types such as
-
Business processes
-
Case definitions
-
Rules
-
Decision tables
-
Data objects
-
Forms
-
Others
Before these assets can be created the business assets project needs to be imported into Business Central as described in Import your business assets project into Business Central
Whenever working with business assets you can easily try them out in your business application by running the application in development mode. That allows developer to build and deploy the assets project directly to a running application. Moreover Business Central can also be used to quickly interact with processes, tasks and cases. To learn more see Launch application in development mode
Once the work on business assets is finished it should be fetch back to your business application source.
-
go into business assets project - {your business application name}-kjar
-
execute
git fetch origin
-
execute
git rebase origin/master
With this your business assets are now part of the business application source tree and can be launched in standalone mode - without Business Central as jBPM controller.
To launch your application just go into service project ({your business application name}-service) and invoke
./launch.sh clean install
for Linux/Unix
./launch.bat clean install
for Windows
In case the version of your business assets project changes you will have to update that information in the service project. Locate the configuration file that is used for standalone mode {your business application name}-service.xml Edit it and update the version for the specific container. |
Business assets project has two special files
-
pom.xml
-
src/main/resources/META-INF/kie-deployment-descriptor.xml
The first one is Apache Maven project file and is managed via Project Settings in Business Central. It allows to define project information (group id, artifact id, version, name, description). In addition it allows to define dependencies the project will have e.g. data model project.
Whenever dependencies are added from the following group ids they should be marked as scope provided
|
Deployment descriptor allows to configure various components of the business automation capability such as
-
Persistence for jBPM
-
Runtime strategy
-
Event listeners
-
Work item handlers
-
Marshalling strategies
-
And more
for complete description of the deployment descriptor see Deployment descriptor
5.5.3. Work Item Handlers
Business processes can take advantage of so-called domain specific services which are implemented as work items and their actual execution is carried out by work item handlers. Work items defined in the process or case definition are linked by name with work item handler (the implementation).
Work item handlers can be registered in three ways
-
via deployment descriptor - use this approach if you want to decouple life cycle of the handler from your business application
-
via auto registration of Spring Components - use this when you have your handlers implemented as Spring beans (components) that are bound to the life cycle of the application
-
via manual registration of any work handler implementation - use this when the handler is not implemented by you and thus there is no way to use the Spring Component approach or it has advanced initialisation logic that does not fit the deployment descriptor approach
5.5.3.1. Register Work Item Handler via deployment descriptor
Registration in deployment descriptor can be done directly in Business Central via Project settings → Deployments
Add the work item handler mapped to the name of the work item
this will result in following source code of the deployment descriptor
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<deployment-descriptor xsi:schemaLocation="http://www.jboss.org/jbpm deployment-descriptor.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<persistence-unit>org.jbpm.domain</persistence-unit>
<audit-persistence-unit>org.jbpm.domain</audit-persistence-unit>
<audit-mode>JPA</audit-mode>
<persistence-mode>JPA</persistence-mode>
<runtime-strategy>SINGLETON</runtime-strategy>
<marshalling-strategies/>
<event-listeners/>
<task-event-listeners/>
<globals/>
<work-item-handlers>
<work-item-handler>
<resolver>mvel</resolver>
<identifier>new org.jbpm.process.workitem.rest.RESTWorkItemHandler("user", "password", classLoader)</identifier>
<parameters/>
<name>Rest</name>
</work-item-handler>
</work-item-handlers>
<environment-entries/>
<configurations/>
<required-roles/>
<remoteable-classes/>
<limit-serialization-classes>true</limit-serialization-classes>
</deployment-descriptor>
5.5.3.2. Register Work Item Handler via auto registration of Spring Components
The easiest way to register work item handlers is to rely on Spring discovery and configuration
of beans. It’s enough to annotate your work item handler class with @Component("WorkItemName")
and that bean will be automatically registered in jBPM.
import org.kie.api.runtime.process.WorkItem;
import org.kie.api.runtime.process.WorkItemHandler;
import org.kie.api.runtime.process.WorkItemManager;
import org.springframework.stereotype.Component;
@Component("Custom")
public class CustomWorkItemHandler implements WorkItemHandler {
@Override
public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
manager.completeWorkItem(workItem.getId(), null);
}
@Override
public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
}
}
This will register CustomWorkItemHandler under Custom
name so every work item named Custom
will use that handler to execute it’s logic.
The name attribute of @Component annotations is mandatory for registration to happen.
In case the name is missing work item handler won’t be registered and warning will be logged.
|
5.5.3.3. Register Work Item Handler programmatically
Last resort option is to get hold of DeploymentService and register handlers programmatically
@Autowire
private SpringKModuleDeploymentService deploymentService;
...
@PostConstruct
public void configure() {
deploymentService.registerWorkItemHandler("Custom", new CustomWorkItemHandler());
}
5.5.4. Event listeners
jBPM allows to register various event listeners that will be invoked upon various events triggered by the jBPM engine. Supported event listener types are
-
ProcessEventListener
-
AgendaEventListener
-
RuleRuntimeEventListener
-
TaskLifeCycleEventListener
-
CaseEventListener
Similar to work item handlers, event listeners can be registered in three ways
-
via deployment descriptor - use this approach if you want to decouple life cycle of the listener from your business application
-
via auto registration of Spring Components - use this when you have your listeners implemented as Spring beans (components) that are bound to the life cycle of the application
-
via manual registration of any work handler implementation - use this when the listener is not implemented by you and thus there is no way to use the Spring Component approach or it has advanced initialisation logic that does not fit the deployment descriptor approach
5.5.4.1. Register event listener via deployment descriptor
Registration in deployment descriptor can be done directly in Business Central via Project settings → Deployments
this will result in following source code of the deployment descriptor
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<deployment-descriptor xsi:schemaLocation="http://www.jboss.org/jbpm deployment-descriptor.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<persistence-unit>org.jbpm.domain</persistence-unit>
<audit-persistence-unit>org.jbpm.domain</audit-persistence-unit>
<audit-mode>JPA</audit-mode>
<persistence-mode>JPA</persistence-mode>
<runtime-strategy>SINGLETON</runtime-strategy>
<marshalling-strategies/>
<event-listeners>
<event-listener>
<resolver>mvel</resolver>
<identifier>new org.jbpm.listeners.CustomProcessEventListener</identifier>
<parameters/>
</event-listener>
</event-listeners>
<task-event-listeners/>
<globals/>
<work-item-handlers/>
<environment-entries/>
<configurations/>
<required-roles/>
<remoteable-classes/>
<limit-serialization-classes>true</limit-serialization-classes>
</deployment-descriptor>
5.5.4.2. Register event listener via auto registration of Spring Components
The easiest way to register event listeners is to rely on Spring discovery and configuration
of beans. It’s enough to annotate your event listener implementation class with @Component()
and that bean will be automatically registered in jBPM.
import org.kie.api.event.process.ProcessCompletedEvent;
import org.kie.api.event.process.ProcessEventListener;
import org.kie.api.event.process.ProcessNodeLeftEvent;
import org.kie.api.event.process.ProcessNodeTriggeredEvent;
import org.kie.api.event.process.ProcessStartedEvent;
import org.kie.api.event.process.ProcessVariableChangedEvent;
import org.springframework.stereotype.Component;
@Component
public class CustomProcessEventListener implements ProcessEventListener {
@Override
public void beforeProcessStarted(ProcessStartedEvent event) {
}
...
}
Event listener can extend default implementation of given event listener to avoid
implementing all methods e.g. org.kie.api.event.process.DefaultProcessEventListener
|
Type of the event listeners is determined by the interface (or super class) it implements.
5.5.4.3. Register event listener programmatically
Last resort option is to get hold of DeploymentService and register handlers programmatically
@Autowire
private SpringKModuleDeploymentService deploymentService;
...
@PostConstruct
public void configure() {
deploymentService.registerProcessEventListener(new CustomProcessEventListener());
}
5.5.5. Custom REST endpoints
In many (if not all) cases there will be a need to expose additional REST endpoints for your business application (in your service project). This can be easily achieved by creating a JAX-RS compatible class (with JAX-RS annotations). It will automatically be registered with the running service when the following scanning option is configured in your apps application.properties config file:
cxf.jaxrs.classes-scan=true
cxf.jaxrs.classes-scan-packages=org.kie.server.springboot.samples.rest
The endpoint will be bound to the global REST api path defined in the cxf.path
property.
An example of a custom endpoint can be found below
package org.kie.server.springboot.samples.rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("extra")
public class AdditionalEndpoint {
@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response listContainers() {
return Response.ok().build();
}
}
5.6. Deploy business application
Business applications are designed to run in pretty much any environment but for production the usual target is cloud-based runtimes that allow scalability and operational efficiency.
Business application deployable components are composed of services. Every application consists of one or more services that are deployed in isolation and in many cases will follow different release cycle.
5.6.1. OpenShift deployment
Business applications can be easily deployed to OpenShift Container Platform. It’s as easy as starting the application locally, meaning by using launch.sh/bat scripts.
You need to have OpenShift installed (good choice for local installation is minishift) or remote installation that can be accessed over network. |
So first of all login to OpenShift Cluster
oc login -u system:admin
once successfully logged in following output (or similar) should be displayed
Logged into "https://192.168.64.2:8443" as "system:admin" using existing credentials.
You have access to the following projects and can switch between them with 'oc project <projectname>':
default
kube-public
kube-system
* myproject
openshift
openshift-infra
openshift-node
openshift-web-console
Using project "myproject".
To deploy your application as to OpenShift Container Platform just go into service project ({your business application name}-service) and invoke
./launch.sh clean install -Popenshift,h2
for Linux/Unix
./launch.bat clean install -Popenshift,h2
for Windows
The launch script will perform the build with openshift profile (see pom.xml in the business assets project and service project for details). The significant difference that is done for openshift is that the business assets project will generate an offline maven repository with the project itself and all its dependencies. Next this maven repository will be included in the image itself and maven (used by business automation capability) will work in offline mode - meaning no access to internet will be attempted.
Launching the application on OpenShift...
--> Found image ef440f7 (15 seconds old) in image stream "myproject/business-application-service" under tag "1.0-SNAPSHOT" for "business-application-service:1.0-SNAPSHOT"
* This image will be deployed in deployment config "business-application-service"
* Ports 8090/tcp, 8778/tcp, 9779/tcp will be load balanced by service "business-application-service"
* Other containers can access this service through the hostname "business-application-service"
--> Creating resources ...
deploymentconfig "business-application-service" created
service "business-application-service" created
--> Success
Application is not exposed. You can expose services to the outside world by executing one or more of the commands below:
'oc expose svc/business-application-service'
Run 'oc status' to view your app.
route "business-application-service" exposed
You can then go to OpenShift Web Console and look at the Overview of your project (myproject by default)
By clicking on the route url (in this case http://business-application-service-myproject.192.168.64.2.nip.io
)
you can go to the application already deployed and running.
5.6.2. Docker deployment
Business applications are by default configured with option to deploy service as docker container.
This is done in very similar way as launching the service locally - via launch.sh/bat script.
You must have Docker installed on your machine to make this work! |
To deploy your application as docker container just go into service project ({your business application name}-service) and invoke
./launch.sh clean install -Pdocker,h2
for Linux/Unix
./launch.bat clean install -Pdocker,h2
for Windows
When building with docker proper database profile needs to be selected as well - this is done via -Pdocker,{db} so the image and the application gets proper JDBC driver selected. |
The launch script will perform the build with docker profile (see pom.xml in the business assets project and service project for details). The significant difference that is done for docker container is that the business assets project will generate an offline maven repository with the project itself and all its dependencies. Next this maven repository will be included in the docker image itself and maven (used by business automation capability) will work in offline mode - meaning no access to internet will be attempted.
Once the build is complete launch script will directly create container and start it, this should be done once the following line is printed to console
Launching the application as docker container...
d40e4cdb662d3b1d9ddee27c5a843be31cb6e7dc4936b0fc1937ce8e48f440ae
the second line is the container id that can be later on used to interact with the container, for instance to follow the logs
docker logs -f d40e4cdb662d3b1d9ddee27c5a843be31cb6e7dc4936b0fc1937ce8e48f440ae
the business application will be accessible at the same port as configured by default that is 8090, simply go to http://localhost:8090 to see your application running as docker container.
5.6.3. Using external database
Currently business applications that require an external database need to provide the database in advance - before the application is launched and properly configured within the application configuration files.
Further releases will improve this by relying on docker compose/OpenShift templates.
5.7. Tutorials
5.7.1. My First Business Application
5.7.1.1. What will you do
You will build a simple but fully functional business application. Once you build it you will explore basic services exposed by the application.
5.7.1.2. What do you need
-
About 10 minutes of your time
-
Java (JDK) 8 or later
-
Maven 3.5.x
-
Access to the Internet
5.7.1.3. What should I do
To get started with business applications the easiest way is to generate the,.
Go to start.jbpm.org and click button
Generate default business application
.
This will generate and download a business-application.zip
file that will consists of
three projects
-
business-application-model
-
business-application-kjar
-
business-application-service
Unzip the business-application.zip
file into desired location and go into
business-application-service
directory. There you will find launch scripts
(for both linux/unix and windows).
./launch.sh clean install
for Linux/Unix
./launch.bat clean install
for Windows
Execute one applicable to your operating system and wait for it to finish.
It might take quite some time (depending on your network) as it will download bunch of dependencies required to execute both build and application itself. |
5.7.1.4. Results
Once the build and launch is complete you can open your browser http://localhost:8090 to see your first business application up and running.
It presents with a welcome screen that is mainly for verification purpose to illustrate that application started successfully.
You can point the browser to http://localhost:8090/rest/server to see the actual Business Automation capability services
By default all REST endpoints (url pattern /rest/*) are secured and require
authentication. Default user that can be used to logon is user with password user
|
Business Automation service supports three types of data format
-
XML (JAXB based)
-
JSON
-
XML (XStream based)
To display Business Automation capability service details in different format set HTTP headers
-
Accept: application/json for JSON format
-
Accept: application/xml for XML (JAXB based) format
-
X-KIE-ContentType: XSTREAM for XML (XStream based) format
5.7.1.5. Summary
Congratulations! you have just built and started your first business application.
5.7.1.6. Source code of the tutorial
Here is the complete source code of the tutorial.
5.7.2. Business Application with Business Assets
5.7.2.1. What will you do
You will enhance your business application with some business assets
-
business process (BPMN2)
and execute this business assets
-
via REST api of your business application
-
via Business Central UI
5.7.2.2. What do you need
-
About 15 minutes of your time
-
Java (JDK) 8 or later
-
Maven 3.5.x
-
Access to the Internet
-
Business Central deployed - see single distribution for instructions
5.7.2.3. What should I do
If you haven’t done it already, complete tutorial My First Business Application
.
Start Business Central (if not already started) and open your browser at
http://localhost:8080/business-central and logon as
user wbadmin
with password wbadmin
Import your business assets project into Business Central
-
Go into business assets project -
business-application-kjar
-
Execute
git init
-
Execute
git add -A
-
Execute
git commit -m "my business assets project"
-
Log in to Business Central and go to projects
-
Select import project and enter the following URL
file:///{path to your business application}/business-application-kjar
-
Click import and confirm project to be imported
Create Business Process
In browser where you logged into Business Central go to Projects. You will see your newly imported project named business-application-kjar, go into that project.
-
go into business-application-kjar project
-
click
Add asset
button -
select Business Process asset
-
provide name for this asset
-
create your business process
Sample business process could be a single user task that will be assigned to user wbadmin
.
Pull back your business assets to business application source code
-
Go to business-application-kjar
-
Execute
git remote add origin ssh://wbadmin@localhost:8001/MySpace/business-application-kjar
-
Execute
git pull origin master
- when prompted enterwbadmin
as password
Go to business-application-service
directory and launch the application
./launch.sh clean install
for Linux/Unix
./launch.bat clean install
for Windows
5.7.2.4. Results
Once the build and launch is complete you can open your browser http://localhost:8090
Next, point the browser to http://localhost:8090/rest/server/containers to see that your business assets project has been properly deployed and is running.
By default all REST endpoints (url pattern /rest/*) are secured and require
authentication. Default user that can be used to logon is wbadmin with password wbadmin
|
Next, point the browser to http://localhost:8090/rest/server/containers/business-application-kjar/processes to see business processes available for execution.
Execute business process
You can execute business process via REST api exposed by your business application (in fact by Business Automation capability).
URL: http://localhost:8090/rest/server/containers/business-application-kjar/processes/{processid}/instances
HTTP method: POST
Optionally HTTP headers can be set to change the format of data returned
-
Accept: application/json for JSON format
-
Accept: application/xml for XML (JAXB based) format
-
X-KIE-ContentType: XSTREAM for XML (XStream based) format
{processid} needs to be replaced with actual process id that is returned from the endpoint http://localhost:8090/rest/server/containers/business-application-kjar/processes
Remember that endpoints are protected so make sure you provide user name and password when making the request. |
In response to this request, a process instance id should be returned.
<long-type>
<value>1</value>
</long-type>
You can examine details of that process instance by pointing your browser to http://localhost:8090/rest/server/containers/business-application-kjar/processes/instances/1
<process-instance>
<process-instance-id>1</process-instance-id>
<process-id>business-application-kjar.process</process-id>
<process-name>process</process-name>
<process-version>1.0</process-version>
<process-instance-state>1</process-instance-state>
<container-id>business-application-kjar-1_0-SNAPSHOT</container-id>
<initiator>wbadmin</initiator>
<start-date>2018-09-14T11:39:39.622+02:00</start-date>
<process-instance-desc>process</process-instance-desc>
<correlation-key>1</correlation-key>
<parent-instance-id>-1</parent-instance-id>
<sla-compliance>0</sla-compliance>
<active-user-tasks>
<task-summary>
<task-id>1</task-id>
<task-name>Task</task-name>
<task-description/>
<task-status>Reserved</task-status>
<task-priority>0</task-priority>
<task-actual-owner>wbadmin</task-actual-owner>
<task-created-by>wbadmin</task-created-by>
<task-created-on>2018-09-14T11:39:39.661+02:00</task-created-on>
<task-activation-time>2018-09-14T11:39:39.661+02:00</task-activation-time>
<task-proc-inst-id>1</task-proc-inst-id>
<task-proc-def-id>business-application-kjar.process</task-proc-def-id>
<task-container-id>business-application-kjar-1_0-SNAPSHOT</task-container-id>
</task-summary>
</active-user-tasks>
</process-instance>
Execute business process from Business Central UI
Stop the application if it’s running.
Go to business-application-service
directory and launch the application in development mode
./launch-dev.sh clean install
for Linux/Unix
./launch-dev.bat clean install
for Windows
this will connect your business application to Business Central so can be administered from within its UI.
Go to Business Central in the browser and navigate to servers (from the home screen).
As you can see the business-application-service Dev
is there and connected. Although
it does not have any kjars deployed. This is because it’s now running in managed mode
meaning it’s Business Central that decides what kjars it should run.
So let’s deploy the business-application-kjar to our running application.
-
Go to projects from home screen of Business Central
-
Go into business-application-kjar project
-
Click
Deploy
button -
Make sure that
Server configuration
is set tobusiness-application-service-dev
and click ok
The project should be successfully deployed and you can examine that state by going back to servers from home screen.
Next, go to process definitions (in Manage section of the Home screen) and select server configuration
(top right corner) - again it should be business-application-service-dev
the list of available
process definition will be loaded and you should see your single process definition from the project
business-application-kjar
.
Examine details of that process definition by clicking on the row in the table. Switch to
Diagram
tab to see the visual representation of your process definition.
Start new instance of the business process by clicking on New instance
button. This will bring up
form (depending on your process definition) it might or might not have any fields. Just click on
Submit
button to start process instance.
Once started process instance details will be opened, you can examine different sections to learn more about your active process instance
-
Instance details - base information about process instance
-
Process variables - latest values for process variables
-
Documents - list of documents managed by the process
-
Logs - detailed logs about what has been done within the process instance
-
Diagram - annotated diagram with completed (greyed out) and active (red borders) nodes
To look at user tasks, go to task inbox (in Track section of the Home screen). List of available tasks will be presented. This time there is no need to select server configuration because Business Central keeps track of recently selected configuration on different screens.
5.7.2.5. Summary
Congratulations! you have enhanced your business application to actually do something - execute business processes. At the same time you have created your first business process and made successful integration between your business application and Business Central.
5.7.2.6. Source code of the tutorial
Here is the complete source code of the tutorial.
5.7.3. Business Application with custom work item handlers and event listeners
5.7.3.1. What will you do
You will enhance your business application with business assets that execute custom business logic and monitors execution via event listeners.
-
business process (BPMN2) with custom service task (aka work item)
-
develop work item handler for the custom service task
-
develop process event listener that will receive events from the jBPM engine
and execute this business assets
-
via REST api of your business application
-
via Business Central UI
5.7.3.2. What do you need
-
About 20 minutes of your time
-
Java (JDK) 8 or later
-
Maven 3.5.x
-
IDE of your choice
-
Access to the Internet
-
Business Central deployed - see single distribution for instructions
5.7.3.3. What should I do
If you haven’t done it already, complete tutorial Business Application with Business Assets
.
If you would like directly start with this tutorial you can get
complete source of the Business Application with Business Assets tutorial from
here
|
Start Business Central (if not already started) and open your browser at
http://localhost:8080/business-central and logon as
user wbadmin
with password wbadmin
Import your business assets project into Business Central
if not already imported proceed with points below to import business asset project
-
Go into business assets project -
business-application-kjar
-
Execute
git init
-
Execute
git add -A
-
Execute
git commit -m "my business assets project"
-
Log in to Business Central and go to projects
-
Select import project and enter the following URL
file:///{path to your business application}/business-application-kjar
-
Click import and confirm project to be imported
Create custom service task in Business Central
-
Go to Projects → business-application-kjar project
-
Click Add asset and select WorkItem Definition
-
Give it a name
CustomTask
It should look like the following snippet
[
[
"name" : "MyTask",
"parameters" : [
"MyFirstParam" : new StringDataType(),
"MySecondParam" : new StringDataType(),
"MyThirdParam" : new ObjectDataType()
],
"results" : [
"Result" : new ObjectDataType("java.util.Map")
],
"displayName" : "My Task",
"icon" : ""
]
]
-
Save and close the editor
Create new process with service task (MyTask
)
-
Click Add Asset button and select Business Process
-
Give it a name
CustomTaskProcess
-
Open
Service Tasks
on the palette (cogs icon) -
Drag and Drop the MyTask service task into the canvas
-
Connect it with start event and finish it with end event
It should look like this
-
Save and close the editor
Implement custom work item handler
-
Import business-application-service project into IDE of your choice
-
Create new class MyTaskWorkItemHandler that implements
org.kie.api.runtime.process.WorkItemHandler
-
Implement the
executeWorkItemHandler
by simply printing out work item and complete the work item
@Override
public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
System.out.println("Work item being executed " + workItem);
manager.completeWorkItem(workItem.getId(), null);
}
-
annotate the class with
@Component
annotation with name that matches the work item defined in Business Central
Complete class of the handler should look like this
package com.company.service.handlers;
import org.kie.api.runtime.process.WorkItem;
import org.kie.api.runtime.process.WorkItemHandler;
import org.kie.api.runtime.process.WorkItemManager;
import org.springframework.stereotype.Component;
@Component("MyTask")
public class MyTaskWorkItemHandler implements WorkItemHandler {
@Override
public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
System.out.println("Work item being executed " + workItem);
manager.completeWorkItem(workItem.getId(), null);
}
@Override
public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
}
}
Implement custom event listener
To be able to monitor execution of our business assets such as business process an event listener can be implemented. In this tutorial we focus on ProcessEventListener but there are other types such as:
-
TaskLifeCycleEventListener
-
CaseEventListener
-
RuleRuntimeEventListener
-
AgendaEventListener
Go back to IDE where the business-application-service is imported
-
Create class MyProcessEventListener that implements
org.kie.api.event.process.ProcessEventListener
-
Implement methods with simple print outs
-
Annotate the class with
Component
- in this case the name is not relevant
Complete class of the event listener should look like this
package com.company.service.listeners;
import org.kie.api.event.process.ProcessCompletedEvent;
import org.kie.api.event.process.ProcessEventListener;
import org.kie.api.event.process.ProcessNodeLeftEvent;
import org.kie.api.event.process.ProcessNodeTriggeredEvent;
import org.kie.api.event.process.ProcessStartedEvent;
import org.kie.api.event.process.ProcessVariableChangedEvent;
import org.springframework.stereotype.Component;
@Component
public class MyProcessEventListener implements ProcessEventListener {
@Override
public void beforeProcessStarted(ProcessStartedEvent event) {
System.out.println("beforeProcessStarted " + event);
}
@Override
public void afterProcessStarted(ProcessStartedEvent event) {
System.out.println("afterProcessStarted " + event);
}
@Override
public void beforeProcessCompleted(ProcessCompletedEvent event) {
System.out.println("beforeProcessCompleted " + event);
}
@Override
public void afterProcessCompleted(ProcessCompletedEvent event) {
System.out.println("afterProcessCompleted " + event);
}
@Override
public void beforeNodeTriggered(ProcessNodeTriggeredEvent event) {
System.out.println("beforeNodeTriggered " + event);
}
@Override
public void afterNodeTriggered(ProcessNodeTriggeredEvent event) {
System.out.println("afterNodeTriggered " + event);
}
@Override
public void beforeNodeLeft(ProcessNodeLeftEvent event) {
System.out.println("beforeNodeLeft " + event);
}
@Override
public void afterNodeLeft(ProcessNodeLeftEvent event) {
System.out.println("afterNodeLeft " + event);
}
@Override
public void beforeVariableChanged(ProcessVariableChangedEvent event) {
System.out.println("beforeVariableChanged " + event);
}
@Override
public void afterVariableChanged(ProcessVariableChangedEvent event) {
System.out.println("afterVariableChanged " + event);
}
}
Run the application
At this point all development effort is done, the last remaining thing is to pull back the business assets project into the business-application-kjar project
-
Go to business-application-kjar
-
Execute
git remote add origin ssh://wbadmin@localhost:8001/MySpace/business-application-kjar
(if not already added) -
Execute
git pull origin master
- when prompted enterwbadmin
as password
Go to business-application-service
directory and launch the application
./launch.sh clean install
for Linux/Unix
./launch.bat clean install
for Windows
5.7.3.4. Results
Once the build and launch is complete you can open your browser http://localhost:8090
Next, point the browser to http://localhost:8090/rest/server/containers to see that your business assets project has been properly deployed and is running.
By default all REST endpoints (url pattern /rest/*) are secured and require
authentication. Default user that can be used to logon is wbadmin with password wbadmin
|
Next, point the browser to http://localhost:8090/rest/server/containers/business-application-kjar/processes to see business processes available for execution. You should see two of them.
Execute business process
You can execute business process via REST api exposed by your business application (in fact by Business Automation capability).
URL: http://localhost:8090/rest/server/containers/business-application-kjar/processes/{processid}/instances
HTTP method: POST
Optionally HTTP headers can be set to change the format of data returned
-
Accept: application/json for JSON format
-
Accept: application/xml for XML (JAXB based) format
-
X-KIE-ContentType: XSTREAM for XML (XStream based) format
{processid} needs to be replaced with actual process id that is returned from the endpoint http://localhost:8090/rest/server/containers/business-application-kjar/processes
Remember that endpoints are protected so make sure you provide user name and password when making the request. |
In response to this request, a process instance id should be returned.
<long-type>
<value>1</value>
</long-type>
You can examine details of that process instance by pointing your browser to http://localhost:8090/rest/server/containers/business-application-kjar/processes/instances/1
<process-instance>
<process-instance-id>1</process-instance-id>
<process-id>business-application-kjar.CustomTaskProcess</process-id>
<process-name>CustomTaskProcess</process-name>
<process-version>1.0</process-version>
<process-instance-state>2</process-instance-state>
<container-id>business-application-kjar-1_0-SNAPSHOT</container-id>
<initiator>wbadmin</initiator>
<start-date>2018-10-11T13:29:55.807+02:00</start-date>
<process-instance-desc>CustomTaskProcess</process-instance-desc>
<correlation-key>1</correlation-key>
<parent-instance-id>-1</parent-instance-id>
<sla-compliance>0</sla-compliance>
</process-instance>
Looking into the application logs (console) you should see that both the handler has been executed and event listener was notified about various events
beforeVariableChanged ==>[ProcessVariableChanged(id=initiator; instanceId=initiator; oldValue=null; newValue=wbadmin; processName=CustomTaskProcess; processId=business-application-kjar.CustomTaskProcess)]
afterVariableChanged ==>[ProcessVariableChanged(id=initiator; instanceId=initiator; oldValue=null; newValue=wbadmin; processName=CustomTaskProcess; processId=business-application-kjar.CustomTaskProcess)]
beforeProcessStarted ==>[ProcessStarted(name=CustomTaskProcess; id=business-application-kjar.CustomTaskProcess)]
beforeNodeTriggered ==>[ProcessNodeTriggered(nodeId=3; id=0; nodeName=null; processName=CustomTaskProcess; processId=business-application-kjar.CustomTaskProcess)]
beforeNodeLeft ==>[ProcessNodeLeft(nodeId=3; id=0; nodeName=null; processName=CustomTaskProcess; processId=business-application-kjar.CustomTaskProcess)]
beforeNodeTriggered ==>[ProcessNodeTriggered(nodeId=1; id=1; nodeName=My Task; processName=CustomTaskProcess; processId=business-application-kjar.CustomTaskProcess)]
Work item being executed WorkItem 1 [name=MyTask, state=0, processInstanceId=1, parameters{}]
beforeNodeLeft ==>[ProcessNodeLeft(nodeId=1; id=1; nodeName=My Task; processName=CustomTaskProcess; processId=business-application-kjar.CustomTaskProcess)]
beforeNodeTriggered ==>[ProcessNodeTriggered(nodeId=2; id=2; nodeName=null; processName=CustomTaskProcess; processId=business-application-kjar.CustomTaskProcess)]
beforeNodeLeft ==>[ProcessNodeLeft(nodeId=2; id=2; nodeName=null; processName=CustomTaskProcess; processId=business-application-kjar.CustomTaskProcess)]
beforeProcessCompleted ==>[ProcessCompleted(name=CustomTaskProcess; id=business-application-kjar.CustomTaskProcess)]
afterProcessCompleted ==>[ProcessCompleted(name=CustomTaskProcess; id=business-application-kjar.CustomTaskProcess)]
afterNodeLeft ==>[ProcessNodeLeft(nodeId=2; id=2; nodeName=null; processName=CustomTaskProcess; processId=business-application-kjar.CustomTaskProcess)]
afterNodeTriggered ==>[ProcessNodeTriggered(nodeId=2; id=2; nodeName=null; processName=CustomTaskProcess; processId=business-application-kjar.CustomTaskProcess)]
afterNodeLeft ==>[ProcessNodeLeft(nodeId=1; id=1; nodeName=My Task; processName=CustomTaskProcess; processId=business-application-kjar.CustomTaskProcess)]
afterNodeTriggered ==>[ProcessNodeTriggered(nodeId=1; id=1; nodeName=My Task; processName=CustomTaskProcess; processId=business-application-kjar.CustomTaskProcess)]
afterNodeLeft ==>[ProcessNodeLeft(nodeId=3; id=0; nodeName=null; processName=CustomTaskProcess; processId=business-application-kjar.CustomTaskProcess)]
afterNodeTriggered ==>[ProcessNodeTriggered(nodeId=3; id=0; nodeName=null; processName=CustomTaskProcess; processId=business-application-kjar.CustomTaskProcess)]
afterProcessStarted ==>[ProcessStarted(name=CustomTaskProcess; id=business-application-kjar.CustomTaskProcess)]
Execute business process from Business Central UI
Follow the same procedure as described in Execute business process from Business Central UI
5.7.3.5. Summary
Congratulations! you have enhanced your business application to take advantage of custom service tasks and you learned how to keep an eye on what is actually being executed by your business application. With this knowledge you can start doing more advanced service tasks that will integrate your application with the outside world.
5.7.3.6. Source code of the tutorial
Here is the complete source code of the tutorial.
5.7.4. Business Application with JPA entity
5.7.4.1. What will you do
You will enhance your business application with JPA entity that will be used both by your business application service and business assets.
-
develop JPA entity as part of your business-application-model project
-
business process (BPMN2) with user task that will display JPA entity
and execute this business assets
-
via REST api of your business application
-
via Business Central UI
5.7.4.2. What do you need
-
About 20 minutes of your time
-
Java (JDK) 8 or later
-
Maven 3.5.x
-
IDE of your choice
-
Access to the Internet
-
Business Central deployed - see single distribution for instructions
5.7.4.3. What should I do
If you haven’t done it already, complete tutorial Business Application with Business Assets
.
If you would like directly start with this tutorial you can get
complete source of the Business Application with Business Assets tutorial from
here
|
Start Business Central (if not already started) and open your browser at
http://localhost:8080/business-central and logon as
user wbadmin
with password wbadmin
Import your business assets project into Business Central
if not already imported proceed with points below to import business asset project
-
Go into business assets project -
business-application-kjar
-
Execute
git init
-
Execute
git add -A
-
Execute
git commit -m "my business assets project"
-
Log in to Business Central and go to projects
-
Select import project and enter the following URL
file:///{path to your business application}/business-application-kjar
-
Click import and confirm project to be imported
Implement JPA entity
-
Import business-application-model project into IDE of your choice
-
Add to pom.xml of the model project dependency to JPA api (in scope provided)
<dependencies>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
<scope>provided</scope>
</dependency>
</dependencies>
-
Implement class as JPA Entity
Person
-
Create three fields in the class
-
id (of type Long)
-
firstName (of type String)
-
lastName (of type String)
-
-
Annotate the class with
@Entity
-
Annotate the
id
field with@Id
and@GeneratedValue(strategy = GenerationType.AUTO)
Complete class of the entity should look like this
package com.company.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return "Person [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + "]";
}
}
Configure service project to use the JPA entity
-
Import business-application-service project into IDE of your choice
-
Add dependency to the business-application-model in your service pom.xml
<dependency>
<groupId>com.company</groupId>
<artifactId>business-application-model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
-
Edit application.properties file (that is located in src/main/resources)
-
Add
spring.jpa.properties.entity-scan-packages=com.company.model
into the file
Adjust the package if you did not use the default com.company.model package |
-
Add the same entry into
application-dev.properties
file
Create new process that use JPA entity
-
Log in to Business Central
-
Go to Projects → business-application-kjar project
-
Go to Settings tab
-
Go to Dependencies
-
Add dependency to business-application-model - make sure it is in provided scope
-
Go to Deployment → Marshalling strategy
-
Add new marshalling strategy with following value
new org.drools.persistence.jpa.marshaller.JPAPlaceholderResolverStrategy(entityManagerFactory)
-
Go back to assets
-
Click Add Asset button and select Business Process
-
Give it a name
JPAProcess
-
Open
Tasks
on the palette -
Drag and Drop the User Task into the canvas
-
Connect it with start event and finish it with end event
-
Create variable named person with type (custom)
com.company.model.Person
It should look like this
-
Map the variable as input and output of user task - use same name for input and output variable
-
Save and close the editor
Run the application
At this point all development effort is done, the last remaining thing is to pull back the business assets project into the business-application-kjar project
-
Go to business-application-kjar
-
Execute
git remote add origin ssh://wbadmin@localhost:8001/MySpace/business-application-kjar
(if not already added) -
Execute
git pull origin master
- when prompted enterwbadmin
as password
Go to business-application-service
directory and launch the application
./launch.sh clean install
for Linux/Unix
./launch.bat clean install
for Windows
5.7.4.4. Results
Once the build and launch is complete you can open your browser http://localhost:8090
Next, point the browser to http://localhost:8090/rest/server/containers to see that your business assets project has been properly deployed and is running.
By default all REST endpoints (url pattern /rest/*) are secured and require
authentication. Default user that can be used to logon is wbadmin with password wbadmin
|
Next, point the browser to http://localhost:8090/rest/server/containers/business-application-kjar/processes to see business processes available for execution. You should see two of them.
Execute business process
You can execute business process via REST api exposed by your business application (in fact by Business Automation capability).
HTTP method: POST
HTTP headers:
-
Accept: application/json
-
Content-Type: application/json
Body:
{
"person" : {
"Person" : {
"firstName":"WB",
"lastName":"Admin"
}
}
}
{processid} needs to be replaced with actual process id that is returned from the endpoint http://localhost:8090/rest/server/containers/business-application-kjar/processes
Remember that endpoints are protected so make sure you provide user name and password when making the request. |
In response to this request, a process instance id should be returned.
1
You can examine details of that process instance by pointing your browser to http://localhost:8090/rest/server/containers/business-application-kjar/processes/instances/1?withVars=true
<process-instance>
<process-instance-id>1</process-instance-id>
<process-id>business-application-kjar.JPAProcess</process-id>
<process-name>JPAProcess</process-name>
<process-version>1.0</process-version>
<process-instance-state>1</process-instance-state>
<container-id>business-application-kjar-1_0-SNAPSHOT</container-id>
<initiator>wbadmin</initiator>
<start-date>2018-10-11T14:42:23.053+02:00</start-date>
<process-instance-desc>JPAProcess</process-instance-desc>
<correlation-key>1</correlation-key>
<parent-instance-id>-1</parent-instance-id>
<sla-compliance>0</sla-compliance>
<active-user-tasks>
<task-summary>
<task-id>1</task-id>
<task-name>Task</task-name>
<task-description/>
<task-status>Reserved</task-status>
<task-priority>0</task-priority>
<task-actual-owner>wbadmin</task-actual-owner>
<task-created-by>wbadmin</task-created-by>
<task-created-on>2018-10-11T14:42:23.058+02:00</task-created-on>
<task-activation-time>2018-10-11T14:42:23.058+02:00</task-activation-time>
<task-proc-inst-id>2</task-proc-inst-id>
<task-proc-def-id>business-application-kjar.JPAProcess</task-proc-def-id>
<task-container-id>business-application-kjar-1_0-SNAPSHOT</task-container-id>
</task-summary>
</active-user-tasks>
<variables>
<entry>
<key>person</key>
<value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="person">
<firstName>WB</firstName>
<id>1</id>
<lastName>Admin</lastName>
</value>
</entry>
<entry>
<key>initiator</key>
<value xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">wbadmin</value>
</entry>
</variables>
</process-instance>
This illustrates that an instance has been created, it has one user task assigned (the owner is wbadmin) and it has two process variables
-
initiator - set to the user who initiated the request
-
person - our JPA entity that was created based on the payload - but note that the id was generated automatically by the database
You can also examine user task by opening following URL in your browser http://localhost:8090/rest/server/containers/business-application-kjar/tasks/1?withInputData=true
<task-instance>
<task-id>1</task-id>
<task-priority>0</task-priority>
<task-name>Task</task-name>
<task-subject/>
<task-description/>
<task-form>Task</task-form>
<task-status>Reserved</task-status>
<task-actual-owner>wbadmin</task-actual-owner>
<task-created-by>wbadmin</task-created-by>
<task-created-on>2018-10-11T14:42:23.058+02:00</task-created-on>
<task-activation-time>2018-10-11T14:42:23.058+02:00</task-activation-time>
<task-skippable>false</task-skippable>
<task-workitem-id>1</task-workitem-id>
<task-process-instance-id>1</task-process-instance-id>
<task-parent-id>-1</task-parent-id>
<task-process-id>business-application-kjar.JPAProcess</task-process-id>
<task-container-id>business-application-kjar-1_0-SNAPSHOT</task-container-id>
<inputData>
<entry>
<key>TaskName</key>
<value xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Task</value>
</entry>
<entry>
<key>NodeName</key>
<value xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Task</value>
</entry>
<entry>
<key>person</key>
<value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="person">
<firstName>WB</firstName>
<id>1</id>
<lastName>Admin</lastName>
</value>
</entry>
<entry>
<key>Skippable</key>
<value xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">false</value>
</entry>
<entry>
<key>ActorId</key>
<value xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">wbadmin</value>
</entry>
</inputData>
</task-instance>
Same person JPA entity is available on the task assigned to wbadmin
5.7.4.5. Summary
Congratulations! you have enhanced your business application to take advantage of a JPA entity as shared model between your business assets and service projects. With the power of business automation and JPA you learned how to externalise data managed by automated by business processes.
5.7.4.6. Source code of the tutorial
Here is the complete source code of the tutorial.
5.7.5. Business Application with ElasticSearch
5.7.5.1. What will you do
You will build business application that pushes out information about your business automation (processes, cases, tasks) directly to an ElasticSearch server. You can then use ElasticSearch REST api to perform advanced queries on top of your business data.
5.7.5.2. What do you need
-
About 20 minutes of your time
-
Java (JDK) 8 or later
-
Maven 3.5.x
-
IDE of your choice
-
Access to the Internet
-
Business Central deployed - see single distribution for instructions
5.7.5.3. What should I do
Install ElasticSearch
To get quickly up and running with ElasticSearch, make use of docker images provided by ElasticSearch.
docker pull docker.elastic.co/elasticsearch/elasticsearch:6.4.2
Once pulled, start it with basic settings recommended for development and test.
docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:6.4.2
Wait a bit and your ElasticSearch will be up and running, to verify if it is working as expected, open you browser at http://localhost:9200 and you should see similar content
{
"name" : "IKXT4Z_",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "G7q7D2zgQy6JzLZBCzbtTQ",
"version" : {
"number" : "6.4.2",
"build_flavor" : "default",
"build_type" : "tar",
"build_hash" : "04711c2",
"build_date" : "2018-09-26T13:34:09.098244Z",
"build_snapshot" : false,
"lucene_version" : "7.4.0",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
when prompted for user name and password use elastic/changeme |
Build business application
To get started with business applications the easiest way is to generate it.
Go to start.jbpm.org and click button
Generate default business application
.
This will generate and download a business-application.zip
file that will consists of
three projects
-
business-application-model
-
business-application-kjar
-
business-application-service
Unzip the business-application.zip
file into desired location and go into
business-application-service
directory. There you will find launch scripts
(for both linux/unix and windows).
Start Business Central (if not already started) and open your browser at
http://localhost:8080/business-central and logon as
user wbadmin
with password wbadmin
Import your business assets project into Business Central
if not already imported proceed with points below to import business asset project
-
Go into business assets project -
business-application-kjar
-
Execute
git init
-
Execute
git add -A
-
Execute
git commit -m "my business assets project"
-
Log in to Business Central and go to projects
-
Select import project and enter the following URL
file:///{path to your business application}/business-application-kjar
-
Click import and confirm project to be imported
Create Business Process
In browser where you logged into Business Central go to Projects. You will see your newly imported project named business-application-kjar, go into that project.
-
go into business-application-kjar project
-
click
Add asset
button -
select Business Process asset
-
provide name for this asset
-
create your business process
Sample business process could be a single user task that will be assigned to user wbadmin
.
Configure service project to use the ElasticSearch
-
Import business-application-service project into IDE of your choice
-
Add dependency to the jbpm-event-emitters-elasticsearch in your service pom.xml
<dependency>
<groupId>org.jbpm</groupId>
<artifactId>jbpm-event-emitters-elasticsearch</artifactId>
<version>${version.org.kie}</version>
</dependency>
There are several configuration parameters that define how business application will connect to ElasticSearch server
-
jbpm.addons.event.emitters.elasticsearch.url - location of the ElasticSearch server, defaults to http://localhost:9200
-
jbpm.addons.event.emitters.elasticsearch.date_format - date format to be used for dates defaults to yyyy-MM-dd’T’hh:mm:ss.SSSZ
-
jbpm.addons.event.emitters.elasticsearch.user - optional user name to be used to authenticate in ElasticSearch server
-
jbpm.addons.event.emitters.elasticsearch.password - optional password to be used to authenticate in ElasticSearch server
If the defaults fit your ElasticSearch setup then you don’t need to set any properties in application.properties.
For the default setup we use in this tutorial, user and password need to be set
-
Edit application.properties file (that is located in src/main/resources)
-
Add
jbpm.addons.event.emitters.elasticsearch.user=elastic
into the file -
Add
jbpm.addons.event.emitters.elasticsearch.password=changeme
into the file
Add the same entry into application-dev.properties file
|
Run the application
At this point all development effort is done, the last remaining thing is to pull back the business assets project into the business-application-kjar project
-
Go to business-application-kjar
-
Execute
git remote add origin ssh://wbadmin@localhost:8001/MySpace/business-application-kjar
(if not already added) -
Execute
git pull origin master
- when prompted enterwbadmin
as password
Go to business-application-service
directory and launch the application
./launch.sh clean install
for Linux/Unix
./launch.bat clean install
for Windows
5.7.5.4. Results
Once the build and launch is complete you can open your browser http://localhost:8090 to see your business application up and running.
It presents with a welcome screen that is mainly for verification purpose to illustrate that application started successfully.
You can point the browser to http://localhost:8090/rest/server to see the actual Business Automation capability services
By default all REST endpoints (url pattern /rest/*) are secured and require
authentication. Default user that can be used to logon is wbadmin with password wbadmin
|
Next, point the browser to http://localhost:8090/rest/server/containers/business-application-kjar/processes to see business processes available for execution. You should see just one.
Execute business process
You can execute business process via REST api exposed by your business application (in fact by Business Automation capability).
HTTP method: POST
HTTP headers:
-
Accept: application/json
-
Content-Type: application/json
Body:
{
"name":"wbadmin",
"age":25
}
{processid} needs to be replaced with actual process id that is returned from the endpoint http://localhost:8090/rest/server/containers/business-application-kjar/processes
Remember that endpoints are protected so make sure you provide user name and password when making the request. |
Once executed you can verify the integration with ElasticSearch simply by pointing your browser to http://localhost:9200/processes/_search?pretty=true and the result should be as follows
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [
{
"_index" : "processes",
"_type" : "process",
"_id" : "business-application-service-dev_1",
"_score" : 1.0,
"_source" : {
"compositeId" : "business-application-service-dev_1",
"id" : 1,
"processId" : "usertaskprocess",
"processName" : "usertaskprocess",
"processVersion" : "1.0",
"state" : 1,
"containerId" : "business-application-kjar_1.0-SNAPSHOT",
"initiator" : "wbadmin",
"date" : "2018-10-25T02:41:55.205+0200",
"processInstanceDescription" : "usertaskprocess",
"correlationKey" : "1",
"parentId" : -1,
"variables" : {
"initiator" : "wbadmin",
"name" : "wbadmin",
"age" : 25
}
}
}
]
}
}
and to see user tasks stored in ElasticSearch point your browser to http://localhost:9200/tasks/_search?pretty=true
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [
{
"_index" : "tasks",
"_type" : "task",
"_id" : "business-application-service-dev_1",
"_score" : 1.0,
"_source" : {
"compositeId" : "business-application-service-dev_1",
"id" : 1,
"priority" : 8,
"name" : "Complete me",
"subject" : "TaskSubject",
"description" : "Here is a task for wbadmin",
"taskType" : null,
"formName" : "CompleteMe",
"status" : "Reserved",
"actualOwner" : "wbadmin",
"createdBy" : "wbadmin",
"createdOn" : "2018-10-25T02:41:54.942+0200",
"activationTime" : "2018-10-25T02:41:54.942+0200",
"expirationDate" : null,
"skipable" : false,
"workItemId" : 1,
"processInstanceId" : 1,
"parentId" : -1,
"processId" : "usertaskprocess",
"containerId" : "business-application-kjar_1.0-SNAPSHOT",
"potentialOwners" : [
"wbadmin"
],
"excludedOwners" : [ ],
"businessAdmins" : [
"Administrator",
"Administrators"
],
"inputData" : {
"Comment" : "TaskSubject",
"Description" : "Here is a task for wbadmin",
"TaskName" : "CompleteMe",
"NodeName" : "Complete me",
"Priority" : "8",
"name" : "wbadmin",
"Skippable" : "false",
"ActorId" : "wbadmin",
"age" : 25
},
"outputData" : null
}
}
]
}
}
When you complete a task or abort a process instance data in ElasticSearch will be immediately updated.
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [
{
"_index" : "processes",
"_type" : "process",
"_id" : "business-application-service-dev_2",
"_score" : 1.0,
"_source" : {
"compositeId" : "business-application-service-dev_2",
"id" : 2,
"processId" : "usertaskprocess",
"processName" : "usertaskprocess",
"processVersion" : "1.0",
"state" : 3,
"containerId" : "business-application-kjar_1.0-SNAPSHOT",
"initiator" : "wbadmin",
"date" : "2018-10-25T03:01:02.557+0200",
"processInstanceDescription" : "usertaskprocess",
"correlationKey" : "2",
"parentId" : -1,
"variables" : {
"initiator" : "wbadmin",
"name" : "bartek",
"age" : 5
}
}
}
]
}
}
5.7.5.5. Summary
Congratulations! you have integrated your business application with ElasticSearch. Now you can take advantage of all the good things ElasticSearch provides you with such as full text search by process variables, task assignees, case participants and more.
5.7.5.6. Source code of the tutorial
Here is the complete source code of the tutorial.
5.7.6. Business Application with JMS
5.7.6.1. What will you do
You will build business application that uses JMS to send information between your business processes. It combines process logic and messaging to provide comprehensive solution to common problems such as - how to notify other participants of particular event.
5.7.6.2. What do you need
-
About 20 minutes of your time
-
Java (JDK) 8 or later
-
Maven 3.5.x
-
IDE of your choice
-
Access to the Internet
-
Business Central deployed - see single distribution for instructions
5.7.6.3. What should I do
Install Apache Artemis
Download and unzip Apache Artemis distribution.
Refer to the location where you unzip it as ${ARTEMIS_HOME}
.
Once downloaded, navigate to the location where you want to store your broker data and create new broker
${ARTEMIS_HOME}/bin/artemis create business-app-broker
You will be prompted for some required information during creation, that should look like this
Creating ActiveMQ Artemis instance at: /.../business-app-broker
--user: is a mandatory property!
Please provide the default username:
admin
--password: is mandatory with this configuration:
Please provide the default password:
--allow-anonymous | --require-login: is a mandatory property!
Allow anonymous access?, valid values are Y,N,True,False
Y
Next, start the broker instance, go to business-app-broker/bin and issue following command
./artemis run
Open your browser at http://localhost:8161/console to logon to management console of Apache Artemis with user name and password provided at the time you created the broker.
For more detailed instruction on how to configure Apache Artemis visit its website |
Last step in configuring JMS service is to create a queue (or an address as it’s called in Apache Artemis).
Once logged into Management Console
-
Go to Artemis in the menu
-
Expand the tree view and click
addresses
-
On right hand side click
Create
-
Create new address with name
ExternalSignalQueue
-
Select
Anycast
All steps are done for installing and configuring Apache Artemis for this tutorial.
Build business application
To get started with business applications the easiest way is to generate it.
Go to start.jbpm.org and click button
Generate default business application
.
This will generate and download a business-application.zip
file that will consists of
three projects
-
business-application-model
-
business-application-kjar
-
business-application-service
Unzip the business-application.zip
file into desired location and go into
business-application-service
directory. There you will find launch scripts
(for both linux/unix and windows).
Start Business Central (if not already started) and open your browser at
http://localhost:8080/business-central and logon as
user wbadmin
with password wbadmin
Import your business assets project into Business Central
if not already imported proceed with points below to import business asset project
-
Go into business assets project -
business-application-kjar
-
Execute
git init
-
Execute
git add -A
-
Execute
git commit -m "my business assets project"
-
Log in to Business Central and go to projects
-
Select import project and enter the following URL
file:///{path to your business application}/business-application-kjar
-
Click import and confirm project to be imported
Create Business Processes
In browser where you logged into Business Central go to Projects. You will see your newly imported project named business-application-kjar, go into that project.
-
go into business-application-kjar project
-
click
Add asset
button -
select Business Process asset
-
provide name for this asset (
throwsignalprocess
) -
create your business process
Sample business process should be a single script task and end signal event. Signal event
should use external scope and define a signal IamDone
Process should define single process variable input
that is then mapped as data output of the end event.
Next create another business process that will receive that signal.
-
go into business-application-kjar project
-
click
Add asset
button -
select Business Process asset
-
provide name for this asset (
catchsignalprocess
) -
create your business process
Sample business process should be a signal catch event and single user task assigned to wbadmin
.
The catch signal event should use the signal same as throwing one and that is IamDone
Process should define single process variable data
that is then mapped as data input of the catch event.
Configure service project to use the Apache Artemis
-
Import business-application-service project into IDE of your choice
-
Add dependency to the spring-boot-starter-artemis in your service pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-artemis</artifactId>
</dependency>
-
Add dependency to the jbpm-workitems-jms in your service pom.xml
<dependency>
<groupId>org.jbpm</groupId>
<artifactId>jbpm-workitems-jms</artifactId>
<version>${version.org.kie}</version>
</dependency>
There are several configuration parameters that define how business application will connect to Apache Artemis
-
Edit application.properties file (that is located in src/main/resources)
spring.artemis.mode=native
spring.artemis.host=localhost
spring.artemis.port=61616
spring.artemis.user=admin
spring.artemis.password=admin
Use the user credentials you provided when creating the broker in the configuration |
Add the same entry into application-dev.properties file
|
Develop JMS components of your Business Application
First of all, you need to enable jms on the service level.
-
Open Application class (located in src/main/java/com/company/service directory)
-
Add
@EnableJms
on the class level (next to @SpringBootApplication)
Then create a new class that will be responsible for sending signals over JMS. This will
be really small extension to out of the box JMS work item handler.
ConfiguredJMSSendTaskWorkItemHandler
needs to extend org.jbpm.process.workitem.jms.JMSSendTaskWorkItemHandler
and this is where the most of the logic comes from.
This class needs to autowire
-
ConnectionFactory - used to connect to Apache Artemis
-
JmsTemplate - used to send messages
Overload executeWorkItem method to take advantage of JmsTemplate instead of direct JMS API.
Last but not least, annotate the class with @Component
annotation so it will be automatically registered as
work item handler. Below is the complete source code of the handler implementation.
package com.company.service.jms;
import javax.jms.ConnectionFactory;
import org.jbpm.process.workitem.jms.JMSSendTaskWorkItemHandler;
import org.kie.api.runtime.process.WorkItem;
import org.kie.api.runtime.process.WorkItemManager;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;
@Component("External Send Task")
public class ConfiguredJMSSendTaskWorkItemHandler extends JMSSendTaskWorkItemHandler {
private JmsTemplate jmsTemplate;
public ConfiguredJMSSendTaskWorkItemHandler(ConnectionFactory connectionFactory, JmsTemplate jmsTemplate) {
super(connectionFactory, null);
this.jmsTemplate = jmsTemplate;
}
@Override
public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
try {
jmsTemplate.send("ExternalSignalQueue", (session) -> createMessage(workItem, session));
manager.completeWorkItem(workItem.getId(), null);
} catch (Exception e) {
handleException(e);
}
}
}
Last development activity is to create the message receiver. This is even easier than sender
as there is out of the box receiver from jBPM - org.jbpm.process.workitem.jms.JMSSignalReceiver
package com.company.service.jms;
import javax.jms.BytesMessage;
import org.jbpm.process.workitem.jms.JMSSignalReceiver;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
@Component
public class ReceiveJMSEvents extends JMSSignalReceiver {
@JmsListener(destination = "ExternalSignalQueue")
public void processMessage(BytesMessage content) {
super.onMessage(content);
}
}
And that’s it, you’re all set to communicate between business processes via JMS.
Run the application
At this point all development effort is done, the last remaining thing is to pull back the business assets project into the business-application-kjar project
-
Go to business-application-kjar
-
Execute
git remote add origin ssh://wbadmin@localhost:8001/MySpace/business-application-kjar
(if not already added) -
Execute
git pull origin master
- when prompted enterwbadmin
as password
Go to business-application-service
directory and launch the application
./launch.sh clean install
for Linux/Unix
./launch.bat clean install
for Windows
5.7.6.4. Results
Once the build and launch is complete you can open your browser http://localhost:8090 to see your business application up and running.
It presents with a welcome screen that is mainly for verification purpose to illustrate that application started successfully.
You can point the browser to http://localhost:8090/rest/server to see the actual Business Automation capability services
By default all REST endpoints (url pattern /rest/*) are secured and require
authentication. Default user that can be used to logon is wbadmin with password wbadmin
|
Next, point the browser to http://localhost:8090/rest/server/containers/business-application-kjar/processes to see business processes available for execution. You should see two processes:
-
catchsignalprocess
-
throwsignalprocess
Execute business process
You can execute business process via REST api exposed by your business application (in fact by Business Automation capability).
First start process instance that will wait for a signal
HTTP method: POST
HTTP headers:
-
Accept: application/json
-
Content-Type: application/json
And then start process instance that will throw (send) signal via JMS
HTTP method: POST
HTTP headers:
-
Accept: application/json
-
Content-Type: application/json
Body:
{
"input":"hello"
}
Remember that endpoints are protected so make sure you provide user name and password when making the request. |
Verify that there is a user task assigned to wbadmin
user with information coming from second process instance - hello
Execute business process from Business Central UI
Stop the application if it’s running.
Go to business-application-service
directory and launch the application in development mode
./launch-dev.sh clean install
for Linux/Unix
./launch-dev.bat clean install
for Windows
this will connect your business application to Business Central so can be administered from within its UI.
Go to Business Central in the browser and navigate to servers (from the home screen).
Let’s deploy the business-application-kjar to our running application.
-
Go to projects from home screen of Business Central
-
Go into business-application-kjar project
-
Click
Deploy
button -
Make sure that
Server configuration
is set tobusiness-application-service-dev
and click ok
The project should be successfully deployed and you can examine that state by going back to servers from home screen.
Next, go to process definitions (in Manage section of the Home screen) and select server configuration
(top right corner) - again it should be business-application-service-dev
the list of available
process definition will be loaded and you should see your single process definitions from the project
business-application-kjar
.
First start process instance that will wait for a signal (catchsignalprocess
),
then start process instance that will throw (send) signal via JMS (throwsignalprocess
).
When starting second process specify the input you want to send together with signal.
Go to Task inbox from home screen to see that task is created with input provided on the second process instance.
5.7.6.5. Summary
Congratulations! you have integrated your business application with JMS. Moreover, you made business processes to talk to each other (over signals). This allows you to build more advanced interactions based on your business logic.
5.7.6.6. Source code of the tutorial
Here is the complete source code of the tutorial.
5.7.7. Business Application with Dynamic Assets
5.7.7.1. What will you do
You will enhance your business application with some dynamic assets that allow more adaptive approach to business logic compared with structured business processes.
Next execute these dynamic assets
-
via REST api of your business application
-
via jBPM Case Management showcase
5.7.7.2. What do you need
-
About 15 minutes of your time
-
Java (JDK) 8 or later
-
Maven 3.5.x
-
Access to the Internet
-
Business Central deployed - see single distribution for instructions
5.7.7.3. What should I do
To get started with business applications the easiest way is to generate it.
Go to start.jbpm.org and click button
Configure your business application
.
-
First step: Select
Business Automation
(selected by default) -
Second step: Provide details for your business application
-
Third step: Select
Dynamic Assets
,Data Model
andService
projects -
Click
Generate business application
button
Start Business Central (if not already started) and open your browser at
http://localhost:8080/business-central and logon as
user wbadmin
with password wbadmin
Import your business assets project into Business Central
-
Go into business assets project -
business-application-kjar
-
Execute
git init
-
Execute
git add -A
-
Execute
git commit -m "my business assets project"
-
Log in to Business Central and go to projects
-
Select import project and enter the following URL
file:///{path to your business application}/business-application-kjar
-
Click import and confirm project to be imported
Create Dynamic Asset - Case definition
In browser where you logged into Business Central go to Projects. You will see your newly imported project named business-application-kjar.
-
go into business-application-kjar project
-
click
Add asset
button -
select
Case definition
asset -
provide name for this asset e.g.
myfirstcase
-
optionally you can provide prefix for case ids - if not given it will default to CASE-XXX where XXX is generated number
-
create your case definition
Case definition is designed in the so-called legacy process designer. |
You can now create your dynamic case definition that does not have to have connected process activities.
Sample case definition could be a two user tasks that will be assigned to user wbadmin
and not connected to anything else.
This sample case definition consists of two user tasks
-
Dynamic User Task
-
Another task that is started automatically
Both of them are assigned to wbadmin
user although only one (second) will be created automatically
when case instance is created. This is because it is marked as autostart
and thus will be directly created.
The first one can be dynamically created on ad hoc basis.
Pull back your business assets to business application source code
-
Go to business-application-kjar
-
Execute
git remote add origin ssh://wbadmin@localhost:8001/MySpace/business-application-kjar
-
Execute
git pull origin master
- when prompted enterwbadmin
as password
Go to business-application-service
directory and launch the application
./launch.sh clean install
for Linux/Unix
./launch.bat clean install
for Windows
5.7.7.4. Results
Once the build and launch is complete you can open your browser http://localhost:8090
Next, point the browser to http://localhost:8090/rest/server/containers to see that your business assets project has been properly deployed and is running.
By default all REST endpoints (url pattern /rest/*) are secured and require
authentication. Default user that can be used to logon is wbadmin with password wbadmin
|
Next, point the browser to http://localhost:8090/rest/server/containers/business-application-kjar/cases/definitions to see dynamic assets (cases) available for execution.
Execute business process
You can execute business process via REST api exposed by your business application (in fact by Business Automation capability).
URL: http://localhost:8090/rest/server/containers/business-application-kjar/cases/{casedefid}/instances
HTTP method: POST
HTTP headers can be set to change the format of data returned
-
Accept: application/json for JSON format
-
Accept: application/xml for XML (JAXB based) format
-
X-KIE-ContentType: XSTREAM for XML (XStream based) format
{casedefid} needs to be replaced with actual case definition id that is returned from the endpoint http://localhost:8090/rest/server/containers/business-application-kjar/cases/definitions
Remember that endpoints are protected so make sure you provide user name and password when making the request. |
In response to this request, a case instance id should be returned.
<string-type>
<value>CASE-0000000001</value>
</string-type>
You can examine details of that case instance by pointing your browser to http://localhost:8090/rest/server/containers/business-application-kjar/cases/instances/CASE-0000000001
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<case-instance>
<case-id>CASE-0000000001</case-id>
<case-description>myfirstcase</case-description>
<case-owner>wbadmin</case-owner>
<case-status>1</case-status>
<case-definition-id>myfirstcase</case-definition-id>
<container-id>business-application-kjar-1_0-SNAPSHOT</container-id>
<case-started-at>2018-10-30T09:54:45.747+01:00</case-started-at>
<case-completion-msg></case-completion-msg>
<case-sla-compliance>0</case-sla-compliance>
</case-instance>
Load tasks for given case instance that are assigned to wbadmin
user
http://localhost:8090/rest/server/queries/cases/instances/CASE-0000000001/tasks/instances/pot-owners
you should see second task from case definition
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<task-summary-list>
<task-summary>
<task-id>1</task-id>
<task-name>Another task that is started automatically</task-name>
<task-subject></task-subject>
<task-description></task-description>
<task-status>Reserved</task-status>
<task-priority>0</task-priority>
<task-is-skipable>true</task-is-skipable>
<task-actual-owner>wbadmin</task-actual-owner>
<task-created-by>wbadmin</task-created-by>
<task-created-on>2018-10-30T09:54:45.790+01:00</task-created-on>
<task-activation-time>2018-10-30T09:54:45.790+01:00</task-activation-time>
<task-proc-inst-id>1</task-proc-inst-id>
<task-proc-def-id>myfirstcase</task-proc-def-id>
<task-container-id>business-application-kjar-1_0-SNAPSHOT</task-container-id>
<task-parent-id>-1</task-parent-id>
</task-summary>
</task-summary-list>
You can trigger dynamically the other user task by issuing request to
Optionally you can send data as payload of the request.
Load tasks again for given case instance that are assigned to wbadmin
user
http://localhost:8090/rest/server/queries/cases/instances/CASE-0000000001/tasks/instances/pot-owners
you should see both tasks from case definition
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<task-summary-list>
<task-summary>
<task-id>1</task-id>
<task-name>Another task that is started automatically</task-name>
<task-subject></task-subject>
<task-description></task-description>
<task-status>Reserved</task-status>
<task-priority>0</task-priority>
<task-is-skipable>true</task-is-skipable>
<task-actual-owner>wbadmin</task-actual-owner>
<task-created-by>wbadmin</task-created-by>
<task-created-on>2018-10-30T09:54:45.790+01:00</task-created-on>
<task-activation-time>2018-10-30T09:54:45.790+01:00</task-activation-time>
<task-proc-inst-id>1</task-proc-inst-id>
<task-proc-def-id>myfirstcase</task-proc-def-id>
<task-container-id>business-application-kjar-1_0-SNAPSHOT</task-container-id>
<task-parent-id>-1</task-parent-id>
</task-summary>
<task-summary>
<task-id>3</task-id>
<task-name>Dynamic User Task</task-name>
<task-subject></task-subject>
<task-description></task-description>
<task-status>Reserved</task-status>
<task-priority>0</task-priority>
<task-is-skipable>true</task-is-skipable>
<task-actual-owner>wbadmin</task-actual-owner>
<task-created-by>wbadmin</task-created-by>
<task-created-on>2018-10-30T10:08:01.257+01:00</task-created-on>
<task-activation-time>2018-10-30T10:08:01.257+01:00</task-activation-time>
<task-proc-inst-id>1</task-proc-inst-id>
<task-proc-def-id>myfirstcase</task-proc-def-id>
<task-container-id>business-application-kjar-1_0-SNAPSHOT</task-container-id>
<task-parent-id>-1</task-parent-id>
</task-summary>
</task-summary-list>
Execute business process from jBPM Case Management Showcase
There is a need to repoint the jBPM Case Management Showcase application to use business application
instead of the KIE Server bundled with single zip distribution of jBPM.
To do so, edit standalone.xml file of jbpm server (JBPM_SERVER/standalone/configuration
) and change the value of
org.kie.server.location
system property
<property name="org.kie.server.location" value="http://localhost:8090/rest/server"/>
Once done, restart jBPM server.
Stop the application if it’s running.
Go to business-application-service
directory and launch the application in development mode
./launch-dev.sh clean install
for Linux/Unix
./launch-dev.bat clean install
for Windows
this will connect your business application to Business Central so can be administered from within its UI.
Go to Business Central in the browser and navigate to servers (from the home screen).
As you can see the business-application-service Dev
is there and connected. Although
it does not have any kjars deployed. This is because it’s now running in managed mode
meaning it’s Business Central that decides what kjars it should run.
So let’s deploy the business-application-kjar to our running application.
-
Go to projects from home screen of Business Central
-
Go into business-application-kjar project
-
Click
Deploy
button -
Make sure that
Server configuration
is set tobusiness-application-service-dev
and click ok
The project should be successfully deployed and you can examine that state by going back to servers from home screen.
Next, go to process definitions (in Manage section of the Home screen) and select server configuration
(top right corner) - again it should be business-application-service-dev
the list of available
process definition will be loaded and you should see your single case definition from the project
business-application-kjar
.
Examine details of that case definition by clicking on the row in the table. Switch to
Diagram
tab to see the visual representation of your case definition.
Business Central does not allow to start case instances and thus you need to switch to Case Management showcase application. It is accessible from the Apps launcher icon (top right corner) next to logout button.
Launch the application and login with wbadmin
. Once logged in you can start a new case instance.
Go into newly started case instance by clicking on the row of the active cases list.
From there you can start a new instance of Dynamic User Task
as the other one is already there.
5.7.7.5. Summary
Congratulations! you have enhanced your business application to take advantage of dynamic and adaptive business assets that allow to do much more than structured processes. You could see how easy it is to add additional user tasks and that’s just the beginning.
5.7.7.6. Source code of the tutorial
Here is the complete source code of the tutorial.
6. jBPM Installer
6.1. Prerequisites
This script assumes you have Java JDK 1.8+ (set as JAVA_HOME), and Ant 1.9+ installed. If you don’t, use the following links to download and install them:
To check whether Java and Ant are installed correctly, type the following commands inside a command prompt: java -version ant -version This should return information about which version of Java and Ant you are currently using. |
6.2. Downloading the Installer
First of all, you need to download the installer and unzip it on your local file system. There are two versions
-
full installer - already contains a lot of the dependencies that are necessary during the installation
-
minimal installer - contains only the installer and will download all required dependencies on the fly
In general, it is probably best to download the full installer: jBPM-7.64.0.Final-installer-full.zip
You can also download the latest build (only for the minimal installer).
6.3. Demo Setup
The easiest way to get started is to simply run the installation script to install the demo setup. The demo install will setup all the web tooling (on top of WildFly) and Eclipse tooling in a pre-configured setup. Go into the jbpm-installer folder where you unzipped the installer and (from a command prompt) run:
ant install.demo
This will:
-
Download WildFly application server
-
Configure and deploy a process execution server
-
Configure and deploy Business Central
-
Configure and deploy the case management application
-
Download Eclipse
-
Install the Drools and jBPM Eclipse plugin
-
Install the Eclipse BPMN 2.0 Modeler
Running this command could take a while (REALLY, not kidding, we are for example downloading an Eclipse installation, even if you downloaded the full installer, specifically for your operating system).
The script always shows which file it is downloading (you could for example check whether it is still downloading by checking whether the size of the file in question in the jbpm-installer/lib folder is still increasing). If you want to avoid downloading specific components (because you will not be using them or you already have them installed somewhere else), check below for running only specific parts of the demo or directing the installer to an already installed component. |
Once the demo setup has finished, you can start playing with the various components by starting the demo setup:
ant start.demo
This will:
-
Start H2 database server
-
Start WildFly application server
-
Start Eclipse
Now wait until the process management console comes up:
The case management UI will be available on:
It could take a minute to start up the application server and web application. If the web page doesn’t show up after a while, make sure you don’t have a firewall blocking that port, or another application already using the port 8080. You can always take a look at the server log {jbpm-installer-folder}/wildfly-{version}/standalone/log/server.log |
Once everything is started, you can start playing with the Eclipse and web tooling, as explained in the following sections.
If you only want to try out the web tooling and do not wish to download and install the Eclipse tooling, you can use these alternative commands:
ant install.demo.noeclipse
ant start.demo.noeclipse
Similarly, if you only want to try out the Eclipse tooling and do not wish to download and install the web tooling, you can use these alternative commands:
ant install.demo.eclipse
ant start.demo.eclipse
Now continue with the 10-minute tutorials. Once you’re done playing and you want to shut down the demo setup, you can use:
ant stop.demo
If at any point in time would like to start over with a clean demo setup - meaning all changes you did inside the web tooling and/or saved in the database will be lost, you can run the following command (after which you can run the installer again from scratch, note that this cannot be undone):
ant clean.demo
6.4. 10-Minute Tutorial using Business Central
Open up the process management console:
It could take a minute to start up the application server and web application. If the web page doesn’t show up after a while, make sure you don’t have a firewall blocking that port, or another application already using the port 8080. You can always take a look at the server log {jbpm-installer-folder}/wildfly-{version}/standalone/log/server.log |
Log in, using krisv / krisv as user name / password.
Using a prebuilt Evaluation example, the following screencast gives an overview of how to manage your process instances. It shows you:
-
How to log in to Business Central
-
How to import an existing example project and build and deploy it
-
How to start a new process instance
-
How to look up the current status of a running process instance
-
How to look up your tasks
-
How to complete a task
-
How to look at reports to monitor your process execution
Business Central supports the entire life cycle of your business processes: authoring, deployment, process management, tasks and dashboards.
-
The project authoring page allows you to look at existing repositories, where each project can contain business processes (but also business rules, data models, forms, etc.). It allows you to create your own project, or you could import an existing example to take a look at.
-
In this screencast, we start by importing the Evaluation project
-
-
The project explorer shows all available artifacts:
-
evaluation: business process describing the evaluation process as a sequence of tasks
-
evaluation-taskform: process form to start the evaluation process
-
PerformanceEvaluation-taskform: task form to perform the evaluation tasks
-
-
To make a process available for execution, you need to successfully build and deploy it first. To do so, open the selected project (in the project authoring page) and click Build & Deploy (top right corner).
-
To manage your process definitions and instances, click the "Process Management" menu option at the top menu bar and select one of the available options depending on you interest:
-
Process Definitions - lists all available process definitions
-
Process Instances - lists all active process instances (allows to show completed, aborted as well by changing filter criteria)
-
-
The process definitions view allows you to start a new process instance by clicking on the Start button. The process form (as defined in the project) will be shown, where you need to fill in the necessary information to start the process. In this case, you need to fill the user you want to start an evaluation for (for example use "krisv") and a reason for the request, after which you can complete the form. Some details about the process instance that was just started will be shown in the process instance details panel. From there you can access additional details:
-
Process model - to visualize the current state of the process
-
Process variables - to see current values of process variables
-
Documents - documents related to the process instance
-
Logs - overview of all process events for that instance
The process instance that you just started is first requiring a self-evaluation of the user and is waiting until the user has completed this task.
-
-
To see the tasks that have been assigned to you, choose the "Tasks" menu option on the top bar. By default, it will show all active tasks, and a "Performance Evaluation" (that was created by the process instance you just started) should be available for you. When you click a task, the task details will be shown, including the task form related to this task. After starting the task, you can fill in the necessary information and complete the task. After completing the task, you could check the "Process Instances" once more to check the progress of your process instance. You should be able to see that the process is now waiting for your HR manager and project manager to also perform an evaluation. You could log in as "john" / "john" and "mary" / "mary" to complete these tasks.
-
After starting and/or completing a few process instances and human tasks, you can generate a report of what has happened so far. Under "Dashboards", select "Process & Task Dashboard". This is a set of predefined charts that allow users to spot what is going on in the system. Charts can be fully customized as well, as explained in the Business Activity Monitoring chapter.
6.5. 10-Minute Tutorial using Eclipse
The following screencast gives an overview of how to use the Eclipse tooling. It shows you:
-
How to import and execute the evaluation sample project
-
Import the evaluation project (included in the jbpm-installer)
-
Open the Evaluation.bpmn process
-
Open the com.sample.ProcessTest Java class
-
Execute the ProcessTest class to run the process
-
-
How to create a new jBPM project (including sample process and JUnit test)
You can import the evaluation project - a sample included in the jbpm-installer - by selecting "File → Import …", select "Existing Projects into Workspace" and browse to the jbpm-installer/sample/evaluation folder and click "Finish". You can open up the evaluation process and the ProcessTest class. To execute the class, right-click it and select "Run as … - Java Application". The console should show how the process was started and how the different actors in the process completed the tasks assigned to them, to complete the process instance.
You could also create a new project using the jBPM project wizard. The sample projects contain a process and an associated Java file to start the process. Select "File - New … - Project …" and under the "jBPM" category and select "jBPM project". Select to create a project with some example files to get you started quickly and click next. Give the project a name. You can choose from a simple HelloWorld example or a slightly more advanced example using persistence and human tasks. If you select the latter and click Finish, you should see a new project containing a "sample.bpmn" process and a "com.sample.ProcessTest" JUnit test class. You can open the BPMN2 process by double-clicking it. To execute the process, right-click ProcessTest.java and select "Run As - Java Application".
6.6. Configuration
6.6.1. Business Central Authentication
The Business Central web application is using the preinstalled other security domain for authenticating and authorizing users (as specified in the WEB-INF/jboss-web.xml inside the WARs).
The application server uses by default property files based realms - Please note that this configuration is intended only for demo purposes (users, roles and passwords are stored in simple property files on the filesystem).
Authentication is configured in the standalone.xml file as follows:
<security-domain name="other" cache-type="default">
<authentication>
<login-module code="Remoting" flag="optional">
<module-option name="password-stacking" value="useFirstPass"/>
</login-module>
<login-module code="RealmDirect" flag="required">
<module-option name="password-stacking" value="useFirstPass"/>
</login-module>
<login-module code="org.kie.security.jaas.KieLoginModule" flag="optional" module="deployment.business-central.war"/>
</authentication>
</security-domain>
<security-realm name="ApplicationRealm">
<authentication>
<local default-user="$local" allowed-users="*" skip-group-loading="true"/>
<properties path="users.properties" relative-to="jboss.server.config.dir"/>
</authentication>
<authorization>
<properties path="roles.properties" relative-to="jboss.server.config.dir"/>
</authorization>
</security-realm>
These are the default users:
Name | Password | Business Central roles | Task roles |
---|---|---|---|
admin |
admin |
admin,analyst,kiemgmt,rest-all,kie-server |
|
krisv |
krisv |
admin,analyst,rest-all,kie-server |
|
john |
john |
analyst,kie-server |
Accounting,PM |
mary |
mary |
analyst,kie-server |
HR |
sales-rep |
sales-rep |
analyst,kie-server |
sales |
jack |
jack |
analyst,kie-server |
IT |
katy |
katy |
analyst,kie-server |
HR |
salaboy |
salaboy |
admin,analyst,rest-all,kie-server |
IT,HR,Accounting |
kieserver |
kieserver1! |
kie-server |
Authentication can be customized by using any of the following options:
-
The users and groups management screens on the Business Central web application.
Navigate into the Business Central web application and click the menu Home → Admin and selecting Users.
-
The jboss-cli.sh script that comes by default on Wildfly/EAP.
Example for Linux platforms - run the following command and follow the script instructions:
$ ./bin/jboss-cli.sh --commands="embed-server --std-out=echo,/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity(identity=<USERNAME>),/subsystem=elytron/filesystem-realm=ApplicationRealm:set-password(identity=<USERNAME>, clear={password='<PASSWORD>'}),/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity-attribute(identity=<USERNAME>, name=role, value=['admin'])"
6.6.2. Using your own database with the jBPM installer
6.6.2.1. Introduction
jBPM uses the Java Persistence API specification (v2) to allow users to configure whatever datasource they want to use to persist runtime data. As a result, the instructions below describe how you should configure a datasource when using JPA on JBoss application server (e.g. EAP7 or Wildfly10) using a persistence.xml file and configuring your datasource and driver in your application server’s standalone.xml , similar to how you would configure any other application using JPA on the application server. The installer automates some of this (like copying the right files to the right location after installation).
By default, the jbpm-installer uses an H2 database for persisting runtime data. In this section we will:
-
modify the persistence settings for runtime persistence of process instance state
-
test the startup with our new settings!
You will need a local instance of a database, in this case we will use MySQL.
6.6.2.2. Database setup
In the MySQL database used in this quickstart, create a single user:
-
user/schema "jbpm" with password "jbpm" (which will be used to persist all entities)
If you end up using different names for your user/schemas, please make a note of where we insert "jbpm" in the configuration files.
If you want to try this quickstart with another database, a section at the end of this quickstart describes what you may need to modify.
6.6.2.3. Configuration
The following files define the persistence settings for the jbpm-installer demo:
-
jbpm-installer/db/jbpm-persistence-JPA2.xml
-
Application server configuration
-
standalone-*.xml
-
There are multiple standalone.xml files available (depending on whether you are using JBoss EAP or Wildfly and whether you are running the normal or full profile). The full profile is required to use the JMS component for remote integration, so will be used by default by the installer. Best practice is to update all standalone.xml files to have consistent setup but most important is to have standalone-full-wildfly-{version}.xml properly configured as this is used by default by the installer. |
Do the following:
-
Disable H2 default database and enable MySQL database in build.properties
# default is H2 # H2.version=1.3.168 # db.name=h2 # db.driver.jar.name=${db.name}.jar # db.driver.download.url=http://repo1.maven.org/maven2/com/h2database/h2/${H2.version}/h2-${H2.version}.jar #mysql db.name=mysql db.driver.module.prefix=com/mysql db.driver.jar.name=mysql-connector-java-5.1.18.jar db.driver.download.url=https://repository.jboss.org/nexus/service/local/repositories/central/content/mysql/mysql-connector-java/5.1.18/mysql-connector-java-5.1.18.jar org.kie.server.persistence.dialect=org.hibernate.dialect.MySQLDialect
You might want to update the db driver jar name and download url to whatever version of the jar matches your installation. Look to also update the dialect to what matches your installation if needed (for example change to MySQL5Dialect for MySQL 5.x specific features).
-
db/jbpm-persistence-JPA2.xml :
This is the JPA persistence file that defines the persistence settings used by jBPM for the jBPM engine information, the logging/BAM information, and task service.
In this file, you will have to change the name of the hibernate dialect used for your database.
The original line is:
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
In the case of a MySQL database, you need to change it to:
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
For those of you who decided to use another database, a list of the available hibernate dialect classes can be found here.
-
standalone-full-wildfly-{version}.xml :
Standalone.xml and standalone-full.xml are the configuration for the standalone JBoss application server. When the installer installs the demo, it copies these files to the
standalone/configuration
directory in the JBoss server directory. Since the installer uses Wildfly by default as application server, you probably need to change standalone-full-wildfly-{version}.xml .We need to change the datasource configuration in
standalone-full.xml
so that the jBPM engine can use our MySQL database. The original file contains (something very similar to) the following lines:<datasource jta="true" jndi-name="java:jboss/datasources/jbpmDS" pool-name="H2DS" enabled="true" use-java-context="true" use-ccm="true"> <connection-url>jdbc:h2:tcp://localhost/~/jbpm-db;MVCC=TRUE</connection-url> <driver>h2</driver> <security> <user-name>sa</user-name> </security> </datasource> <drivers> <driver name="h2" module="com.h2database.h2"> <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class> </driver> </drivers>
Change the lines to the following:
<datasource jta="true" jndi-name="java:jboss/datasources/jbpmDS" pool-name="MySQLDS" enabled="true" use-java-context="true" use-ccm="true"> <connection-url>jdbc:mysql://localhost:3306/jbpm</connection-url> <driver>mysql</driver> <security> <user-name>jbpm</user-name> <password>jbpm</password> </security> </datasource>
and add an additional driver configuration:
<driver name="mysql" module="com.mysql"> <xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class> </driver>
-
To install driver jars in JBoss application server (Wildfly, EAP, etc.), it is recommended to install the driver jar as a module. The installer already takes care of this mostly: it will copy the driver jar (you specified in the build.properties ) to the right folder inside the modules directory of your server and put a matching module.xml next to it. For MySQL, this file is called db/mysql_module.xml . Open this file and make sure that the file name of the driver jar listed there is identical the driver jar name you specified in the build.properties (including the version). Note that, even if you simply uncommented the default MySQL configuration, you will still need to add the right version here.
-
Starting the demo
We’ve modified all the necessary files at this point. Now would be a good time to make sure your database is started up as well!
The installer script copies this file into the business-central WAR before the WAR is installed on the server. If you have already run the installer, it is recommended to stop the installer and clean it first using
ant stop.demo
and
ant clean.demo
before continuing.
Run
ant install.demo
to (re)install the wars and copy the necessary configuration files. Once you’ve done that, (re)start the demo using
ant start.demo
-
Problems?
If this isn’t working for you, please try the following:
-
Please double check the files you’ve modified: I wrote this, but still made mistakes when changing files!
-
Please make sure that you don’t secretly have another (unmodified) instance of JBoss AS running.
-
If neither of those work (and you’re using MySQL), then please do let us know.
-
6.6.2.4. Using a different database
If you decide to use a different database with this demo, you need to remember the following when going through the steps above:
-
Configuring the jBPM datasource in
standalone.xml
:-
After locating the
java:jboss/datasources/jbpmDS
datasource, you need to provide the following properties specific to your database:-
Change the url of your database
-
Change the user-name and password
-
Change the name of the driver (which you’ll create next)
For example:
<datasource jta="true" jndi-name="java:jboss/datasources/jbpmDS" pool-name="PostgreSQLDS" enabled="true" use-java-context="true" use-ccm="true"> <connection-url>jdbc:postgresql://localhost:5432/jbpm</connection-url> <driver>postgresql</driver> <security> <user-name>jbpm</user-name> <password>jbpm</password> </security> </datasource>
-
-
Add an additional driver configuration:
-
Change the name of the driver to match the name you specified when configuring the datasource in the previous step
-
Change the module of the driver: the database driver jar should be installed as a module (see below) and here you should reference the unique name of the module. Since the installer can take care of automatically generating this module for you (see below), this should match the
db.driver.module.prefix
property inbuild.properties
(where forward slashes are replaced by a point). In the example below, I usedorg/postgresql
asdb.driver.module.prefix
which means that I should then useorg.postgresql
as module name for the driver. -
Fill in the correct name of the XA datasource class to use.
-
For example:
+
<driver name="postgresql" module="org.postgresql"> <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class> </driver>
-
-
You need to change the dialect in persistence.xml to the dialect for your database, for example:
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
-
In order to make sure your driver will be correctly installed in the JBoss application server, there are typically multiple options, like install as a module or as a deployment. It is recommended to install the driver as a module for EAP and Wildfly.
-
Install the driver JAR as a module, which is what the install script does.
-
Otherwise, you can modify and install the downloaded JAR as a deployment. In this case you will have to copy the JAR yourself to the
standalone/deployments
directory.
If you choose to install driver as JBoss module (recommended), please do the following:
-
In
build.properties
, disable the default H2 driver properties# default is H2 # H2.version=1.3.168 # db.name=h2 # db.driver.jar.name=h2-${H2.version}.jar # db.driver.download.url=http://repo1.maven.org/maven2/com/h2database/h2/${H2.version}/h2-${H2.version}.jar
-
Uncomment one of the other example configs (mysql or postgresql) or create your own:
#postgresql db.name=postgresql db.driver.module.prefix=org/postgresql db.driver.jar.name=postgresql-9.1-902.jdbc4.jar db.driver.download.url=https://repository.jboss.org/nexus/content/repositories/thirdparty-uploads/postgresql/postgresql/9.1-902.jdbc4/postgresql-9.1-902.jdbc4.jar
-
Change the
db.name
property inbuild.properties
to a name for your database. -
Change the
db.driver.module.prefix
property to a name for the module of your driver. Note that this should match the module property when configuring the driver in standalone.xml (where forward slashes in the prefix here are replaced by a point). In the example above, I usedorg/postgresql
asdb.driver.module.prefix
which means that I should then useorg.postgresql
as module name for the driver. -
Change the
db.driver.jar.name
property to the name of the jar that contains your database driver. -
Change the
db.driver.download.url
property to where the driver jar can be downloaded. Alternatively, you could manually download the jar yourself, and place it in thedb/drivers
folder, using the same name as you specified in thedb.driver.jar.name
property.
-
-
Lastly, you’ll have to create the
db/${db.name}_module.xml
file. As an example you can use db/mysql_module.xml, so just make a copy of it and:-
Change the name of the module to match the driver module name above
-
Change the name of the module resource path to the name of the
db.driver.jar.name
property.
-
-
For example, the top of the file would look like:
-
<module xmlns="urn:jboss:module:1.0" name="org.postgresql"> <resources> <resource-root path="postgresql-9.1-902.jdbc4.jar"/> </resources>
6.6.3. jBPM database schema scripts (DDL scripts)
By default the demo setup makes use of Hibernate auto DDL generation capabilities to build up the complete database schema, including all tables, sequences, etc. This might not always be welcomed (by your database administrator), and thus the installer provides DDL scripts for most popular databases.
Database name | Location |
---|---|
db2 |
jbpm-db-scripts/db/ddl-scripts/db2 |
derby |
jbpm-db-scripts/db/ddl-scripts/derby |
h2 |
jbpm-db-scripts/db/ddl-scripts/h2 |
hsqldb |
jbpm-db-scripts/db/ddl-scripts/hsqldb |
mysql5 |
jbpm-db-scripts/db/ddl-scripts/mysql5 |
mysqlinnodb |
jbpm-db-scripts/db/ddl-scripts/mysqlinnodb |
oracle |
jbpm-db-scripts/db/ddl-scripts/oracle |
postgresql |
jbpm-db-scripts/db/ddl-scripts/postgresql |
sqlserver |
jbpm-db-scripts/db/ddl-scripts/sqlserver |
sqlserver2008 |
jbpm-db-scripts/db/ddl-scripts/sqlserver2008 |
sybase |
jbpm-db-scripts/db/ddl-scripts/sybase |
DDL scripts are provided for both jBPM and Quartz schemas although Quartz schema DDL script is only required when the timer service should be configured with Quartz database job store. See the section on timers for additional details.
This can be used to initially create the database schema, but it can also serve as the basis for any\ optimization that needs to be applied - such as indexes, etc.
If you use MySQL 5.7 or earlier (MariaDB 10.2.3 or earlier), you also need to run jbpm-db-scripts/db/ddl-scripts/mysql5/mysql-jbpm-amend-auto-increment-procedure.sql This script creates a procedure for jBPM tables (ProcessInstanceInfo/WorkItemInfo/Task) to protect AUTO_INCREMENT counter. Without the procedure, ID values of those tables could be reset on MySQL/MariaDB restart (https://dev.mysql.com/doc/refman/8.0/en/innodb-auto-increment-handling.html#innodb-auto-increment-initialization). It would introduce further side effects. In addition to creating the procedure, you have to call the procedure on MySQL/MariaDB restart. For example, /etc/my.cnf
Write mysql-jbpm-amend-auto-increment-call.sql
|
If you use PostgreSQL with jBPM, you also need to run jbpm-db-scripts/db/ddl-scripts/postgresql/postgresql-jbpm-lo-trigger-clob.sql This script creates triggers for jBPM tables to protect CLOB references of large objects. Without the triggers, vacuumlo tool (https://www.postgresql.org/docs/9.4/static/vacuumlo.html) deletes active large objects so causes an issue to jBPM. If you are already running jBPM without the triggers, you also need to run the following SQLs after applying the triggers to protect existing CLOB.
|
6.6.4. jBPM installer script
jBPM installer ant script performs most of the work automatically and usually does not require additional attention but in case it does, here is a list of available targets that might be needed to perform some of the steps manually.
Target | Description |
---|---|
clean.db |
cleans up database used by jBPM demo (applies only to H2 database) |
clean.demo |
cleans up entire installation so new installation can be performed |
clean.demo.noeclipse |
same as clean.demo but does not remove Eclipse |
clean.eclipse |
removes Eclipse and its workspace |
clean.generated.ddl |
removes DDL scripts generated if any |
clean.jboss |
removes application server with all its deployments |
clean.jboss.repository |
removes repository content for demo setup (guvnor Maven repo, niogit, etc) |
download.db.driver |
downloads DB driver configured in build.properties |
download.ddl.dependencies |
downloads all dependencies required to run DDL script generation tool |
download.droolsjbpm.eclipse |
downloads Drools and jBPM Eclipse plugin |
download.eclipse |
downloads Eclipse distribution |
download.eclipse.gef |
downloads Eclipse GEF feature |
download.jboss |
downloads JBoss Application Server |
download.jBPM.bin |
downloads jBPM binary distribution (jBPM libs and its dependencies) |
download.jBPM.casemgmt |
downloads jBPM case management console |
download.jBPM.console |
downloads jBPM process management console |
download.kie.server |
downloads jBPM process execution server |
install.db.files |
installs DB driver as JBoss module |
install.demo |
installs complete demo environment |
install.demo.eclipse |
installs Eclipse with all jBPM plugins, no server installation |
install.demo.noeclipse |
similar to install.demo but skips Eclipse installation |
install.droolsjbpm-eclipse.into.eclipse |
installs droolsjbpm Eclipse plugin into Eclipse |
install.eclipse |
install Eclipse IDE |
install.jboss |
installs JBoss AS |
install.jBPM-casemgmt.into.jboss |
installs jBPM case management application |
install.jBPM-console.into.jboss |
installs jBPM process management console |
install.kie-server.into.jboss |
installs jBPM process execution server |
6.7. Frequently Asked Questions
Some common issues are explained below.
-
What if the installer complains it cannot download component X?
Are you connected to the Internet? Do you have a firewall turned on? Do you require a proxy? It might be possible that one of the locations we’re downloading the components from is temporarily offline. Try downloading the components manually (possibly from alternate locations) and put them in the jbpm-installer/lib folder.
-
What if the installer complains it cannot extract / unzip a certain JAR/WAR/zip?
If your download failed while downloading a component, it is possible that the installer is trying to use an incomplete file. Try deleting the component in question from the jbpm-installer/lib folder and reinstall, so it will be downloaded again.
-
What if I have been changing my installation (and it no longer works) and I want to start over again with a clean installation?
You can use
ant clean.demo
to remove all the installed components, so you end up with a fresh installation again. -
I sometimes see exceptions when trying to stop or restart certain services, what should I do?
If you see errors during shutdown, are you sure the services were still running? If you see exceptions during restart, are you sure the service you started earlier was successfully shutdown? Maybe try killing the services manually if necessary.
-
Something seems to be going wrong when running Eclipse but I have no idea what. What can I do?
Always check the consoles for output like error messages or stack traces. You can also check the Eclipse Error Log for exceptions. Try adding an audit logger to your session to figure out what’s happening at runtime, or try debugging your application.
-
Something seems to be going wrong when running the web-based application like the business-central. What can I do?
You can check the server log for possible exceptions: jbpm-installer/jboss-as-{version}/standalone/log/server.log (for JBoss AS7).
For all other questions, try contacting the jBPM community as described in the Getting Started chapter.
7. Examples
7.1. Introduction
Business Central provides various sample projects that will help you in getting started with automating business processes. These are bundled together with the application and you can easily try them out by navigating to
and clicking on Try Samples.This section shows the different examples that can be found in the jbpm-playground repository. All these examples are high level and business oriented.
If you want to contribute with these examples please get in touch with any member of the jBPM/Drools Team.
7.2. Importing Projects through Git
To import the Human Resources example, as well as other examples, follow these steps:
-
Logging in to Business Central
-
On the command line, change into the $SERVER_HOME/bin/ directory and execute the following command:
-
for Unix environment:
./standalone.sh
-
for Windows environment:
./standalone.bat
-
-
Once your server is up and running, open the following address in a web browser:
http://localhost:8080/business-central
This opens the login page.
-
Log in to Business Central with the user credentials created during installation.
-
-
Importing Projects Through Git
-
Click
. -
Click Import Project.
-
If your current space contains at least one project, the Import Project option is available under the dropdown menu in the space menu bar.
-
-
In the Import Project dialogue, enter the following information:
-
Repository URL : enter the Git URL you want to import, for example: https://github.com/kiegroup/jbpm-playground.
-
Authentication Options: If the target git repository requires authentication, you can specify the user name and password using the expanded dialog option.
-
-
Click Import.
-
This will import a number of examples into your instance of jBPM.
7.3. Human Resources Example
The Human Resource Example’s use case can be described as follows: A company wants to hire new developers. In this process, three departments (that is the Human resources, IT, and Accounting) are involved. These departments are represented by three users: Katy, Jack, and John respectively.
Note that only four out of the six defined activities within the business process are User Tasks. User Tasks require human interaction. The other two tasks are Service Tasks, which are automated and connected to other systems.
Each instance of the process will follow certain actions:
-
The human resources team performs the initial interview with the candidate.
-
The IT department team performs the technical interview.
-
Based on the output from the previous two steps, the accounting team creates a job proposal.
-
When the proposal has been drafted, it is automatically sent to the candidate via email.
-
If the candidate accepts the proposal, a new meeting to sign the contract is scheduled.
-
Finally, if the candidate accepts the proposal, the system posts a message about the new hire using Twitter service connector.
Note, that Jack, John, and Katy represent any employee within the company with appropriate role assigned.
7.3.1. The Kie Project: human-resources
To start exploring the project:
-
Click
. -
Click
.
The asset list page contains the hiring.bpmn2 process and a set of forms for each human task. Click these assets to explore. Notice that different editors open for different types of assets.
7.3.2. Building the Human Resources Example
To build the Project:
-
Click
. -
Click Human Resources Kjar Example.
-
Click Deploy.
Deploy creates a new JAR artifact that is deployed to the runtime environment as a new deployment unit.
After successfully building and deploying your project, you can verify its presence in the Execution Servers tab. Click to do so.
When you Deploy a project from the Project Editor, it is deployed using the default configuration which means using the Singleton strategy, the default Kie Base and the default Kie session.
If you want to change these settings, you can make the necessary adjustments on the Settings tab for the specific project. Then, you will be able to set a different strategy, or use a non-default Kie Base or Kie Session. Once you saved your settings you can redeploy the project as a new Deployment Unit.
Once your artifact that contains the process definition is deployed, the Process Definition will become available in
.7.3.3. Create a new Process Instance
To create new process instances:
Click
.Start your instance:
The Process Definitions section contains all the available process definitions in the runtime environment. In order to add new process definitions, build and deploy a new project.
Most processes require additional information to create a new process instance. This is done through forms. For this project, fill in the name of the candidate that is to be interviewed.
When you click Submit, you create a new process instance. This creates the first task, that is available for the Human Resources team. To see the task, you need to logout and log in as a user with the appropriate role assigned, that is someone from the Human Resources.
When you start the process, you can interact with the human tasks. To do so, click
.Note that in order to see the tasks in the task list, you need to belong to specific user groups, for which the task is designed. For example, the HR Interview task is visible only for the members of the HR group, and the Tech Interview Task is visible only to the members of the IT group.
7.4. Examples zip
A zip file of examples can also be downloaded from the downloads page, containing various examples that can be opened in the Eclipse-based Developers Tools. Simply download and unzip the examples artefact and import into your Eclipse workspace.
8. jBPM Version Migration Guide
8.1. Deprecated in jBPM 7
Property | Description | jBPM 7 Behavior |
---|---|---|
|
This property is responsible for how the |
In jBPM 7, this is no longer possible: all |
8.2. Changed in jBPM 7
Jira | Description | What to do |
---|---|---|
Value of constant |
Update your code to reflect this change - from old value |
jBPM Core
Using the jBPM Core Engine
9. Core Engine API
9.1. Core engine API for the jBPM engine
The jBPM engine executes business processes. To define the processes, you create business assets, including process definitions and custom tasks.
You can use the Core Engine API to load, execute, and manage processes in the jBPM engine.
Several levels of control are available:
-
At the lowest level, you can directly create a KIE base and a KIE session. A KIE base represents all the assets in a business process. A KIE session is an entity in the jBPM engine that runs instances of a business process. This level provides fine-grained control, but requires explicit declaration and configuration of process instances, task handlers, event handlers, and other jBPM engine entities in your code.
-
You can use the RuntimeManager class to manage sessions and processes. This class provides sessions for required process instances using a configurable strategy. It automatically configures the interaction between the KIE session and task services. It disposes of jBPM engine entities that are no longer necessary, ensuring optimal use of resources. You can use a fluent API to instantiate
RuntimeManager
with the necessary business assets and to configure its environment. -
You can use the Services API to manage the execution of processes. For example, the deployment service deploys business assets into the engine, forming a deployment unit. The process service runs a process from this deployment unit.
If you want to embed the jBPM engine in your application, the Services API is the most convenient option, because it hides the internal details of configuring and managing the engine.
-
Finally, you can deploy a KIE Server that loads business assets from KJAR files and runs processes. KIE Server provides a REST API for loading and managing the processes. You can also use Business Central to manage a KIE Server.
If you use KIE Server, you do not need to use the Core Engine API.
For the full reference information for all public jBPM engine API calls, see the Java documentation. Other API classes also exist in the code, but they are internal APIs that can be changed in later versions. Use public APIs in applications that you develop and maintain.
9.2. KIE base and KIE session
A KIE base contains a reference to all process definitions and other assets relevant for a process. The engine uses this KIE base to look up all information for the process, or for several processes, whenever necessary.
You can load assets into a KIE base from various sources, such as a class path, file system, or process repository. Creating a KIE base is a resource-heavy operation, as it involves loading and parsing assets from various sources. You can dynamically modify the KIE base to add or remove process definitions and other assets at run time.
After you create a KIE base, you can instantiate a KIE session based on this KIE base. Use this KIE session to run processes based on the definitions in the KIE base.
When you use the KIE session to start a process, a new process instance is created. This instance maintains a specific process state. Different instances in the same KIE session can use the same process definition but have different states.
For example, if you develop an application to process sales orders, you can create one or more process definitions that determine how an order should be processed. When starting the application, you first need to create a KIE base that contains those process definitions. You can then create a session based on this KIE base. When a new sales order comes in, start a new process instance for the order. This process instance contains the state of the process for the specific sales request.
You can create many KIE sessions for the same KIE base and you can create many instances of the process within the same KIE session. Creating a KIE session, and also creating a process instance within the KIE session, uses far fewer resources than creating a KIE base. If you modify a KIE base, all the KIE sessions that use it can use the modifications automatically.
In most simple use cases, you can use a single KIE session to execute all processes. You can also use several sessions if needed. For example, if you want order processing for different customers to be completely independent, you can create a KIE session for each customer. You can also use multiple sessions for scalability reasons.
In typical applications you do not need to create a KIE base or KIE session directly. However, when you use other levels of the jBPM engine API, you can interact with elements of the API that this level defines.
9.2.1. KIE base
The KIE base includes all process definitions and other assets that your application might need to execute a business process.
To create a KIE base, use a KieHelper
instance to load processes from various resources, such as the class path or the file system, and to create a new KIE base.
The following code snippet shows how to create a KIE base consisting of only one process definition, which is loaded from the class path.
KieHelper kieHelper = new KieHelper();
KieBase kieBase = kieHelper
.addResource(ResourceFactory.newClassPathResource("MyProcess.bpmn"))
.build();
The ResourceFactory
class has similar methods to load resources from a file, a URL, an InputStream, a Reader, and other sources.
This "manual" process of creating a KIE base is simpler than other alternatives, but can make an application hard to maintain. Use other methods of creating a KIE base, such as the |
9.2.2. KIE session
After creating and loading the KIE base, you can create a KIE session to interact with the jBPM engine. You can use this session to start and manage processes and to signal events.
The following code snippet creates a session based on the KIE base that you created previously and then starts a process instance, referencing the ID in the process definition.
KieSession ksession = kbase.newKieSession();
ProcessInstance processInstance = ksession.startProcess("com.sample.MyProcess");
9.2.3. ProcessRuntime interface
The KieSession
class exposes the ProcessRuntime
interface, which defines all the session methods for interacting with processes, as the following definition shows.
ProcessRuntime
interface /**
* Start a new process instance. Use the process (definition) that
* is referenced by the given process ID.
*
* @param processId The ID of the process to start
* @return the ProcessInstance that represents the instance of the process that was started
*/
ProcessInstance startProcess(String processId);
/**
* Start a new process instance. Use the process (definition) that
* is referenced by the given process ID. You can pass parameters
* to the process instance as name-value pairs, and these parameters set
* variables of the process instance.
*
* @param processId the ID of the process to start
* @param parameters the process variables to set when starting the process instance
* @return the ProcessInstance that represents the instance of the process that was started
*/
ProcessInstance startProcess(String processId,
Map<String, Object> parameters);
/**
* Signals the jBPM engine that an event has occurred. The type parameter defines
* the type of event and the event parameter can contain additional information
* related to the event. All process instances that are listening to this type
* of (external) event will be notified. For performance reasons, use this type of
* event signaling only if one process instance must be able to notify
* other process instances. For internal events within one process instance, use the
* signalEvent method that also include the processInstanceId of the process instance
* in question.
*
* @param type the type of event
* @param event the data associated with this event
*/
void signalEvent(String type,
Object event);
/**
* Signals the process instance that an event has occurred. The type parameter defines
* the type of event and the event parameter can contain additional information
* related to the event. All node instances inside the given process instance that
* are listening to this type of (internal) event will be notified. Note that the event
* will only be processed inside the given process instance. All other process instances
* waiting for this type of event will not be notified.
*
* @param type the type of event
* @param event the data associated with this event
* @param processInstanceId the id of the process instance that should be signaled
*/
void signalEvent(String type,
Object event,
long processInstanceId);
/**
* Returns a collection of currently active process instances. Note that only process
* instances that are currently loaded and active inside the jBPM engine are returned.
* When using persistence, it is likely not all running process instances are loaded
* as their state is stored persistently. It is best practice not to use this
* method to collect information about the state of your process instances but to use
* a history log for that purpose.
*
* @return a collection of process instances currently active in the session
*/
Collection<ProcessInstance> getProcessInstances();
/**
* Returns the process instance with the given ID. Note that only active process instances
* are returned. If a process instance has been completed already, this method returns
* null.
*
* @param id the ID of the process instance
* @return the process instance with the given ID, or null if it cannot be found
*/
ProcessInstance getProcessInstance(long processInstanceId);
/**
* Aborts the process instance with the given ID. If the process instance has been completed
* (or aborted), or if the process instance cannot be found, this method will throw an
* IllegalArgumentException.
*
* @param id the ID of the process instance
*/
void abortProcessInstance(long processInstanceId);
/**
* Returns the WorkItemManager related to this session. This object can be used to
* register new WorkItemHandlers or to complete (or abort) WorkItems.
*
* @return the WorkItemManager related to this session
*/
WorkItemManager getWorkItemManager();
9.2.4. Correlation Keys
When working with processes, you might need to assign a business identifier to a process instance and then use the identifier to reference the instance without storing the generated instance ID.
To provide such capabilities, the jBPM engine uses the CorrelationKey
interface, which can define CorrelationProperties
. A class that implements CorrelationKey
can have either a single property describing it or a multi-property set. The value of the property or a combination of values of several properties refers to a unique instance.
The KieSession
class implements the CorrelationAwareProcessRuntime
interface to support correlation capabilities. This interface exposes the following methods:
CorrelationAwareProcessRuntime
interface /**
* Start a new process instance. Use the process (definition) that
* is referenced by the given process ID. You can pass parameters
* to the process instance (as name-value pairs), and these parameters set
* variables of the process instance.
*
* @param processId the ID of the process to start
* @param correlationKey custom correlation key that can be used to identify the process instance
* @param parameters the process variables to set when starting the process instance
* @return the ProcessInstance that represents the instance of the process that was started
*/
ProcessInstance startProcess(String processId, CorrelationKey correlationKey, Map<String, Object> parameters);
/**
* Create a new process instance (but do not yet start it). Use the process
* (definition) that is referenced by the given process ID.
* You can pass to the process instance (as name-value pairs),
* and these parameters set variables of the process instance.
* Use this method if you need a reference to the process instance before actually
* starting it. Otherwise, use startProcess.
*
* @param processId the ID of the process to start
* @param correlationKey custom correlation key that can be used to identify the process instance
* @param parameters the process variables to set when creating the process instance
* @return the ProcessInstance that represents the instance of the process that was created (but not yet started)
*/
ProcessInstance createProcessInstance(String processId, CorrelationKey correlationKey, Map<String, Object> parameters);
/**
* Returns the process instance with the given correlationKey. Note that only active process instances
* are returned. If a process instance has been completed already, this method will return
* null.
*
* @param correlationKey the custom correlation key assigned when the process instance was created
* @return the process instance identified by the key or null if it cannot be found
*/
ProcessInstance getProcessInstance(CorrelationKey correlationKey);
Correlation is usually used with long-running processes. You must enable persistence if you want to store correlation information permanently.
9.3. Runtime manager
The RuntimeManager
class provides a layer in the jBPM engine API that simplifies and empowers its usage. This class encapsulates and manages the KIE base and KIE session, as well as the task service that provides handlers for all tasks in the process. The KIE session and the task service within the runtime manager are already configured to work with each other and you do not need to provide such configuration. For example, you do not need to register a human task handler and to ensure that it is connected to the required service.
The runtime manager manages the KIE session according to a predefined strategy. The following strategies are available:
-
Singleton: The runtime manager maintains a single
KieSession
and uses it for all the requested processes. -
Per Request: The runtime manager creates a new
KieSession
for every request. -
Per Process Instance: The runtime manager maintains mapping between process instance and
KieSession
and always provides the sameKieSession
whenever working with a given process instance.
Regardless of the strategy, the RuntimeManager
class ensures the same capabilities in initialization and configuration of the jBPM engine components:
-
KieSession
instances are loaded with the same factories (either in memory or JPA based). -
Work item handlers are registered on every
KieSession
instance (either loaded from the database or newly created). -
Event listeners (
Process
,Agenda
,WorkingMemory
) are registered on every KIE session, whether the session is loaded from the database or newly created. -
The task service is configured with the following required components:
-
The JTA transaction manager
-
The same entity manager factory as the one used for
KieSession
instances -
The
UserGroupCallback
instance that can be configured in the environment
-
The runtime manager also enables disposing the jBPM engine cleanly. It provides dedicated methods to dispose a RuntimeEngine
instance when it is no longer needed, releasing any resources it might have acquired.
The following code shows the definition of the RuntimeManager
interface:
RuntimeManager
interfacepublic interface RuntimeManager {
/**
* Returns a <code>RuntimeEngine</code> instance that is fully initialized:
* <ul>
* <li>KieSession is created or loaded depending on the strategy</li>
* <li>TaskService is initialized and attached to the KIE session (through a listener)</li>
* <li>WorkItemHandlers are initialized and registered on the KIE session</li>
* <li>EventListeners (process, agenda, working memory) are initialized and added to the KIE session</li>
* </ul>
* @param context the concrete implementation of the context that is supported by given <code>RuntimeManager</code>
* @return instance of the <code>RuntimeEngine</code>
*/
RuntimeEngine getRuntimeEngine(Context<?> context);
/**
* Unique identifier of the <code>RuntimeManager</code>
* @return
*/
String getIdentifier();
/**
* Disposes <code>RuntimeEngine</code> and notifies all listeners about that fact.
* This method should always be used to dispose <code>RuntimeEngine</code> that is not needed
* anymore. <br/>
* Do not use KieSession.dispose() used with RuntimeManager as it will break the internal
* mechanisms of the manager responsible for clear and efficient disposal.<br/>
* Disposing is not needed if <code>RuntimeEngine</code> was obtained within an active JTA transaction,
* if the getRuntimeEngine method was invoked during active JTA transaction, then disposing of
* the runtime engine will happen automatically on transaction completion.
* @param runtime
*/
void disposeRuntimeEngine(RuntimeEngine runtime);
/**
* Closes <code>RuntimeManager</code> and releases its resources. Call this method when
* a runtime manager is not needed anymore. Otherwise it will still be active and operational.
*/
void close();
}
The RuntimeManager
class also provides the RuntimeEngine
class, which includes methods to get access to underlying jBPM engine components:
RuntimeEngine
interfacepublic interface RuntimeEngine {
/**
* Returns the <code>KieSession</code> configured for this <code>RuntimeEngine</code>
* @return
*/
KieSession getKieSession();
/**
* Returns the <code>TaskService</code> configured for this <code>RuntimeEngine</code>
* @return
*/
TaskService getTaskService();
}
An identifier of the The same If you don’t specify an identifier when creating a If you maintain multiple runtime managers in your application, you must specify a unique identifier for every For example, the deployment service maintains multiple runtime managers and uses the GAV value of the KJAR file as an identifier. The same logic is used in Business Central and in KIE Server, because they depend on the deployment service. |
When you need to interact with the jBPM engine or task service from within a handler or a listener, you can use the |
9.3.1. Runtime manager strategies
The RuntimeManager
class supports the following strategies for managing KIE sessions.
- Singleton strategy
-
This strategy instructs the runtime manager to maintain a single
RuntimeEngine
instance (and in turn singleKieSession
andTaskService
instances). Access to the runtime engine is synchronized and, therefore, thread safe, although it comes with a performance penalty due to synchronization.This strategy is similar to what was available by default in jBPM version 5.x. Use this strategy for simple use cases.
This strategy has the following characteristics:
-
It has a small memory footprint, with single instances of the runtime engine and the task service.
-
It is simple and compact in design and usage.
-
It is a good fit for low-to-medium load on the jBPM engine because of synchronized access.
-
In this strategy, because of the single
KieSession
instance, all state objects (such as facts) are directly visible to all process instances and vice versa. -
The strategy is not contextual. When you retrieve instances of
RuntimeEngine
from a singletonRuntimeManager
, you do not need to take theContext
instance into account. Usually, you can useEmptyContext.get()
as the context, although a null argument is acceptable as well. -
In this strategy, the runtime manager keeps track of the ID of the
KieSession
, so that the same session remains in use after aRuntimeManager
restart. The ID is stored as a serialized file in a temporary location in the file system that, depending on the environment, can be one of the following directories:-
The value of the
jbpm.data.dir
system property -
The value of the
jboss.server.data.dir
system property -
The value of the
java.io.tmpdir
system property
-
A combination of the Singleton strategy and the EJB Timer Scheduler might raise Hibernate issues under load. Do not use this combination in production applications. The EJB Timer Scheduler is the default scheduler in KIE Server.
-
- Per request strategy
-
This strategy instructs the runtime manager to provide a new instance of
RuntimeEngine
for every request. One or more invocations of the jBPM engine within a single transaction are considered a single request.The same instance of
RuntimeEngine
must be used within a single transaction to ensure correctness of state. Otherwise, an operation completed in one call would not be visible in the next call.This strategy is stateless, as process state is preserved only within the request. When a request is completed, the
RuntimeEngine
instance is permanently destroyed. If persistence is used, information related to the KIE session is removed from the persistence database as well.This strategy has the following characteristics:
-
It provides completely isolated jBPM engine and task service operations for every request.
-
It is completely stateless, because facts are stored only for the duration of the request.
-
It is a good fit for high-load, stateless processes, where no facts or timers must be preserved between requests.
-
In this strategy, the KIE session is only available during the life of a request and is destroyed at the end of the request.
-
The strategy is not contextual. When you retrieve instances of
RuntimeEngine
from a per-requestRuntimeManager
, you do not need to take theContext
instance into account. Usually, you can useEmptyContext.get()
as the context, although a null argument is acceptable as well.
-
- Per process instance strategy
-
This strategy instructs
RuntimeManager
to maintain a strict relationship between a KIE session and a process instance. EachKieSession
is available as long as theProcessInstance
to which it belongs is active.This strategy provides the most flexible approach for using advanced capabilities of the jBPM engine, such as rule evaluation and isolation between process instances. It maximizes performance and reduces potential bottlenecks introduced by synchronization. At the same time, unlike the request strategy, it reduces the number of KIE sessions to the actual number of process instances, rather than the total number of requests.
This strategy has the following characteristics:
-
It provides isolation for every process instance.
-
It maintains a strict relationship between
KieSession
andProcessInstance
to ensure that it always delivers the sameKieSession
for a givenProcessInstance
. -
It merges the lifecycle of
KieSession
withProcessInstance
, and both are disposed when the process instance completes or aborts. -
It enables maintenance of data, such as facts and timers, in the scope of the process instance. Only the process instance has access to the data.
-
It introduces some overhead because of the need to look up and load the
KieSession
for the process instance. -
It validates every usage of a
KieSession
so it cannot be used for other process instances. An exception is thrown if another process instance uses the sameKieSession
. -
The strategy is contextual and accepts the following context instances:
-
EmptyContext
or null: Used when starting a process instance because no process instance ID is available yet -
ProcessInstanceIdContext
: Used after the process instance is created -
CorrelationKeyContext
: Used as an alternative toProcessInstanceIdContext
to use a custom (business) key instead of the process instance ID
-
-
9.3.2. Typical usage scenario for the runtime manager
The typical usage scenario for the runtime manager consists of the following stages:
-
At application startup time, complete the following stage:
-
Build a
RuntimeManager
instance and keep it for the entire lifetime of the application, as it is thread-safe and can be accessed concurrently.
-
-
At request time, complete the following stages:
-
Get
RuntimeEngine
from theRuntimeManager
, using the proper context instance as determined by the strategy that you configured for theRuntimeManager
class. -
Get the
KieSession
andTaskService
objects from theRuntimeEngine
. -
Use the
KieSession
andTaskService
objects for operations such asstartProcess
orcompleteTask
. -
After completing processing, dispose
RuntimeEngine
using theRuntimeManager.disposeRuntimeEngine
method.
-
-
At application shutdown time, complete the following stage:
-
Close the
RuntimeManager
instance.
-
When |
The following example shows how you can build a RuntimeManager
instance and get a RuntimeEngine
instance (that encapsulates KieSession
and TaskService
classes) from it:
RuntimeManager
instance and then getting RuntimeEngine
and KieSession
// First, configure the environment to be used by RuntimeManager
RuntimeEnvironment environment = RuntimeEnvironmentBuilder.Factory.get()
.newDefaultInMemoryBuilder()
.addAsset(ResourceFactory.newClassPathResource("BPMN2-ScriptTask.bpmn2"), ResourceType.BPMN2)
.get();
// Next, create the RuntimeManager - in this case the singleton strategy is chosen
RuntimeManager manager = RuntimeManagerFactory.Factory.get().newSingletonRuntimeManager(environment);
// Then get RuntimeEngine from the runtime manager, using an empty context because singleton does not keep track
// of runtime engine as there is only one
RuntimeEngine runtime = manager.getRuntimeEngine(EmptyContext.get());
// Get the KieSession from the RuntimeEngine - already initialized with all handlers, listeners, and other requirements
// configured on the environment
KieSession ksession = runtimeEngine.getKieSession();
// Add invocations of the jBPM engine here,
// for example, ksession.startProcess(processId);
// Finally, dispose the runtime engine
manager.disposeRuntimeEngine(runtimeEngine);
This example provides the simplest, or minimal, way of using RuntimeManager
and RuntimeEngine
classes. It has the following characteristics:
-
The
KieSession
instance is created in memory, using thenewDefaultInMemoryBuilder
builder. -
A single process, which is added as an asset, is available for execution.
-
The
TaskService
class is configured and attached to theKieSession
instance through theLocalHTWorkItemHandler
interface to support user task capabilities within processes.
9.3.3. Runtime environment configuration object
The RuntimeManager
class encapsulates internal jBPM engine complexity, such as creating, disposing, and registering handlers.
It also provides fine-grained control over jBPM engine configuration. To set this configuration, you must create a RuntimeEnvironment
object and then use it to create the RuntimeManager
object.
The following definition shows the methods available in the RuntimeEnvironment
interface:
RuntimeEnvironment
interface public interface RuntimeEnvironment {
/**
* Returns <code>KieBase</code> that is to be used by the manager
* @return
*/
KieBase getKieBase();
/**
* KieSession environment that is to be used to create instances of <code>KieSession</code>
* @return
*/
Environment getEnvironment();
/**
* KieSession configuration that is to be used to create instances of <code>KieSession</code>
* @return
*/
KieSessionConfiguration getConfiguration();
/**
* Indicates if persistence is to be used for the KieSession instances
* @return
*/
boolean usePersistence();
/**
* Delivers a concrete implementation of <code>RegisterableItemsFactory</code> to obtain handlers and listeners
* that is to be registered on instances of <code>KieSession</code>
* @return
*/
RegisterableItemsFactory getRegisterableItemsFactory();
/**
* Delivers a concrete implementation of <code>UserGroupCallback</code> that is to be registered on instances
* of <code>TaskService</code> for managing users and groups.
* @return
*/
UserGroupCallback getUserGroupCallback();
/**
* Delivers a custom class loader that is to be used by the jBPM engine and task service instances
* @return
*/
ClassLoader getClassLoader();
/**
* Closes the environment, permitting closing of all dependent components such as ksession factories
*/
void close();
9.3.4. Runtime environment builder
To create an instance of RuntimeEnvironment
that contains the required data, use the RuntimeEnvironmentBuilder
class. This class provides a fluent API to configure a RuntimeEnvironment
instance with predefined settings.
The following definition shows the methods in the RuntimeEnvironmentBuilder
interface:
RuntimeEnvironmentBuilder
interfacepublic interface RuntimeEnvironmentBuilder {
public RuntimeEnvironmentBuilder persistence(boolean persistenceEnabled);
public RuntimeEnvironmentBuilder entityManagerFactory(Object emf);
public RuntimeEnvironmentBuilder addAsset(Resource asset, ResourceType type);
public RuntimeEnvironmentBuilder addEnvironmentEntry(String name, Object value);
public RuntimeEnvironmentBuilder addConfiguration(String name, String value);
public RuntimeEnvironmentBuilder knowledgeBase(KieBase kbase);
public RuntimeEnvironmentBuilder userGroupCallback(UserGroupCallback callback);
public RuntimeEnvironmentBuilder registerableItemsFactory(RegisterableItemsFactory factory);
public RuntimeEnvironment get();
public RuntimeEnvironmentBuilder classLoader(ClassLoader cl);
public RuntimeEnvironmentBuilder schedulerService(Object globalScheduler);
Use the RuntimeEnvironmentBuilderFactory
class to obtain instances of RuntimeEnvironmentBuilder
. Along with empty instances with no settings, you can get builders with several preconfigured sets of configuration options for the runtime manager.
The following definition shows the methods in the RuntimeEnvironmentBuilderFactory
interface:
RuntimeEnvironmentBuilderFactory
interfacepublic interface RuntimeEnvironmentBuilderFactory {
/**
* Provides a completely empty <code>RuntimeEnvironmentBuilder</code> instance to manually
* set all required components instead of relying on any defaults.
* @return new instance of <code>RuntimeEnvironmentBuilder</code>
*/
public RuntimeEnvironmentBuilder newEmptyBuilder();
/**
* Provides default configuration of <code>RuntimeEnvironmentBuilder</code> that is based on:
* <ul>
* <li>DefaultRuntimeEnvironment</li>
* </ul>
* @return new instance of <code>RuntimeEnvironmentBuilder</code> that is already preconfigured with defaults
*
* @see DefaultRuntimeEnvironment
*/
public RuntimeEnvironmentBuilder newDefaultBuilder();
/**
* Provides default configuration of <code>RuntimeEnvironmentBuilder</code> that is based on:
* <ul>
* <li>DefaultRuntimeEnvironment</li>
* </ul>
* but does not have persistence for the jBPM engine configured so it will only store process instances in memory
* @return new instance of <code>RuntimeEnvironmentBuilder</code> that is already preconfigured with defaults
*
* @see DefaultRuntimeEnvironment
*/
public RuntimeEnvironmentBuilder newDefaultInMemoryBuilder();
/**
* Provides default configuration of <code>RuntimeEnvironmentBuilder</code> that is based on:
* <ul>
* <li>DefaultRuntimeEnvironment</li>
* </ul>
* This method is tailored to work smoothly with KJAR files
* @param groupId group id of kjar
* @param artifactId artifact id of kjar
* @param version version number of kjar
* @return new instance of <code>RuntimeEnvironmentBuilder</code> that is already preconfigured with defaults
*
* @see DefaultRuntimeEnvironment
*/
public RuntimeEnvironmentBuilder newDefaultBuilder(String groupId, String artifactId, String version);
/**
* Provides default configuration of <code>RuntimeEnvironmentBuilder</code> that is based on:
* <ul>
* <li>DefaultRuntimeEnvironment</li>
* </ul>
* This method is tailored to work smoothly with KJAR files and use the kbase and ksession settings in the KJAR
* @param groupId group id of kjar
* @param artifactId artifact id of kjar
* @param version version number of kjar
* @param kbaseName name of the kbase defined in kmodule.xml stored in kjar
* @param ksessionName name of the ksession define in kmodule.xml stored in kjar
* @return new instance of <code>RuntimeEnvironmentBuilder</code> that is already preconfigured with defaults
*
* @see DefaultRuntimeEnvironment
*/
public RuntimeEnvironmentBuilder newDefaultBuilder(String groupId, String artifactId, String version, String kbaseName, String ksessionName);
/**
* Provides default configuration of <code>RuntimeEnvironmentBuilder</code> that is based on:
* <ul>
* <li>DefaultRuntimeEnvironment</li>
* </ul>
* This method is tailored to work smoothly with KJAR files and use the release ID defined in the KJAR
* @param releaseId <code>ReleaseId</code> that described the kjar
* @return new instance of <code>RuntimeEnvironmentBuilder</code> that is already preconfigured with defaults
*
* @see DefaultRuntimeEnvironment
*/
public RuntimeEnvironmentBuilder newDefaultBuilder(ReleaseId releaseId);
/**
* Provides default configuration of <code>RuntimeEnvironmentBuilder</code> that is based on:
* <ul>
* <li>DefaultRuntimeEnvironment</li>
* </ul>
* This method is tailored to work smoothly with KJAR files and use the kbase, ksession, and release ID settings in the KJAR
* @param releaseId <code>ReleaseId</code> that described the kjar
* @param kbaseName name of the kbase defined in kmodule.xml stored in kjar
* @param ksessionName name of the ksession define in kmodule.xml stored in kjar
* @return new instance of <code>RuntimeEnvironmentBuilder</code> that is already preconfigured with defaults
*
* @see DefaultRuntimeEnvironment
*/
public RuntimeEnvironmentBuilder newDefaultBuilder(ReleaseId releaseId, String kbaseName, String ksessionName);
/**
* Provides default configuration of <code>RuntimeEnvironmentBuilder</code> that is based on:
* <ul>
* <li>DefaultRuntimeEnvironment</li>
* </ul>
* It relies on KieClasspathContainer that requires the presence of kmodule.xml in the META-INF folder which
* defines the kjar itself.
* Expects to use default kbase and ksession from kmodule.
* @return new instance of <code>RuntimeEnvironmentBuilder</code> that is already preconfigured with defaults
*
* @see DefaultRuntimeEnvironment
*/
public RuntimeEnvironmentBuilder newClasspathKmoduleDefaultBuilder();
/**
* Provides default configuration of <code>RuntimeEnvironmentBuilder</code> that is based on:
* <ul>
* <li>DefaultRuntimeEnvironment</li>
* </ul>
* It relies on KieClasspathContainer that requires the presence of kmodule.xml in the META-INF folder which
* defines the kjar itself.
* @param kbaseName name of the kbase defined in kmodule.xml
* @param ksessionName name of the ksession define in kmodule.xml
* @return new instance of <code>RuntimeEnvironmentBuilder</code> that is already preconfigured with defaults
*
* @see DefaultRuntimeEnvironment
*/
public RuntimeEnvironmentBuilder newClasspathKmoduleDefaultBuilder(String kbaseName, String ksessionName);
The runtime manager also provides access to a TaskService
object as an integrated component of a RuntimeEngine
object, configured to communicate with the KIE session. If you use one of the default builders, the following configuration settings for the task service are present:
-
The persistence unit name is set to
org.jbpm.persistence.jpa
(for both jBPM engine and task service). -
The human task handler is registered on the KIE session.
-
The JPA-based history log event listener is registered on the KIE session.
-
An event listener to trigger rule task evaluation (
fireAllRules
) is registered on the KIE session.
9.3.5. Registration of handlers and listeners for runtime engines
If you use the runtime manager API, the runtime engine object represents the jBPM engine.
To extend runtime engines with your own handlers or listeners, you can implement the RegisterableItemsFactory
interface and then include it in the runtime environment using the RuntimeEnvironmentBuilder.registerableItemsFactory()
method. Then the runtime manager automatically adds the handlers or listeners to every runtime engine it creates.
The following definition shows the methods in the RegisterableItemsFactory
interface:
RegisterableItemsFactory
interface /**
* Returns new instances of <code>WorkItemHandler</code> that will be registered on <code>RuntimeEngine</code>
* @param runtime provides <code>RuntimeEngine</code> in case handler need to make use of it internally
* @return map of handlers to be registered - in case of no handlers empty map shall be returned.
*/
Map<String, WorkItemHandler> getWorkItemHandlers(RuntimeEngine runtime);
/**
* Returns new instances of <code>ProcessEventListener</code> that will be registered on <code>RuntimeEngine</code>
* @param runtime provides <code>RuntimeEngine</code> in case listeners need to make use of it internally
* @return list of listeners to be registered - in case of no listeners empty list shall be returned.
*/
List<ProcessEventListener> getProcessEventListeners(RuntimeEngine runtime);
/**
* Returns new instances of <code>AgendaEventListener</code> that will be registered on <code>RuntimeEngine</code>
* @param runtime provides <code>RuntimeEngine</code> in case listeners need to make use of it internally
* @return list of listeners to be registered - in case of no listeners empty list shall be returned.
*/
List<AgendaEventListener> getAgendaEventListeners(RuntimeEngine runtime);
/**
* Returns new instances of <code>WorkingMemoryEventListener</code> that will be registered on <code>RuntimeEngine</code>
* @param runtime provides <code>RuntimeEngine</code> in case listeners need to make use of it internally
* @return list of listeners to be registered - in case of no listeners empty list shall be returned.
*/
List<WorkingMemoryEventListener> getWorkingMemoryEventListeners(RuntimeEngine runtime);
The jBPM engine provides default implementations of RegisterableItemsFactory
. You can extend these implementations to define custom handlers and listeners.
The following available implementations might be useful:
-
org.jbpm.runtime.manager.impl.SimpleRegisterableItemsFactory
: The simplest possible implementation. It does not have any predefined content and uses reflection to produce instances of handlers and listeners based on given class names. -
org.jbpm.runtime.manager.impl.DefaultRegisterableItemsFactory
: An extension of the Simple implementation that introduces the same defaults as the default runtime environment builder and still provides the same capabilities as the Simple implementation. -
org.jbpm.runtime.manager.impl.cdi.InjectableRegisterableItemsFactory
: An extension of the Default implementation that is tailored for CDI environments and provides a CDI style approach to finding handlers and listeners using producers.
9.3.5.1. Registering work item handlers using a file
You can register simple work item handlers, which are stateless or rely on the KieSession
state, by defining them in the CustomWorkItem.conf
file and placing the file on the class path.
-
Create a file named
drools.session.conf
in theMETA-INF
subdirectory of the root of the class path. For web applications the directory isWEB-INF/classes/META-INF
. -
Add the following line to the
drools.session.conf
file:drools.workItemHandlers = CustomWorkItemHandlers.conf
-
Create a file named
CustomWorkItemHandlers.conf
in the same directory. -
In the
CustomWorkItemHandlers.conf
file, define custom work item handlers using the MVEL style, similar to the following example:[ "Log": new org.jbpm.process.instance.impl.demo.SystemOutWorkItemHandler(), "WebService": new org.jbpm.process.workitem.webservice.WebServiceWorkItemHandler(ksession), "Rest": new org.jbpm.process.workitem.rest.RESTWorkItemHandler(), "Service Task" : new org.jbpm.process.workitem.bpmn2.ServiceTaskHandler(ksession) ]
The work item handlers that you listed are registered for any KIE session created by the application, regardless of whether the application uses the runtime manager API.
9.3.5.2. Registration of handlers and listeners in a CDI environment
If your application uses the runtime manager API and runs in a CDI environment, your classes can implement the dedicated producer interfaces to provide custom work item handlers and event listeners to all runtime engines.
To create a work item handler, you must implement the WorkItemHandlerProducer
interface.
WorkItemHandlerProducer
interfacepublic interface WorkItemHandlerProducer {
/**
* Returns a map of work items (key = work item name, value= work item handler instance)
* to be registered on the KieSession
* <br/>
* The following parameters are accepted:
* <ul>
* <li>ksession</li>
* <li>taskService</li>
* <li>runtimeManager</li>
* </ul>
*
* @param identifier - identifier of the owner - usually RuntimeManager that allows the producer to filter out
* and provide valid instances for given owner
* @param params - the owner might provide some parameters, usually KieSession, TaskService, RuntimeManager instances
* @return map of work item handler instances (recommendation is to always return new instances when this method is invoked)
*/
Map<String, WorkItemHandler> getWorkItemHandlers(String identifier, Map<String, Object> params);
}
To create an event listener, you must implement the EventListenerProducer
interface. Annotate the event listener producer with the proper qualifier to indicate the type of listeners that it provides. Use one of the following annotations:
-
@Process
forProcessEventListener
-
@Agenda
forAgendaEventListener
-
@WorkingMemory
forWorkingMemoryEventListener
EventListenerProducer
interfacepublic interface EventListenerProducer<T> {
/**
* Returns a list of instances for given (T) type of listeners
* <br/>
* The following parameters are accepted:
* <ul>
* <li>ksession</li>
* <li>taskService</li>
* <li>runtimeManager</li>
* </ul>
* @param identifier - identifier of the owner - usually RuntimeManager that allows the producer to filter out
* and provide valid instances for given owner
* @param params - the owner might provide some parameters, usually KieSession, TaskService, RuntimeManager instances
* @return list of listener instances (recommendation is to always return new instances when this method is invoked)
*/
List<T> getEventListeners(String identifier, Map<String, Object> params);
}
Package your implementations of these interfaces as a bean archive by including beans.xml
in the META-INF
subdirectory. Place the bean archive on the application class path, for example, in WEB-INF/lib
for a web application. The CDI-based runtime manager discovers the packages and registers the work item handlers and event listeners in every KieSession
that it creates or loads from the data store.
The jBPM engine provides certain parameters to the producers to enable stateful and advanced operation. For example, the handlers or listeners can use the parameters to signal the jBPM engine or the process instance in case of an error. The jBPM engine provides the following components as parameters:
-
KieSession
-
TaskService
-
RuntimeManager
In addition, the identifier of the RuntimeManager
class instance is provided as a parameter. You can apply filtering to the identifier to decide whether this RuntimeManager
instance receives the handlers and listeners.
9.4. Services in the jBPM engine
The jBPM engine provides a set of high-level services, running on top of the runtime manager API. This API is available since jBPM version 6.2.
The services provide the most convenient way to embed the jBPM engine in your application. KIE Server also uses these services internally.
When you use services, you do not need to implement your own handling of the runtime manager, runtime engines, sessions, and other jBPM engine entities. However, you can access the underlying RuntimeManager
objects through the services when necessary.
If you use the EJB remote client for the services API, the |
9.4.1. Modules for jBPM engine services
The jBPM engine services are provided as a set of modules. These modules are grouped by their framework dependencies. You can choose the suitable modules and use only these modules, without making your application dependent on the frameworks that other modules use.
The following modules are available:
-
jbpm-services-api
: Only API classes and interfaces -
jbpm-kie-services
: A code implementation of the services API in pure Java without any framework dependencies -
jbpm-services-cdi
: A CDI wrapper on top of the core services implementation -
jbpm-services-ejb-api
: An extension of the services API to support EJB requirements -
jbpm-services-ejb-impl
: EJB wrappers on top of the core services implementation -
jbpm-services-ejb-timer
: A scheduler service based on the EJB timer service to support time-based operations, such as timer events and deadlines -
jbpm-services-ejb-client
: An EJB remote client implementation, currently supporting only Red Hat JBoss EAP
9.4.2. Deployment service
The deployment service deploys and undeploys units in the jBPM engine.
A deployment unit represents the contents of a KJAR file. A deployment unit includes business assets, such as process definitions, rules, forms, and data models. After deploying the unit you can execute the processes it defines. You can also query the available deployment units.
Every deployment unit has a unique identifier string, deploymentId
, also known as deploymentUnitId
. You can use this identifier to apply any service actions to the deployment unit.
In a typical use case for this service, you can load and unload multiple KJARs at the same time and, when necessary, execute processes simultaneously.
The following code sample shows simple use of the deployment service.
// Create deployment unit by providing the GAV of the KJAR
DeploymentUnit deploymentUnit = new KModuleDeploymentUnit(GROUP_ID, ARTIFACT_ID, VERSION);
// Get the deploymentId for the deployed unit
String deploymentId = deploymentUnit.getIdentifier();
// Deploy the unit
deploymentService.deploy(deploymentUnit);
// Retrieve the deployed unit
DeployedUnit deployed = deploymentService.getDeployedUnit(deploymentId);
// Get the runtime manager
RuntimeManager manager = deployed.getRuntimeManager();
The following definition shows the complete DeploymentService
interface:
DeploymentService
interfacepublic interface DeploymentService {
void deploy(DeploymentUnit unit);
void undeploy(DeploymentUnit unit);
RuntimeManager getRuntimeManager(String deploymentUnitId);
DeployedUnit getDeployedUnit(String deploymentUnitId);
Collection<DeployedUnit> getDeployedUnits();
void activate(String deploymentId);
void deactivate(String deploymentId);
boolean isDeployed(String deploymentUnitId);
}
9.4.3. Definition service
When you deploy a process definition using the deployment service, the definition service automatically scans the definition, parses the process, and extracts the information that the jBPM engine requires.
You can use the definition service API to retrieve information about the process definition. The service extracts this information directly from the BPMN2 process definition. The following information is available:
-
Process definition such as ID, name, and description
-
Process variables including the name and type of every variable
-
Reusable sub-processes used in the process (if any)
-
Service tasks that represent domain-specific activities
-
User tasks including assignment information
-
Task data with input and output information
The following code sample shows simple use of the definition service. The processID
must correspond to the ID of a process definition in a KJAR file that you already deployed using the deployment service.
String processId = "org.jbpm.writedocument";
Collection<UserTaskDefinition> processTasks =
bpmn2Service.getTasksDefinitions(deploymentUnit.getIdentifier(), processId);
Map<String, String> processData =
bpmn2Service.getProcessVariables(deploymentUnit.getIdentifier(), processId);
Map<String, String> taskInputMappings =
bpmn2Service.getTaskInputMappings(deploymentUnit.getIdentifier(), processId, "Write a Document" );
You can also use the definition service to scan a definition that you provide as BPMN2-compliant XML content, without the use of a KJAR file. The buildProcessDefinition
method provides this capability.
The following definition shows the complete DefinitionService
interface:
DefinitionService
interfacepublic interface DefinitionService {
ProcessDefinition buildProcessDefinition(String deploymentId, String bpmn2Content, ClassLoader classLoader, boolean cache) throws IllegalArgumentException;
ProcessDefinition getProcessDefinition(String deploymentId, String processId);
Collection<String> getReusableSubProcesses(String deploymentId, String processId);
Map<String, String> getProcessVariables(String deploymentId, String processId);
Map<String, String> getServiceTasks(String deploymentId, String processId);
Map<String, Collection<String>> getAssociatedEntities(String deploymentId, String processId);
Collection<UserTaskDefinition> getTasksDefinitions(String deploymentId, String processId);
Map<String, String> getTaskInputMappings(String deploymentId, String processId, String taskName);
Map<String, String> getTaskOutputMappings(String deploymentId, String processId, String taskName);
}
9.4.4. Process service
The deployment and definition services prepare process data in the jBPM engine. To execute processes based on this data, use the process service. The process service supports interaction with the jBPM engine execution environment, including the following actions:
-
Starting a new process instance
-
Running a process as a single transaction
-
Working with an existing process instance, for example, signalling events, getting information details, and setting values of variables
-
Working with work items
The process service is also a command executor. You can use it to execute commands on the KIE session to extend its capabilities.
The process service is optimized for runtime operations. Use it when you need to run a process or to alter a process instance, for example, signal events or change variables. For read operations, for example, showing available process instances, use the runtime data service. |
The following code sample shows deploying and running a process:
KModuleDeploymentUnit deploymentUnit = new KModuleDeploymentUnit(GROUP_ID, ARTIFACT_ID, VERSION);
deploymentService.deploy(deploymentUnit);
long processInstanceId = processService.startProcess(deploymentUnit.getIdentifier(), "customtask");
ProcessInstance pi = processService.getProcessInstance(processInstanceId);
The startProcess
method expects deploymentId
as the first argument. Using this argument, you can start processes in a certain deployment when your application might have multiple deployments.
For example, you might deploy different versions of the same process from different KJAR files. You can then start the required version using the correct deploymentId
.
The following definition shows the complete ProcessService
interface:
ProcessService
interfacepublic interface ProcessService {
/**
* Starts a process with no variables
*
* @param deploymentId deployment identifier
* @param processId process identifier
* @return process instance IDentifier
* @throws RuntimeException in case of encountered errors
* @throws DeploymentNotFoundException in case a deployment with the given deployment identifier does not exist
* @throws DeploymentNotActiveException in case the deployment with the given deployment identifier is not active
*/
Long startProcess(String deploymentId, String processId);
/**
* Starts a process and sets variables
*
* @param deploymentId deployment identifier
* @param processId process identifier
* @param params process variables
* @return process instance IDentifier
* @throws RuntimeException in case of encountered errors
* @throws DeploymentNotFoundException in case a deployment with the given deployment identifier does not exist
* @throws DeploymentNotActiveException in case the deployment with the given deployment identifier is not active
*/
Long startProcess(String deploymentId, String processId, Map<String, Object> params);
/**
* Starts a process with no variables and assigns a correlation key
*
* @param deploymentId deployment identifier
* @param processId process identifier
* @param correlationKey correlation key to be assigned to the process instance - must be unique
* @return process instance IDentifier
* @throws RuntimeException in case of encountered errors
* @throws DeploymentNotFoundException in case a deployment with the given deployment identifier does not exist
* @throws DeploymentNotActiveException in case the deployment with the given deployment identifier is not active
*/
Long startProcess(String deploymentId, String processId, CorrelationKey correlationKey);
/**
* Starts a process, sets variables, and assigns a correlation key
*
* @param deploymentId deployment identifier
* @param processId process identifier
* @param correlationKey correlation key to be assigned to the process instance - must be unique
* @param params process variables
* @return process instance IDentifier
* @throws RuntimeException in case of encountered errors
* @throws DeploymentNotFoundException in case a deployment with the given deployment identifier does not exist
* @throws DeploymentNotActiveException in case the deployment with the given deployment identifier is not active
*/
Long startProcess(String deploymentId, String processId, CorrelationKey correlationKey, Map<String, Object> params);
/**
* Run a process that is designed to start and finish in a single transaction.
* This method starts the process and returns when the process completes.
* It returns the state of process variables at the outcome of the process
*
* @param deploymentId deployment identifier for the KJAR file of the process
* @param processId process identifier
* @param params process variables
* @return the state of process variables at the end of the process
*/
Map<String, Object> computeProcessOutcome(String deploymentId, String processId, Map<String, Object> params);
/**
* Starts a process at the listed nodes, instead of the normal starting point.
* This method can be used for restarting a process that was aborted. However,
* it does not restore the context of a previous process instance. You must
* supply all necessary variables when calling this method.
* This method does not guarantee that the process is started in a valid state.
*
* @param deploymentId deployment identifier
* @param processId process identifier
* @param params process variables
* @param nodeIds list of BPMN node identifiers where the process must start
* @return process instance IDentifier
* @throws RuntimeException in case of encountered errors
* @throws DeploymentNotFoundException in case a deployment with the given deployment identifier does not exist
* @throws DeploymentNotActiveException in case the deployment with the given deployment identifier is not active
*/
Long startProcessFromNodeIds(String deploymentId, String processId, Map<String, Object> params, String... nodeIds);
/**
* Starts a process at the listed nodes, instead of the normal starting point,
* and assigns a correlation key.
* This method can be used for restarting a process that was aborted. However,
* it does not restore the context of a previous process instance. You must
* supply all necessary variables when calling this method.
* This method does not guarantee that the process is started in a valid state.
*
* @param deploymentId deployment identifier
* @param processId process identifier
* @param key correlation key (must be unique)
* @param params process variables
* @param nodeIds list of BPMN node identifiers where the process must start.
* @return process instance IDentifier
* @throws RuntimeException in case of encountered errors
* @throws DeploymentNotFoundException in case a deployment with the given deployment identifier does not exist
* @throws DeploymentNotActiveException in case the deployment with the given deployment identifier is not active
*/
Long startProcessFromNodeIds(String deploymentId, String processId, CorrelationKey key, Map<String, Object> params, String... nodeIds);
/**
* Aborts the specified process
*
* @param processInstanceId process instance unique identifier
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
void abortProcessInstance(Long processInstanceId);
/**
* Aborts the specified process
*
* @param deploymentId deployment to which the process instance belongs
* @param processInstanceId process instance unique identifier
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
void abortProcessInstance(String deploymentId, Long processInstanceId);
/**
* Aborts all specified processes
*
* @param processInstanceIds list of process instance unique identifiers
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
void abortProcessInstances(List<Long> processInstanceIds);
/**
* Aborts all specified processes
*
* @param deploymentId deployment to which the process instance belongs
* @param processInstanceIds list of process instance unique identifiers
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
void abortProcessInstances(String deploymentId, List<Long> processInstanceIds);
/**
* Signals an event to a single process instance
*
* @param processInstanceId the process instance unique identifier
* @param signalName the ID of the signal in the process
* @param event the event object to be passed with the event
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
void signalProcessInstance(Long processInstanceId, String signalName, Object event);
/**
* Signals an event to a single process instance
*
* @param deploymentId deployment to which the process instance belongs
* @param processInstanceId the process instance unique identifier
* @param signalName the ID of the signal in the process
* @param event the event object to be passed with the event
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
void signalProcessInstance(String deploymentId, Long processInstanceId, String signalName, Object event);
/**
* Signal an event to a list of process instances
*
* @param processInstanceIds list of process instance unique identifiers
* @param signalName the ID of the signal in the process
* @param event the event object to be passed with the event
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
void signalProcessInstances(List<Long> processInstanceIds, String signalName, Object event);
/**
* Signal an event to a list of process instances
*
* @param deploymentId deployment to which the process instances belong
* @param processInstanceIds list of process instance unique identifiers
* @param signalName the ID of the signal in the process
* @param event the event object to be passed with the event
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
void signalProcessInstances(String deploymentId, List<Long> processInstanceIds, String signalName, Object event);
/**
* Signal an event to a single process instance by correlation key
*
* @param correlationKey the unique correlation key of the process instance
* @param signalName the ID of the signal in the process
* @param event the event object to be passed in with the event
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given key was not found
*/
void signalProcessInstanceByCorrelationKey(CorrelationKey correlationKey, String signalName, Object event);
/**
* Signal an event to a single process instance by correlation key
*
* @param deploymentId deployment to which the process instance belongs
* @param correlationKey the unique correlation key of the process instance
* @param signalName the ID of the signal in the process
* @param event the event object to be passed in with the event
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given key was not found
*/
void signalProcessInstanceByCorrelationKey(String deploymentId, CorrelationKey correlationKey, String signalName, Object event);
/**
* Signal an event to given list of correlation keys
*
* @param correlationKeys list of unique correlation keys of process instances
* @param signalName the ID of the signal in the process
* @param event the event object to be passed in with the event
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with one of the given keys was not found
*/
void signalProcessInstancesByCorrelationKeys(List<CorrelationKey> correlationKeys, String signalName, Object event);
/**
* Signal an event to given list of correlation keys
*
* @param deploymentId deployment to which the process instances belong
* @param correlationKeys list of unique correlation keys of process instances
* @param signalName the ID of the signal in the process
* @param event the event object to be passed in with the event
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with one of the given keys was not found
*/
void signalProcessInstancesByCorrelationKeys(String deploymentId, List<CorrelationKey> correlationKeys, String signalName, Object event);
/**
* Signal an event to a any process instance that listens to a given signal and belongs to a given deployment
*
* @param deployment identifier of the deployment
* @param signalName the ID of the signal in the process
* @param event the event object to be passed with the event
* @throws DeploymentNotFoundException in case the deployment unit was not found
*/
void signalEvent(String deployment, String signalName, Object event);
/**
* Returns process instance information. Will return null if no
* active process with the ID is found
*
* @param processInstanceId The process instance unique identifier
* @return Process instance information
* @throws DeploymentNotFoundException in case the deployment unit was not found
*/
ProcessInstance getProcessInstance(Long processInstanceId);
/**
* Returns process instance information. Will return null if no
* active process with the ID is found
*
* @param deploymentId deployment to which the process instance belongs
* @param processInstanceId The process instance unique identifier
* @return Process instance information
* @throws DeploymentNotFoundException in case the deployment unit was not found
*/
ProcessInstance getProcessInstance(String deploymentId, Long processInstanceId);
/**
* Returns process instance information. Will return null if no
* active process with that correlation key is found
*
* @param correlationKey correlation key assigned to the process instance
* @return Process instance information
* @throws DeploymentNotFoundException in case the deployment unit was not found
*/
ProcessInstance getProcessInstance(CorrelationKey correlationKey);
/**
* Returns process instance information. Will return null if no
* active process with that correlation key is found
*
* @param deploymentId deployment to which the process instance belongs
* @param correlationKey correlation key assigned to the process instance
* @return Process instance information
* @throws DeploymentNotFoundException in case the deployment unit was not found
*/
ProcessInstance getProcessInstance(String deploymentId, CorrelationKey correlationKey);
/**
* Sets a process variable.
* @param processInstanceId The process instance unique identifier
* @param variableId The variable ID to set
* @param value The variable value
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
void setProcessVariable(Long processInstanceId, String variableId, Object value);
/**
* Sets a process variable.
*
* @param deploymentId deployment to which the process instance belongs
* @param processInstanceId The process instance unique identifier
* @param variableId The variable id to set.
* @param value The variable value.
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
void setProcessVariable(String deploymentId, Long processInstanceId, String variableId, Object value);
/**
* Sets process variables.
*
* @param processInstanceId The process instance unique identifier
* @param variables map of process variables (key = variable name, value = variable value)
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
void setProcessVariables(Long processInstanceId, Map<String, Object> variables);
/**
* Sets process variables.
*
* @param deploymentId deployment to which the process instance belongs
* @param processInstanceId The process instance unique identifier
* @param variables map of process variables (key = variable name, value = variable value)
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
void setProcessVariables(String deploymentId, Long processInstanceId, Map<String, Object> variables);
/**
* Gets a process instance variable.
*
* @param processInstanceId the process instance unique identifier
* @param variableName the variable name to get from the process
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
Object getProcessInstanceVariable(Long processInstanceId, String variableName);
/**
* Gets a process instance variable.
*
* @param deploymentId deployment to which the process instance belongs
* @param processInstanceId the process instance unique identifier
* @param variableName the variable name to get from the process
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
Object getProcessInstanceVariable(String deploymentId, Long processInstanceId, String variableName);
/**
* Gets a process instance variable values.
*
* @param processInstanceId The process instance unique identifier
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
Map<String, Object> getProcessInstanceVariables(Long processInstanceId);
/**
* Gets a process instance variable values.
*
* @param deploymentId deployment to which the process instance belongs
* @param processInstanceId The process instance unique identifier
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
Map<String, Object> getProcessInstanceVariables(String deploymentId, Long processInstanceId);
/**
* Returns all signals available in current state of given process instance
*
* @param processInstanceId process instance ID
* @return list of available signals or empty list if no signals are available
*/
Collection<String> getAvailableSignals(Long processInstanceId);
/**
* Returns all signals available in current state of given process instance
*
* @param deploymentId deployment to which the process instance belongs
* @param processInstanceId process instance ID
* @return list of available signals or empty list if no signals are available
*/
Collection<String> getAvailableSignals(String deploymentId, Long processInstanceId);
/**
* Completes the specified WorkItem with the given results
*
* @param id workItem ID
* @param results results of the workItem
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws WorkItemNotFoundException in case a work item with the given ID was not found
*/
void completeWorkItem(Long id, Map<String, Object> results);
/**
* Completes the specified WorkItem with the given results
*
* @param deploymentId deployment to which the process instance belongs
* @param processInstanceId process instance ID to which the work item belongs
* @param id workItem ID
* @param results results of the workItem
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws WorkItemNotFoundException in case a work item with the given ID was not found
*/
void completeWorkItem(String deploymentId, Long processInstanceId, Long id, Map<String, Object> results);
/**
* Abort the specified workItem
*
* @param id workItem ID
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws WorkItemNotFoundException in case a work item with the given ID was not found
*/
void abortWorkItem(Long id);
/**
* Abort the specified workItem
*
* @param deploymentId deployment to which the process instance belongs
* @param processInstanceId process instance ID to which the work item belongs
* @param id workItem ID
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws WorkItemNotFoundException in case a work item with the given ID was not found
*/
void abortWorkItem(String deploymentId, Long processInstanceId, Long id);
/**
* Returns the specified workItem
*
* @param id workItem ID
* @return The specified workItem
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws WorkItemNotFoundException in case a work item with the given ID was not found
*/
WorkItem getWorkItem(Long id);
/**
* Returns the specified workItem
*
* @param deploymentId deployment to which the process instance belongs
* @param processInstanceId process instance ID to which the work item belongs
* @param id workItem ID
* @return The specified workItem
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws WorkItemNotFoundException in case a work item with the given ID was not found
*/
WorkItem getWorkItem(String deploymentId, Long processInstanceId, Long id);
/**
* Returns active work items by process instance ID.
*
* @param processInstanceId process instance ID
* @return The list of active workItems for the process instance
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
List<WorkItem> getWorkItemByProcessInstance(Long processInstanceId);
/**
* Returns active work items by process instance ID.
*
* @param deploymentId deployment to which the process instance belongs
* @param processInstanceId process instance ID
* @return The list of active workItems for the process instance
* @throws DeploymentNotFoundException in case the deployment unit was not found
* @throws ProcessInstanceNotFoundException in case a process instance with the given ID was not found
*/
List<WorkItem> getWorkItemByProcessInstance(String deploymentId, Long processInstanceId);
/**
* Executes the provided command on the underlying command executor (usually KieSession)
* @param deploymentId deployment identifier
* @param command actual command for execution
* @return results of the command execution
* @throws DeploymentNotFoundException in case a deployment with the given deployment identifier does not exist
* @throws DeploymentNotActiveException in case the deployment with the given deployment identifier is not active for restricted commands (for example, start process)
*/
public <T> T execute(String deploymentId, Command<T> command);
/**
* Executes the provided command on the underlying command executor (usually KieSession)
* @param deploymentId deployment identifier
* @param context context implementation to be used to get the runtime engine
* @param command actual command for execution
* @return results of the command execution
* @throws DeploymentNotFoundException in case a deployment with the given deployment identifier does not exist
* @throws DeploymentNotActiveException in case the deployment with the given deployment identifier is not active for restricted commands (for example, start process)
*/
public <T> T execute(String deploymentId, Context<?> context, Command<T> command);
}
9.4.5. Runtime Data Service
You can use the runtime data service to retrieve all runtime information about processes, such as started process instances and executed node instances.
For example, you can build a list-based UI to show process definitions, process instances, tasks for a given user, and other data, based on information provided by the runtime data service.
This service is optimized to be as efficient as possible while providing all required information.
The following examples show various usage of this service.
Collection definitions = runtimeDataService.getProcesses(new QueryContext());
Collection<processinstancedesc> instances = runtimeDataService.getProcessInstances(new QueryContext());
Collection<nodeinstancedesc> instances = runtimeDataService.getProcessInstanceHistoryActive(processInstanceId, new QueryContext());
john
List<tasksummary> taskSummaries = runtimeDataService.getTasksAssignedAsPotentialOwner("john", new QueryFilter(0, 10));
The runtime data service methods support two important parameters, QueryContext
and QueryFilter
. QueryFilter
is an extension of QueryContext
. You can use these parameters to manage the result set, providing pagination, sorting, and ordering. You can also use them to apply additional filtering when searching for user tasks.
The following definition shows the methods of the RuntimeDataService
interface:
RuntimeDataService
interfacepublic interface RuntimeDataService {
/**
* Represents type of node instance log entries
*
*/
enum EntryType {
START(0),
END(1),
ABORTED(2),
SKIPPED(3),
OBSOLETE(4),
ERROR(5);
}
// Process instance information
/**
* Returns a list of process instance descriptions
* @param queryContext control parameters for the result, such as sorting and paging
* @return list of {@link ProcessInstanceDesc} instances representing the available process instances
*/
Collection<ProcessInstanceDesc> getProcessInstances(QueryContext queryContext);
/**
* Returns a list of all process instance descriptions with the given statuses and initiated by <code>initiator</code>
* @param states list of possible state (int) values that the {@link ProcessInstance} can have
* @param initiator the initiator of the {@link ProcessInstance}
* @param queryContext control parameters for the result, such as sorting and paging
* @return list of {@link ProcessInstanceDesc} instances representing the process instances that match
* the given criteria (states and initiator)
*/
Collection<ProcessInstanceDesc> getProcessInstances(List<Integer> states, String initiator, QueryContext queryContext);
/**
* Returns a list of process instance descriptions found for the given process ID and statuses and initiated by <code>initiator</code>
* @param states list of possible state (int) values that the {@link ProcessInstance} can have
* @param processId ID of the {@link Process} (definition) used when starting the process instance
* @param initiator initiator of the {@link ProcessInstance}
* @param queryContext control parameters for the result, such as sorting and paging
* @return list of {@link ProcessInstanceDesc} instances representing the process instances that match
* the given criteria (states, processId, and initiator)
*/
Collection<ProcessInstanceDesc> getProcessInstancesByProcessId(List<Integer> states, String processId, String initiator, QueryContext queryContext);
/**
* Returns a list of process instance descriptions found for the given process name and statuses and initiated by <code>initiator</code>
* @param states list of possible state (int) values that the {@link ProcessInstance} can have
* @param processName name (not ID) of the {@link Process} (definition) used when starting the process instance
* @param initiator initiator of the {@link ProcessInstance}
* @param queryContext control parameters for the result, such as sorting and paging
* @return list of {@link ProcessInstanceDesc} instances representing the process instances that match
* the given criteria (states, processName and initiator)
*/
Collection<ProcessInstanceDesc> getProcessInstancesByProcessName(List<Integer> states, String processName, String initiator, QueryContext queryContext);
/**
* Returns a list of process instance descriptions found for the given deployment ID and statuses
* @param deploymentId deployment ID of the runtime
* @param states list of possible state (int) values that the {@link ProcessInstance} can have
* @param queryContext control parameters for the result, such as sorting and paging
* @return list of {@link ProcessInstanceDesc} instances representing the process instances that match
* the given criteria (deploymentId and states)
*/
Collection<ProcessInstanceDesc> getProcessInstancesByDeploymentId(String deploymentId, List<Integer> states, QueryContext queryContext);
/**
* Returns process instance descriptions found for the given processInstanceId. If no descriptions are found, null is returned. At the same time, the method
* fetches all active tasks (in status: Ready, Reserved, InProgress) to provide the information about what user task is keeping each instance
* and who owns the task (if the task is already claimed by a user)
* @param processInstanceId ID of the process instance to be fetched
* @return process instance information, in the form of a {@link ProcessInstanceDesc} instance
*/
ProcessInstanceDesc getProcessInstanceById(long processInstanceId);
/**
* Returns the active process instance description found for the given correlation key. If none is found, returns null. At the same time it
* fetches all active tasks (in status: Ready, Reserved, InProgress) to provide information about which user task is keeping each instance
* and who owns the task (if the task is already claimed by a user)
* @param correlationKey correlation key assigned to the process instance
* @return process instance information, in the form of a {@link ProcessInstanceDesc} instance
*/
ProcessInstanceDesc getProcessInstanceByCorrelationKey(CorrelationKey correlationKey);
/**
* Returns process instances descriptions (regardless of their states) found for the given correlation key. If no descriptions are found, an empty list is returned
* This query uses 'LIKE' to match correlation keys so it accepts partial keys. Matching
* is performed based on a 'starts with' criterion
* @param correlationKey correlation key assigned to the process instance
* @return list of {@link ProcessInstanceDesc} instances representing the process instances that match
* the given correlation key
*/
Collection<ProcessInstanceDesc> getProcessInstancesByCorrelationKey(CorrelationKey correlationKey, QueryContext queryContext);
/**
* Returns process instance descriptions, filtered by their states, that were found for the given correlation key. If none are found, returns an empty list
* This query uses 'LIKE' to match correlation keys so it accepts partial keys. Matching
* is performed based on a 'starts with' criterion
* @param correlationKey correlation key assigned to process instance
* @param states list of possible state (int) values that the {@link ProcessInstance} can have
* @return list of {@link ProcessInstanceDesc} instances representing the process instances that match
* the given correlation key
*/
Collection<ProcessInstanceDesc> getProcessInstancesByCorrelationKeyAndStatus(CorrelationKey correlationKey, List<Integer> states, QueryContext queryContext);
/**
* Returns a list of process instance descriptions found for the given process definition ID
* @param processDefId ID of the process definition
* @param queryContext control parameters for the result, such as sorting and paging
* @return list of {@link ProcessInstanceDesc} instances representing the process instances that match
* the given criteria (deploymentId and states)
*/
Collection<ProcessInstanceDesc> getProcessInstancesByProcessDefinition(String processDefId, QueryContext queryContext);
/**
* Returns a list of process instance descriptions found for the given process definition ID, filtered by state
* @param processDefId ID of the process definition
* @param states list of possible state (int) values that the {@link ProcessInstance} can have
* @param queryContext control parameters for the result, such as sorting and paging
* @return list of {@link ProcessInstanceDesc} instances representing the process instances that match
* the given criteria (deploymentId and states)
*/
Collection<ProcessInstanceDesc> getProcessInstancesByProcessDefinition(String processDefId, List<Integer> states, QueryContext queryContext);
/**
* Returns process instance descriptions that match process instances that have the given variable defined, filtered by state
* @param variableName name of the variable that process instance should have
* @param states list of possible state (int) values that the {@link ProcessInstance} can have. If null, returns only active instances
* @param queryContext control parameters for the result, such as sorting and paging
* @return list of {@link ProcessInstanceDesc} instances representing the process instances that have the given variable defined
*/
Collection<ProcessInstanceDesc> getProcessInstancesByVariable(String variableName, List<Integer> states, QueryContext queryContext);
/**
* Returns process instance descriptions that match process instances that have the given variable defined and the value of the variable matches the given variableValue
* @param variableName name of the variable that process instance should have
* @param variableValue value of the variable to match
* @param states list of possible state (int) values that the {@link ProcessInstance} can have. If null, returns only active instances
* @param queryContext control parameters for the result, such as sorting and paging
* @return list of {@link ProcessInstanceDesc} instances representing the process instances that have the given variable defined with the given value
*/
Collection<ProcessInstanceDesc> getProcessInstancesByVariableAndValue(String variableName, String variableValue, List<Integer> states, QueryContext queryContext);
/**
* Returns a list of process instance descriptions that have the specified parent
* @param parentProcessInstanceId ID of the parent process instance
* @param states list of possible state (int) values that the {@link ProcessInstance} can have. If null, returns only active instances
* @param queryContext control parameters for the result, such as sorting and paging
* @return list of {@link ProcessInstanceDesc} instances representing the available process instances
*/
Collection<ProcessInstanceDesc> getProcessInstancesByParent(Long parentProcessInstanceId, List<Integer> states, QueryContext queryContext);
/**
* Returns a list of process instance descriptions that are subprocesses of the specified process, or subprocesses of those subprocesses, and so on. The list includes the full hierarchy of subprocesses under the specified parent process
* @param processInstanceId ID of the parent process instance
* @return list of {@link ProcessInstanceDesc} instances representing the full hierarchy of this process
*/
Collection<ProcessInstanceDesc> getProcessInstancesWithSubprocessByProcessInstanceId(Long processInstanceId, List<Integer> states, QueryContext queryContext);
// Node and Variable instance information
/**
* Returns the active node instance descriptor for the given work item ID, if the work item exists and is active
* @param workItemId identifier of the work item
* @return NodeInstanceDesc for work item if it exists and is still active, otherwise null is returned
*/
NodeInstanceDesc getNodeInstanceForWorkItem(Long workItemId);
/**
* Returns a trace of all active nodes for the given process instance ID
* @param processInstanceId unique identifier of the process instance
* @param queryContext control parameters for the result, such as sorting and paging
* @return
*/
Collection<NodeInstanceDesc> getProcessInstanceHistoryActive(long processInstanceId, QueryContext queryContext);
/**
* Returns a trace of all executed (completed) nodes for the given process instance ID
* @param processInstanceId unique identifier of the process instance
* @param queryContext control parameters for the result, such as sorting and paging
* @return
*/
Collection<NodeInstanceDesc> getProcessInstanceHistoryCompleted(long processInstanceId, QueryContext queryContext);
/**
* Returns a complete trace of all executed (completed) and active nodes for the given process instance ID
* @param processInstanceId unique identifier of the process instance
* @param queryContext control parameters for the result, such as sorting and paging
* @return {@link NodeInstance} information, in the form of a list of {@link NodeInstanceDesc} instances,
* that come from a process instance that matches the given criteria (deploymentId, processId)
*/
Collection<NodeInstanceDesc> getProcessInstanceFullHistory(long processInstanceId, QueryContext queryContext);
/**
* Returns a complete trace of all events of the given type (START, END, ABORTED, SKIPPED, OBSOLETE or ERROR) for the given process instance
* @param processInstanceId unique identifier of the process instance
* @param queryContext control parameters for the result, such as sorting and paging
* @param type type of events to be returned (START, END, ABORTED, SKIPPED, OBSOLETE or ERROR). To return all events, use {@link #getProcessInstanceFullHistory(long, QueryContext)}
* @return collection of node instance descriptions
*/
Collection<NodeInstanceDesc> getProcessInstanceFullHistoryByType(long processInstanceId, EntryType type, QueryContext queryContext);
/**
* Returns a trace of all nodes for the given node types and process instance ID
* @param processInstanceId unique identifier of the process instance
* @param nodeTypes list of node types to filter nodes of the process instance
* @param queryContext control parameters for the result, such as sorting and paging
* @return collection of node instance descriptions
*/
Collection<NodeInstanceDesc> getNodeInstancesByNodeType(long processInstanceId, List<String> nodeTypes, QueryContext queryContext);
/**
* Returns a trace of all nodes for the given node types and correlation key
* @param correlationKey correlation key
* @param states list of states
* @param nodeTypes list of node types to filter nodes of process instance
* @param queryContext control parameters for the result, such as sorting and paging
* @return collection of node instance descriptions
*/
Collection<NodeInstanceDesc> getNodeInstancesByCorrelationKeyNodeType(CorrelationKey correlationKey, List<Integer> states, List<String> nodeTypes, QueryContext queryContext);
/**
* Returns a collection of all process variables and their current values for the given process instance
* @param processInstanceId process instance ID
* @return information about variables in the specified process instance,
* represented by a list of {@link VariableDesc} instances
*/
Collection<VariableDesc> getVariablesCurrentState(long processInstanceId);
/**
* Returns a collection of changes to the given variable within the scope of a process instance
* @param processInstanceId unique identifier of the process instance
* @param variableId ID of the variable
* @param queryContext control parameters for the result, such as sorting and paging
* @return information about the variable with the given ID in the specified process instance,
* represented by a list of {@link VariableDesc} instances
*/
Collection<VariableDesc> getVariableHistory(long processInstanceId, String variableId, QueryContext queryContext);
// Process information
/**
* Returns a list of process definitions for the given deployment ID
* @param deploymentId deployment ID of the runtime
* @param queryContext control parameters for the result, such as sorting and paging
* @return list of {@link ProcessDefinition} instances representing processes that match
* the given criteria (deploymentId)
*/
Collection<ProcessDefinition> getProcessesByDeploymentId(String deploymentId, QueryContext queryContext);
/**
* Returns a list of process definitions that match the given filter
* @param filter regular expression
* @param queryContext control parameters for the result, such as sorting and paging
* @return list of {@link ProcessDefinition} instances with a name or ID that matches the given regular expression
*/
Collection<ProcessDefinition> getProcessesByFilter(String filter, QueryContext queryContext);
/**
* Returns all process definitions available
* @param queryContext control parameters for the result, such as sorting and paging
* @return list of all available processes, in the form a of a list of {@link ProcessDefinition} instances
*/
Collection<ProcessDefinition> getProcesses(QueryContext queryContext);
/**
* Returns a list of process definition identifiers for the given deployment ID
* @param deploymentId deployment ID of the runtime
* @param queryContext control parameters for the result, such as sorting and paging
* @return list of all available process id's for a particular deployment/runtime
*/
Collection<String> getProcessIds(String deploymentId, QueryContext queryContext);
/**
* Returns process definitions for the given process ID regardless of the deployment
* @param processId ID of the process
* @return collection of {@link ProcessDefinition} instances representing the {@link Process}
* with the specified process ID
*/
Collection<ProcessDefinition> getProcessesById(String processId);
/**
* Returns the process definition for the given deployment and process identifiers
* @param deploymentId ID of the deployment (runtime)
* @param processId ID of the process
* @return {@link ProcessDefinition} instance, representing the {@link Process}
* that is present in the specified deployment with the specified process ID
*/
ProcessDefinition getProcessesByDeploymentIdProcessId(String deploymentId, String processId);
// user task query operations
/**
* Return a task by its workItemId
* @param workItemId
* @return @{@link UserTaskInstanceDesc} task
*/
UserTaskInstanceDesc getTaskByWorkItemId(Long workItemId);
/**
* Return a task by its taskId
* @param taskId
* @return @{@link UserTaskInstanceDesc} task
*/
UserTaskInstanceDesc getTaskById(Long taskId);
/**
* Return a task by its taskId with SLA data if the withSLA param is true
* @param taskId
* @param withSLA
* @return @{@link UserTaskInstanceDesc} task
*/
UserTaskInstanceDesc getTaskById(Long taskId, boolean withSLA);
/**
* Return a list of assigned tasks for a Business Administrator user. Business
* administrators play the same role as task stakeholders but at task type
* level. Therefore, business administrators can perform the exact same
* operations as task stakeholders. Business administrators can also observe
* the progress of notifications
*
* @param userId identifier of the Business Administrator user
* @param filter filter for the list of assigned tasks
* @return list of @{@link TaskSummary} task summaries
*/
List<TaskSummary> getTasksAssignedAsBusinessAdministrator(String userId, QueryFilter filter);
/**
* Return a list of assigned tasks for a Business Administrator user for with one of the listed
* statuses
* @param userId identifier of the Business Administrator user
* @param statuses the statuses of the tasks to return
* @param filter filter for the list of assigned tasks
* @return list of @{@link TaskSummary} task summaries
*/
List<TaskSummary> getTasksAssignedAsBusinessAdministratorByStatus(String userId, List<Status> statuses, QueryFilter filter);
/**
* Return a list of tasks that a user is eligible to own
*
* @param userId identifier of the user
* @param filter filter for the list of tasks
* @return list of @{@link TaskSummary} task summaries
*/
List<TaskSummary> getTasksAssignedAsPotentialOwner(String userId, QueryFilter filter);
/**
* Return a list of tasks the user or user groups are eligible to own
*
* @param userId identifier of the user
* @param groupIds a list of identifiers of the groups
* @param filter filter for the list of tasks
* @return list of @{@link TaskSummary} task summaries
*/
List<TaskSummary> getTasksAssignedAsPotentialOwner(String userId, List<String> groupIds, QueryFilter filter);
/**
* Return a list of tasks the user is eligible to own and that are in one of the listed
* statuses
*
* @param userId identifier of the user
* @param status filter for the task statuses
* @param filter filter for the list of tasks
* @return list of @{@link TaskSummary} task summaries
*/
List<TaskSummary> getTasksAssignedAsPotentialOwnerByStatus(String userId, List<Status> status, QueryFilter filter);
/**
* Return a list of tasks the user or groups are eligible to own and that are in one of the listed
* statuses
* @param userId identifier of the user
* @param groupIds filter for the identifiers of the groups
* @param status filter for the task statuses
* @param filter filter for the list of tasks
* @return list of @{@link TaskSummary} task summaries
*/
List<TaskSummary> getTasksAssignedAsPotentialOwner(String userId, List<String> groupIds, List<Status> status, QueryFilter filter);
/**
* Return a list of tasks the user is eligible to own, that are in one of the listed
* statuses, and that have an expiration date starting at <code>from</code>. Tasks that do not have expiration date set
* will also be included in the result set
*
* @param userId identifier of the user
* @param status filter for the task statuses
* @param from earliest expiration date for the tasks
* @param filter filter for the list of tasks
* @return list of @{@link TaskSummary} task summaries
*/
List<TaskSummary> getTasksAssignedAsPotentialOwnerByExpirationDateOptional(String userId, List<Status> status, Date from, QueryFilter filter);
/**
* Return a list of tasks the user has claimed, that are in one of the listed
* statuses, and that have an expiration date starting at <code>from</code>. Tasks that do not have expiration date set
* will also be included in the result set
*
* @param userId identifier of the user
* @param strStatuses filter for the task statuses
* @param from earliest expiration date for the tasks
* @param filter filter for the list of tasks
* @return list of @{@link TaskSummary} task summaries
*/
List<TaskSummary> getTasksOwnedByExpirationDateOptional(String userId, List<Status> strStatuses, Date from, QueryFilter filter);
/**
* Return a list of tasks the user has claimed
*
* @param userId identifier of the user
* @param filter filter for the list of tasks
* @return list of @{@link TaskSummary} task summaries
*/
List<TaskSummary> getTasksOwned(String userId, QueryFilter filter);
/**
* Return a list of tasks the user has claimed with one of the listed
* statuses
*
* @param userId identifier of the user
* @param status filter for the task statuses
* @param filter filter for the list of tasks
* @return list of @{@link TaskSummary} task summaries
*/
List<TaskSummary> getTasksOwnedByStatus(String userId, List<Status> status, QueryFilter filter);
/**
* Get a list of tasks the Process Instance is waiting on
*
* @param processInstanceId identifier of the process instance
* @return list of task identifiers
*/
List<Long> getTasksByProcessInstanceId(Long processInstanceId);
/**
* Get filter for the tasks the Process Instance is waiting on that are in one of the
* listed statuses
*
* @param processInstanceId identifier of the process instance
* @param status filter for the task statuses
* @param filter filter for the list of tasks
* @return list of @{@link TaskSummary} task summaries
*/
List<TaskSummary> getTasksByStatusByProcessInstanceId(Long processInstanceId, List<Status> status, QueryFilter filter);
/**
* Get a list of task audit logs for all tasks owned by the user, applying a query filter to the list of tasks
*
*
* @param userId identifier of the user that owns the tasks
* @param filter filter for the list of tasks
* @return list of @{@link AuditTask} task audit logs
*/
List<AuditTask> getAllAuditTask(String userId, QueryFilter filter);
/**
* Get a list of task audit logs for all tasks that are active and owned by the user, applying a query filter to the list of tasks
*
* @param userId identifier of the user that owns the tasks
* @param filter filter for the list of tasks
* @return list of @{@link AuditTask} audit tasks
*/
List<AuditTask> getAllAuditTaskByStatus(String userId, QueryFilter filter);
/**
* Get a list of task audit logs for group tasks (actualOwner == null) for the user, applying a query filter to the list of tasks
*
* @param userId identifier of the user that is associated with the group tasks
* @param filter filter for the list of tasks
* @return list of @{@link AuditTask} audit tasks
*/
List<AuditTask> getAllGroupAuditTask(String userId, QueryFilter filter);
/**
* Get a list of task audit logs for tasks that are assigned to a Business Administrator user, applying a query filter to the list of tasks
*
* @param userId identifier of the Business Administrator user
* @param filter filter for the list of tasks
* @return list of @{@link AuditTask} audit tasks
*/
List<AuditTask> getAllAdminAuditTask(String userId, QueryFilter filter);
/**
* Gets a list of task events for the given task
* @param taskId identifier of the task
* @param filter for the list of events
* @return list of @{@link TaskEvent} task events
*/
List<TaskEvent> getTaskEvents(long taskId, QueryFilter filter);
/**
* Query on {@link TaskSummary} instances
* @param userId the user associated with the tasks queried
* @return {@link TaskSummaryQueryBuilder} used to create the query
*/
TaskSummaryQueryBuilder taskSummaryQuery(String userId);
/**
* Gets a list of {@link TaskSummary} instances for tasks that define a given variable
* @param userId the ID of the user associated with the tasks
* @param variableName the name of the task variable
* @param statuses the list of statuses that the task can have
* @param queryContext the query context
* @return a {@link List} of {@link TaskSummary} instances
*/
List<TaskSummary> getTasksByVariable(String userId, String variableName, List<Status> statuses, QueryContext queryContext);
/**
* Gets a list of {@link TaskSummary} instances for tasks that define a given variable and the variable is set to the given value
* @param userId the ID of the user associated with the tasks
* @param variableName the name of the task variable
* @param variableValue the value of the task variable
* @param statuses the list of statuses that the task can have
* @param context the query context
* @return a {@link List} of {@link TaskSummary} instances
*/
List<TaskSummary> getTasksByVariableAndValue(String userId, String variableName, String variableValue, List<Status> statuses, QueryContext context);
}
9.4.6. User Task Service
The user task service covers the complete lifecycle of an individual task, and you can use the service to manage a user task from start to end.
Task queries are not a part of the user task service. Use the runtime data service to query for tasks. Use the user task service for scoped operations on one task, including the following actions:
-
Modification of selected properties
-
Access to task variables
-
Access to task attachments
-
Access to task comments
The user task service is also a command executor. You can use it to execute custom task commands.
The following example shows starting a process and interacting with a task in the process:
long processInstanceId =
processService.startProcess(deployUnit.getIdentifier(), "org.jbpm.writedocument");
List<Long> taskIds =
runtimeDataService.getTasksByProcessInstanceId(processInstanceId);
Long taskId = taskIds.get(0);
userTaskService.start(taskId, "john");
UserTaskInstanceDesc task = runtimeDataService.getTaskById(taskId);
Map<String, Object> results = new HashMap<String, Object>();
results.put("Result", "some document data");
userTaskService.complete(taskId, "john", results);
9.4.7. Quartz-based timer service
The jBPM engine provides a cluster-ready timer service using Quartz. You can use the service to dispose or load your KIE session at any time. The service can manage how long a KIE session is active in order to fire each timer appropriately.
The following example shows a basic Quartz configuration file for a clustered environment:
#============================================================================
# Configure Main Scheduler Properties
#============================================================================
org.quartz.scheduler.instanceName = jBPMClusteredScheduler
org.quartz.scheduler.instanceId = AUTO
#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 5
#============================================================================
# Configure JobStore
#============================================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreCMT
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties=false
org.quartz.jobStore.dataSource=managedDS
org.quartz.jobStore.nonManagedTXDataSource=nonManagedDS
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=true
org.quartz.jobStore.clusterCheckinInterval = 20000
#=========================================================================
# Configure Datasources
#=========================================================================
org.quartz.dataSource.managedDS.jndiURL=jboss/datasources/psbpmsDS
org.quartz.dataSource.nonManagedDS.jndiURL=jboss/datasources/quartzNonManagedDS
You must modify the previous example to fit your environment.
For more information about configuring a Quartz scheduler, see the documentation for the Quartz 1.8.5 distribution archive.
9.4.8. Query service
The query service provides advanced search capabilities that are based on Dashbuilder data sets.
With this approach, you can control how to retrieve data from underlying data store. You can use complex JOIN
statements with external tables such as JPA entities tables or custom systems database tables.
The query service is built around the following two sets of operations:
-
Management operations:
-
Register a query definition
-
Replace a query definition
-
Unregister (remove) a query definition
-
Get a query definition
-
Get all registered query definitions
-
-
Runtime operations:
-
Simple query based on
QueryParam
as the filter provider -
Advanced query based on
QueryParamBuilder
as the filter provider
-
Dashbuilder data sets provide support for multiple data sources, such as CSV, SQL, and Elastic Search. However, the jBPM engine uses a RDBMS-based backend and focuses on SQL-based data sets.
Therefore, the jBPM engine query service is a subset of Dashbuilder data set capabilities that enables efficient queries with a simple API.
9.4.8.1. Key classes of the query service
The query service relies on the following key classes:
-
QueryDefinition
: Represents the definition of a data set. The definition consists of a unique name, an SQL expression (the query) and the source, the JNDI name of the data source to use when performing queries. -
QueryParam
: The basic structure that represents an individual query parameter or condition. This structure consists of the column name, operator, and expected values. -
QueryResultMapper
: The class that maps raw dataset data (rows and columns) to an object representation. -
QueryParamBuilder
: The class that builds query filters that are applied to the query definition to invoke the query.
QueryResultMapper
maps data taken from a database (dataset) to an object representation. It is similar to ORM providers such as hibernate
, which map tables to entities.
Many object types can be used for representing dataset results. Therefore, existing mappers might not always suit your needs. Mappers in QueryResultMapper
are pluggable and you can provide your own mapper when necessary, in order to transform dataset data into any type you need.
The jBPM engine supplies the following mappers:
-
org.jbpm.kie.services.impl.query.mapper.ProcessInstanceQueryMapper
, registered with the nameProcessInstances
-
org.jbpm.kie.services.impl.query.mapper.ProcessInstanceWithVarsQueryMapper
, registered with the nameProcessInstancesWithVariables
-
org.jbpm.kie.services.impl.query.mapper.ProcessInstanceWithCustomVarsQueryMapper
, registered with the nameProcessInstancesWithCustomVariables
-
org.jbpm.kie.services.impl.query.mapper.UserTaskInstanceQueryMapper
, registered with the nameUserTasks
-
org.jbpm.kie.services.impl.query.mapper.UserTaskInstanceWithVarsQueryMapper
, registered with the nameUserTasksWithVariables
-
org.jbpm.kie.services.impl.query.mapper.UserTaskInstanceWithCustomVarsQueryMapper
, registered with nameUserTasksWithCustomVariables
-
org.jbpm.kie.services.impl.query.mapper.TaskSummaryQueryMapper
, registered with the nameTaskSummaries
-
org.jbpm.kie.services.impl.query.mapper.RawListQueryMapper
, registered with the nameRawList
Each QueryResultMapper
is registered with a unique string name. You can look up mappers by this name instead of referencing the full class name. This feature is especially important when using EJB remote invocation of services, because it avoids relying on a particular implementation on the client side.
To reference a QueryResultMapper
by the string name, use NamedQueryMapper
, which is a part of the jbpm-services-api
module. This class acts as a delegate (lazy delegate) and looks up the actual mapper when the query is performed.
NamedQueryMapper
queryService.query("my query def", new NamedQueryMapper<Collection<ProcessInstanceDesc>>("ProcessInstances"), new QueryContext());
QueryParamBuilder
provides an advanced way of building filters for data sets.
By default, when you use a query method of QueryService
that accepts zero or more QueryParam
instances, all of these parameters are joined with an AND
operator, so a data entry must match all of them.
However, sometimes more complicated relationships between parameters are required. You can use QueryParamBuilder
to build custom builders that provide filters at the time the query is issued.
One existing implementation of QueryParamBuilder
is available in the jBPM engine. It covers default QueryParams
that are based on the core functions.
These core functions are SQL-based conditions, including the following conditions:
-
IS_NULL
-
NOT_NULL
-
EQUALS_TO
-
NOT_EQUALS_TO
-
LIKE_TO
-
GREATER_THAN
-
GREATER_OR_EQUALS_TO
-
LOWER_THAN
-
LOWER_OR_EQUALS_TO
-
BETWEEN
-
IN
-
NOT_IN
Before invoking a query, the jBPM engine invokes the build method of the QueryParamBuilder
interface as many times as necessary while the method returns a non-null value. Because of this approach, you can build up complex filter options that could not be expressed by a simple list of QueryParams
.
The following example shows a basic implementation of QueryParamBuilder
. It relies on the DashBuilder Dataset API.
QueryParamBuilder
public class TestQueryParamBuilder implements QueryParamBuilder<ColumnFilter> {
private Map<String, Object> parameters;
private boolean built = false;
public TestQueryParamBuilder(Map<String, Object> parameters) {
this.parameters = parameters;
}
@Override
public ColumnFilter build() {
// return null if it was already invoked
if (built) {
return null;
}
String columnName = "processInstanceId";
ColumnFilter filter = FilterFactory.OR(
FilterFactory.greaterOrEqualsTo((Long)parameters.get("min")),
FilterFactory.lowerOrEqualsTo((Long)parameters.get("max")));
filter.setColumnId(columnName);
built = true;
return filter;
}
}
After implementing the builder, you can use an instance of this class when performing a query with the QueryService
service, as shown in the following example:
QueryService
servicequeryService.query("my query def", ProcessInstanceQueryMapper.get(), new QueryContext(), paramBuilder);
9.4.8.2. Using the query service in a typical scenario
The following procedure outlines the typical way in which your code might use the query service.
-
Define the data set, which is a view of the data you want to use. Use the
QueryDefinition
class in the services API to complete this operation:Defining the data setSqlQueryDefinition query = new SqlQueryDefinition("getAllProcessInstances", "java:jboss/datasources/ExampleDS"); query.setExpression("select * from processinstancelog");
This example represents the simplest possible query definition.
The constructor requires the following parameters:
-
A unique name that identifies the query at run time
-
A JNDI data source name to use for performing queries with this definition
The parameter of the
setExpression()
method is the SQL statement that builds up the data set view. Queries in the query service use data from this view and filter this data as necessary.
-
-
Register the query:
Registering a queryqueryService.registerQuery(query);
-
If required, collect all the data from the dataset, without any filtering:
Collecting all the data from the datasetCollection<ProcessInstanceDesc> instances = queryService.query("getAllProcessInstances", ProcessInstanceQueryMapper.get(), new QueryContext());
This simple query uses defaults from
QueryContext
for paging and sorting. -
If required, use a
QueryContext
object that changes the defaults of the paging and sorting:Changing defaults using aQueryContext
objectQueryContext ctx = new QueryContext(0, 100, "start_date", true); Ā Ā Ā Ā Ā Ā Ā Ā Ā Collection<ProcessInstanceDesc> instances = queryService.query("getAllProcessInstances", ProcessInstanceQueryMapper.get(), ctx);
-
If required, use the query to filter data:
Using a query to filter data// single filter param Collection<ProcessInstanceDesc> instances = queryService.query("getAllProcessInstances", ProcessInstanceQueryMapper.get(), new QueryContext(), QueryParam.likeTo(COLUMN_PROCESSID, true, "org.jbpm%")); Ā // multiple filter params (AND) Collection<ProcessInstanceDesc> instances = queryService.query("getAllProcessInstances", ProcessInstanceQueryMapper.get(), new QueryContext(), Ā QueryParam.likeTo(COLUMN_PROCESSID, true, "org.jbpm%"), Ā QueryParam.in(COLUMN_STATUS, 1, 3));
With the query service, you can define what data to fetch and how to filter it. Limitation of the JPA provider or other similar limitations do not apply. You can tailor database queries to your environment to increase performance.
Further examples can be found here.
9.4.9. Advanced query service
The advanced query service provides capabilities to search for processes and tasks, based on process and task attributes, process variables, and internal variables of user tasks. The search automatically covers all existing processes in the jBPM engine.
The names and required values of attributes and variables are defined in QueryParam
objects.
Process attributes include process instance ID, correlation key, process definition ID, and deployment ID. Task attributes include task name, owner, and status.
The following search methods are available:
-
queryProcessByVariables
: Search for process instances based on a list of process attributes and process variable values. To be included in the result, a process instance must have the listed attributes and the listed values in its process variables. -
queryProcessByVariablesAndTask
: Search for process instances based on a list of process attributes, process variable values, and task variable values. To be included in the result, a process instance must have the listed attributes and the listed values in its process variables. It also must include a task with the listed values in its task variables. -
queryUserTasksByVariables
: Search for user tasks based on a list of task attributes, task variable values, and process variable values. To be included in the result, a task must have the listed attributes and listed values in its task variables. It also must be included in a process with the listed values in its process variables.
The service is provided by the AdvanceRuntimeDataService
class. The interface for this class also defines predefined task and process attribute names.
AdvanceRuntimeDataService
interfacepublic interface AdvanceRuntimeDataService {
String TASK_ATTR_NAME = "TASK_NAME";
String TASK_ATTR_OWNER = "TASK_OWNER";
String TASK_ATTR_STATUS = "TASK_STATUS";
String PROCESS_ATTR_INSTANCE_ID = "PROCESS_INSTANCE_ID";
String PROCESS_ATTR_CORRELATION_KEY = "PROCESS_CORRELATION_KEY";
String PROCESS_ATTR_DEFINITION_ID = "PROCESS_DEFINITION_ID";
String PROCESS_ATTR_DEPLOYMENT_ID = "PROCESS_DEPLOYMENT_ID";
String PROCESS_COLLECTION_VARIABLES = "ATTR_COLLECTION_VARIABLES";
List<ProcessInstanceWithVarsDesc> queryProcessByVariables(List<QueryParam> attributes,
List<QueryParam> processVariables, QueryContext queryContext);
List<ProcessInstanceWithVarsDesc> queryProcessByVariablesAndTask(List<QueryParam> attributes,
List<QueryParam> processVariables, List<QueryParam> taskVariables,
List<String> potentialOwners, QueryContext queryContext);
List<UserTaskInstanceWithPotOwnerDesc> queryUserTasksByVariables(List<QueryParam> attributes,
List<QueryParam> taskVariables, List<QueryParam> processVariables,
List<String> potentialOwners, QueryContext queryContext);
}
9.4.10. Process instance migration service
The process instance migration service is a utility for migrating process instances from one deployment to another. Process or task variables are not affected by the migration. However, the new deployment can use a different process definition.
When migrating a process, the process instance migration service also automatically migrates all the subprocesses of the process, the subprocesses of those subprocesses, and so on. If you attempt to migrate a subprocess without migrating the parent process, the migration fails.
For the simplest approach to process migration, let active process instances finish and start new process instances in the new deployment. If this approach is not suitable for your needs, consider the following issues before starting process instance migration:
-
Backward compatibility
-
Data change
-
Need for node mapping
Whenever possible, create backward-compatible processes by extending process definitions. For example, removing nodes from the process definition breaks compatibility. If you make such changes, you must provide node mapping. Process instance migration uses node mapping if an active process instance is in a node that has been removed.
A node map contains source node IDs from the old process definition mapped to target node IDs in the new process definition. You can map nodes of the same type only, such as a user task to a user task.
jBPM offers several implementations of the migration service:
ProcessInstanceMigrationService
interface that implement the migration servicepublic interface ProcessInstanceMigrationService {
/**
* Migrates a given process instance that belongs to the source deployment into the target process ID that belongs to the target deployment.
* The following rules are enforced:
* <ul>
* <li>the source deployment ID must point to an existing deployment</li>
* <li>the process instance ID must point to an existing and active process instance</li>
* <li>the target deployment must exist</li>
* <li>the target process ID must exist in the target deployment</li>
* </ul>
* Returns a migration report regardless of migration being successful or not; examine the report for the outcome of the migration.
* @param sourceDeploymentId deployment to which the process instance to be migrated belongs
* @param processInstanceId ID of the process instance to be migrated
* @param targetDeploymentId ID of the deployment to which the target process belongs
* @param targetProcessId ID of the process to which the process instance should be migrated
* @return returns complete migration report
*/
MigrationReport migrate(String sourceDeploymentId, Long processInstanceId, String targetDeploymentId, String targetProcessId);
/**
* Migrates a given process instance (with node mapping) that belongs to source deployment into the target process ID that belongs to the target deployment.
* The following rules are enforced:
* <ul>
* <li>the source deployment ID must point to an existing deployment</li>
* <li>the process instance ID must point to an existing and active process instance</li>
* <li>the target deployment must exist</li>
* <li>the target process ID must exist in the target deployment</li>
* </ul>
* Returns a migration report regardless of migration being successful or not; examine the report for the outcome of the migration.
* @param sourceDeploymentId deployment to which the process instance to be migrated belongs
* @param processInstanceId ID of the process instance to be migrated
* @param targetDeploymentId ID of the deployment to which the target process belongs
* @param targetProcessId ID of the process to which the process instance should be migrated
* @param nodeMapping node mapping - source and target unique IDs of nodes to be mapped - from process instance active nodes to new process nodes
* @return returns complete migration report
*/
MigrationReport migrate(String sourceDeploymentId, Long processInstanceId, String targetDeploymentId, String targetProcessId, Map<String, String> nodeMapping);
/**
* Migrates given process instances that belong to the source deployment into a target process ID that belongs to the target deployment.
* The following rules are enforced:
* <ul>
* <li>the source deployment ID must point to an existing deployment</li>
* <li>the process instance ID must point to an existing and active process instance</li>
* <li>the target deployment must exist</li>
* <li>the target process ID must exist in the target deployment</li>
* </ul>
* Returns a migration report regardless of migration being successful or not; examine the report for the outcome of the migration.
* @param sourceDeploymentId deployment to which the process instances to be migrated belong
* @param processInstanceIds list of process instance IDs to be migrated
* @param targetDeploymentId ID of the deployment to which the target process belongs
* @param targetProcessId ID of the process to which the process instances should be migrated
* @return returns complete migration report
*/
List<MigrationReport> migrate(String sourceDeploymentId, List<Long> processInstanceIds, String targetDeploymentId, String targetProcessId);
/**
* Migrates given process instances (with node mapping) that belong to the source deployment into a target process ID that belongs to the target deployment.
* The following rules are enforced:
* <ul>
* <li>the source deployment ID must point to an existing deployment</li>
* <li>the process instance ID must point to an existing and active process instance</li>
* <li>the target deployment must exist</li>
* <li>the target process ID must exist in the target deployment</li>
* </ul>
* Returns a migration report regardless of migration being successful or not; examine the report for the outcome of the migration.
* @param sourceDeploymentId deployment to which the process instances to be migrated belong
* @param processInstanceIds list of process instance ID to be migrated
* @param targetDeploymentId ID of the deployment to which the target process belongs
* @param targetProcessId ID of the process to which the process instances should be migrated
* @param nodeMapping node mapping - source and target unique IDs of nodes to be mapped - from process instance active nodes to new process nodes
* @return returns list of migration reports one per each process instance
*/
List<MigrationReport> migrate(String sourceDeploymentId, List<Long> processInstanceIds, String targetDeploymentId, String targetProcessId, Map<String, String> nodeMapping);
}
To migrate process instances on a KIE Server, use the following implementations. These methods are similar to the methods in the ProcessInstanceMigrationService
interface, providing the same migration implementations for KIE Server deployments.
ProcessAdminServicesClient
interface that implement the migration service for KIE Server deploymentspublic interface ProcessAdminServicesClient {
MigrationReportInstance migrateProcessInstance(String containerId, Long processInstanceId, String targetContainerId, String targetProcessId);
MigrationReportInstance migrateProcessInstance(String containerId, Long processInstanceId, String targetContainerId, String targetProcessId, Map<String, String> nodeMapping);
List<MigrationReportInstance> migrateProcessInstances(String containerId, List<Long> processInstancesId, String targetContainerId, String targetProcessId);
List<MigrationReportInstance> migrateProcessInstances(String containerId, List<Long> processInstancesId, String targetContainerId, String targetProcessId, Map<String, String> nodeMapping);
}
You can migrate a single process instance or multiple process instances at once. If you migrate multiple process instances, each instance is migrated in a separate transaction to ensure that the migrations do not affect each other.
After migration is completed, the migrate
method returns a MigrationReport
object that contains the following information:
-
The start and end dates of the migration.
-
The migration outcome (success or failure).
-
A log entry of the
INFO
,WARN
, orERROR
type. TheERROR
message terminates the migration.
The following example shows a process instance migration:
import org.kie.server.api.model.admin.MigrationReportInstance;
import org.kie.server.api.marshalling.MarshallingFormat;
import org.kie.server.client.KieServicesClient;
import org.kie.server.client.KieServicesConfiguration;
public class ProcessInstanceMigrationTest{
private static final String SOURCE_CONTAINER = "com.redhat:MigrateMe:1.0";
private static final String SOURCE_PROCESS_ID = "MigrateMe.MigrateMev1";
private static final String TARGET_CONTAINER = "com.redhat:MigrateMe:2";
private static final String TARGET_PROCESS_ID = "MigrateMe.MigrateMeV2";
public static void main(String[] args) {
KieServicesConfiguration config = KieServicesFactory.newRestConfiguration("http://HOST:PORT/kie-server/services/rest/server", "USERNAME", "PASSWORD");
config.setMarshallingFormat(MarshallingFormat.JSON);
KieServicesClient client = KieServicesFactory.newKieServicesClient(config);
long sourcePid = client.getProcessClient().startProcess(SOURCE_CONTAINER, SOURCE_PROCESS_ID);
// Use the 'report' object to return migration results.
MigrationReportInstance report = client.getAdminClient().migrateProcessInstance(SOURCE_CONTAINER, sourcePid,TARGET_CONTAINER, TARGET_PROCESS_ID);
System.out.println("Was migration successful:" + report.isSuccessful());
client.getProcessClient().abortProcessInstance(TARGET_CONTAINER, sourcePid);
}
}
Known limitations of process instance migration
The following situations can cause a failure of the migration or incorrect migration:
-
A new or modified task requires inputs that are not available in the migrated process instance.
-
You modify the tasks prior to the active task where the changes have an impact on further processing.
-
You remove a human task that is currently active. To replace a human task, you must map it to another human task.
-
You add a new task parallel to the single active task. As all branches in an
AND
gateway are not activated, the process gets stuck. -
You remove active timer events (these events are not changed in the database).
-
You fix or update inputs and outputs in an active task (the task data is not migrated).
If you apply mapping to a task node, only the task node name and description are mapped. Other task fields, including the TaskName
variable, are not mapped to the new task.
9.4.11. Deployments and different process versions
The deployment service puts business assets into an execution environment. However, in some cases additional management is required to make the assets available in the correct context. Notably, if you deploy several versions of the same process, you must ensure that process instances use the correct version.
Activation and Deactivation of deployments
In some cases, a number of process instances are running on a deployment, and then you add a new version of the same process to the runtime environment.
You might decide that new instances of this process definition must use the new version while the existing active instances should continue with the previous version.
To enable this scenario, use the following methods of the deployment service:
-
activate
: Activates a deployment so it can be available for interaction. You can list its process definitions and start new process instances for this deployment. -
deactivate
: Deactivates a deployment. Disables the option to list process definitions and to start new process instances of processes in the deployment. However, you can continue working with the process instances that are already active, for example, signal events and interact with user tasks.
You can use this feature for smooth transition between project versions without the need for process instance migration.
Invocation of the latest version of a process
If you need to use the latest version of the project’s process, you can use the latest
keyword to interact with several operations in services. This approach is supported only when the process identifier remains the same in all versions.
The following example explains the feature.
The initial deployment unit is org.jbpm:HR:1.0
. It contains the first version of a hiring process.
After several weeks, you develop a new version and deploy it to the execution server as org.jbpm:HR.2.0
. It includes version 2 of the hiring process.
If you want to call the process and ensure that you use the latest version, you can use the following deployment ID:
org.jbpm.HR:latest
If you use this deployment ID, the jBPM engine finds the latest available version of the project. It uses the following identifiers:
-
groupId
:org.jbpm
-
artifactId
:HR
The version numbers are compared by Maven rules to find the latest version.
The following code example shows deployment of multiple versions and interacting with the latest version:
KModuleDeploymentUnit deploymentUnitV1 = new KModuleDeploymentUnit("org.jbpm", "HR", "1.0");
deploymentService.deploy(deploymentUnitV1);
long processInstanceId = processService.startProcess("org.jbpm:HR:LATEST", "customtask");
ProcessInstanceDesc piDesc = runtimeDataService.getProcessInstanceById(processInstanceId);
// We have started a process with the project version 1
assertEquals(deploymentUnitV1.getIdentifier(), piDesc.getDeploymentId());
// Next we deploy version 2
KModuleDeploymentUnit deploymentUnitV2 = new KModuleDeploymentUnit("org.jbpm", "HR", "2.0");
deploymentService.deploy(deploymentUnitV2);
processInstanceId = processService.startProcess("org.jbpm:HR:LATEST", "customtask");
piDesc = runtimeDataService.getProcessInstanceById(processInstanceId);
// This time we have started a process with the project version 2
assertEquals(deploymentUnitV2.getIdentifier(), piDesc.getDeploymentId());
This feature is also available in the KIE Server REST API. When sending a request with a deployment ID, you can use |
9.4.12. Deployment synchronization
Prior to jBPM 6.2, jBPM services did not have a deployment store by default.
When embedded in business-central/kie-wb, they utilized the sistem.git
VFS repository to preserve deployed units across server restarts.
While that approach works, it causes some drawbacks:
-
It is not available for custom systems that use services
-
It requires a complex setup process in a cluster deployment, involving
zookeeper
andhelix
Since version 6.2, jBPM services include a deployment synchronizer that stores available deployments into a database, including the deployment descriptor for every deployment.
The synchronizer also monitors this table to keep it in sync with other installations that might be using the same data source. This functionality is especially important when running in a cluster or when Business Central and a custom application must operate on the same artifacts.
By default, when running core services, you must configure synchronization. For EJB and CDI extensions, synchronization is enabled automatically.
The following code sample configures synchronization:
TransactionalCommandService commandService = new TransactionalCommandService(emf);
DeploymentStore store = new DeploymentStore();
store.setCommandService(commandService);
DeploymentSynchronizer sync = new DeploymentSynchronizer();
sync.setDeploymentService(deploymentService);
sync.setDeploymentStore(store);
DeploymentSyncInvoker invoker = new DeploymentSyncInvoker(sync, 2L, 3L, TimeUnit.SECONDS);
invoker.start();
....
invoker.stop();
With this configuration, deployments are synchronized every three seconds with an initial delay of two seconds.
9.5. Threads in the jBPM engine
We can refer to two types of multi-threading: logical and technical. Technical multi-threading involves multiple threads or processes that are started, for example, by a Java or C program. Logical multi-threading happens in a BPM process, for example, after the process reaches a parallel gateway. In execution logic, the original process splits into two processes that run in a parallel fashion.
jBPM engine code implements logical multi-threading using one technical thread.
The reason for this design choice is that multiple (technical) threads must be able to communicate state information to each other if they are working on the same process. This requirement brings a number of complications. The extra logic required for safe communication between threads, as well as the extra overhead required to avoid race conditions and deadlocks, can negate any performance benefit of using such threads.
In general, the jBPM engine executes actions in series. For example, when the jBPM engine encounters a script task in a process, it executes the script synchronously and waits for it to complete before continuing execution. In the same way, if a process encounters a parallel gateway, the jBPM engine sequentially triggers each of the outgoing branches, one after the other.
This is possible because execution is almost always instantaneous, meaning that it is extremely fast and produces almost no overhead. As a result, sequential execution does not create any effects that a user can notice.
Any code in a process that you supply is also executed synchronously and the jBPM engine waits for it to finish before continuing the process. For example, if you use a Thread.sleep(…)
as part of a custom script, the jBPM engine thread is blocked during the sleep period.
When a process reaches a service task, the jBPM engine also invokes the handler for the task synchronously and waits for the completeWorkItem(…)
method to return before continuing execution. If your service handler is not instantaneous, implement the asynchronous execution independently in your code.
For example, your service task might invoke an external service. The delay in invoking this service remotely and waiting for the results might be significant. Therefore, invoke this service asynchronously. Your handler must only invoke the service and then return from the method, then notify the jBPM engine later when the results are available. In the meantime, the jBPM engine can continue execution of the process.
Human tasks are a typical example of a service that needs to be invoked asynchronously. A human task requires a human actor to respond to a request, and the jBPM engine must not wait for this response.
When a human task node is triggered, the human task handler only creates a new task on the task list of the assigned actor. The jBPM engine is then able to continue execution on the rest of the process, if necessary. The handler notifies the jBPM engine asynchronously when the user has completed the task.
9.6. Execution errors in the jBPM engine
Any part of jBPM engine execution, including the task service, can throw an exception. An exception can be any class that extends java.lang.Throwable
.
Some exceptions are handled at the process level. Notably, a work item handler can throw a custom exception that specifies a subprocess for error handling.
If an exception is not handled and reaches the jBPM engine, it becomes an execution error. When an execution error happens, the jBPM engine rolls back the current transaction and leaves the process in the previous stable state. After that, the jBPM engine continues the execution of the process from that point.
Execution errors are visible to the caller that sent the request to the jBPM engine. The jBPM engine also includes an extendable mechanism for handling execution errors and storing information about them. This mechanism consists of the following components:
-
ExecutionErrorManager
: The entry point for error handling. This class is integrated withRuntimeManager
, which is responsible for providing it to the underlyingKieSession
andTaskService
.ExecutionErrorManager
provides access to other classes in the execution error handling mechanism.When the jBPM engine creates a
RuntimeManager
instance, it also creates a correspondingExecutionErrorManager
instance. -
ExecutionErrorHandler
: The primary class for error handling. This class is implemented in the jBPM engine and you normally do not need to customize or extend it directly.ExecutionErrorHandler
calls error filters to process particular errors and callsExecutionErrorStorage
to store error information.The
ExecutionErrorHandler
is bound to the life cycle ofRuntimeEngine
; it is created when a new runtime engine is created and is destroyed whenRuntimeEngine
is disposed. A single instance of theExecutionErrorHandler
is used within a given execution context or transaction. BothKieSession
andTaskService
use that instance to inform the error handling about processed nodes or tasks.ExecutionErrorHandler
is informed about the following events:-
Starting of processing of a node instance
-
Completion of processing of a node instance
-
Starting of processing of a task instance
-
Completion of processing of a task instance
The
ExecutionErrorHandler
uses this information to record the context for errors, especially if the error itself does not provide process context information. For example, database exceptions do not carry any process information.
-
-
ExecutionErrorStorage
: The pluggable storage class for execution error information.When the jBPM engine creates a
RuntimeManager
instance, it also creates a correspondingExecutionErrorStorage
instance. Then theExecutionErrorHandler
class calls thisExecutionErrorStorage
instance to store information abiout every execution error.The default storage implementation uses a database table to store all the available information for every error. Different detail levels might be available for different error types, as some errors might not permit extraction of detailed information.
-
A number of filters that process particular types of execution errors. You can add custom filters.
By default, every execution error is recorded as unacknowledged. You can use Business Central to view all recorded execution errors and to acknowledge them. You can also create jobs that automatically acknowledge all or some execution errors.
9.6.1. Execution error types and filters
Execution error handling attempts to catch and handle any kind of error. However, users might need to handle different errors in different ways. Also, different detailed information is available for different types of errors.
The error handling mechanism supports pluggable filters. Every filter processes a particular type of error. You can add filters that process specific errors in different ways, overriding default processing.
A filter is an implementation of the ExecutionErrorFilter
interface. This interface builds instances of ExecutionError
, which are later stored using the ExecutionErrorStorage
class.
The ExecutionErrorFilter
interface has the following methods:
-
accept
: Indicates if an error can be processed by the filter -
filter
: Processes an error and returns theExecutionError
instance -
getPriority
: Indicates the priority for this filter
The execution error handler processes each error separately. For each error, it starts calling the accept
method of all registered filters, starting with the filters that have a lower priority value. If the accept
method of a filter returns true
, the handler calls the filter
method of the filter and does not call any other filters.
Because of the priority system, only one filter processes any error. More specialized filters have lower priority values. An error that is not accepted by any specialized filters reaches generic filters that have higher priority values.
The ServiceLoader
mechanism provides ExecutionErrorFilter
instances. To register custom filters, add their fully qualified class names to the META-INF/services/org.kie.internal.runtime.error.ExecutionErrorFilter
file of your service project.
jBPM ships with the following execution error filters:
Class name | Type | Priority |
---|---|---|
org.jbpm.runtime.manager.impl.error.filters.ProcessExecutionErrorFilter |
Process |
100 |
org.jbpm.runtime.manager.impl.error.filters.TaskExecutionErrorFilter |
Task |
80 |
org.jbpm.runtime.manager.impl.error.filters.DBExecutionErrorFilter |
DB |
200 |
org.jbpm.executor.impl.error.JobExecutionErrorFilter |
Job |
100 |
Filters are given a higher execution order based on the lowest value of the priority. Therefore, the execution error handler invokes these filters in the following order:
-
Task
-
Process
-
Job
-
DB
9.6.2. Viewing process execution errors in Business Central
You can view process errors in two locations in Business Central:
-
Menu → Manage → Process Instances
-
Menu → Manage → Execution Errors
In the Manage Process Instances page, the Errors column displays the number of errors, if any, for the current process instance.
-
An error has occurred while running a process in Business Central.
-
In Business Central, go to Menu → Manage → Process Instances and hover over the number shown in the Errors column.
-
Click the number of errors shown in the Errors column to navigate to the Manage Execution Errors page.
The Manage Execution Errors page shows a list of errors for all process instances.
9.6.3. Managing execution errors
By definition, every process error that is detected and stored is unacknowledged and must be handled by someone or something (in case of automatic error recovery). You can view a filtered list of errors that were or were not acknowledged. Acknowledging an error saves the user information and time stamp for traceability.
-
In Business Central, select Menu → Manage → Execution Errors.
-
Select an error from the list to open the Details tab. The Details tab displays information about the error or errors.
-
Click the Acknowledge button to acknowledge the error. You can view acknowledged errors later by selecting Yes on the Acknowledged filter in the Manage Execution Errors page.
If the error is related to a task, a Go to Task button is displayed.
-
Optional: Click the Go to Task button, if applicable, to view the associated job information in the Manage Tasks page.
In the Manage Tasks page, you can restart, reschedule, or retry the corresponding task.
9.6.4. Error filtering
For execution errors in the Manage Execution Errors screen, you can use the Filters panel to display only the errors that fit chosen criteria.
-
The Manage Execution Errors screen is open.
Make changes in the Filters panel on the left side of the screen as necessary:
- Type
-
Filter execution errors by type. You can select multiple type filters. If you deselect all types, all errors are displayed, regardless of type.
The following execution error types are available:
-
DB
-
Task
-
Process
-
Job
-
- Process Instance Id
-
Filter by process instance ID.
Input:
Numeric
- Job Id
-
Filter by job ID. The job id is created automatically when the job is created.
Input:
Numeric
- Id
-
Filter by process instance ID.
Input:
Numeric
- Acknowledged
-
Filter errors that have been or have not been acknowledged.
- Error Date
-
Filtering by the date or time that the error occurred.
This filter has the following quick filter options:
-
Last Hour
-
Today
-
Last 24 Hours
-
Last 7 Days
-
Last 30 Days
-
Custom
Select the Custom option to open a calendar tool for selecting a date and time range.
Figure 38. Search by Date
-
9.6.5. Auto-acknowledging execution errors
By default, execution errors are unacknowledged when they occur. To avoid the need to acknowledge every execution error manually, you can configure jobs to auto-acknowledge some or all execution errors.
If you configure an auto-acknowledge job, the job runs every day by default. To auto-acknowledge execution errors only once, set the |
-
In Business Central, select Menu → Manage → Jobs.
-
In the top right of the screen, click New Job.
-
Enter any identifier for the job in the Business Key field.
-
In the Type field, enter the type of the auto-acknowledge job:
-
org.jbpm.executor.commands.error.JobAutoAckErrorCommand
: Acknowledge all execution errors of typeJob
where the job to which the error relates is now cancelled, completed, or rescheduled for another execution. -
org.jbpm.executor.commands.error.TaskAutoAckErrorCommand
: Acknowledge all execution errors of typeTask
where the task to which the error relates is in an exit state (completed, failed, exited, obsolete). -
org.jbpm.executor.commands.error.ProcessAutoAckErrorCommand
: Acknowledge all execution errors of any type where the process instance from which the error originates is already finished (completed or aborted), or the task from which the error originates is already finished.
-
-
Select a Due On time for the job to be completed:
-
To run the job immediately, select the
Run now
option. -
To run the job at a specific time, select
Run later
. A date and time field appears next to theRun later
option. Click the field to open the calendar and schedule a specific time and date for the job.Figure 39. Example of scheduling an auto-acknowledge job
-
-
By default, after the initial run the job runs once every day . To change this setting, complete the following steps:
-
Click the Advanced tab.
-
Click the Add Parameter button.
-
Enter the configuration parameter you want to apply to the job:
-
If you want the job to run only once, add the
SingleRun
parameter with the value oftrue
. -
If you want he job to run periodically, add the
NextRun
parameter with the value of a valid time expression, such as2h
,5d
,1m
, and so on.
-
-
Optional: To set a custom entity manager factory name, enter the
EmfName
parameter.Figure 40. Example of setting parameters for an auto-acknowledge job
-
-
Click Create to create the job and return to the Manage Jobs page.
9.6.6. Cleaning up the error list
The jBPM engine stores execution errors in the ExecutionErrorInfo
database table. If you want to clean up the table and remove errors permanently, you can schedule a job with the org.jbpm.executor.commands.ExecutionErrorCleanupCommand
command.
The command deletes execution errors that are associated with completed or aborted process instances.
-
In Business Central, select Menu → Manage → Jobs.
-
In the top right of the screen, click New Job.
-
Type any identifier for the job into the Business Key field.
-
In the Type field, enter
org.jbpm.executor.commands.ExecutionErrorCleanupCommand
. -
Select a Due On time for the job to be completed:
-
To run the job immediately, select the
Run now
option. -
To run the job at a specific time, select
Run later
. A date and time field appears next to theRun later
option. Click the field to open the calendar and schedule a specific time and date for the job.
-
-
Click the Advanced tab.
-
Add any of the following parameters as necessary:
-
DateFormat
: The format for dates in parameters. If not set,yyyy-MM-dd
is used, as in the pattern of theSimpleDateFormat
class. -
EmfName
: Name of the custom entity manager factory to be used for queries. -
SingleRun
: Schedules the job for a single execution. If set totrue
, the job runs once and is not scheduled for repeated execution. -
NextRun
: Schedules the job for repeated execution in a time period. The value must be a valid time expression, for example,1d
,5h
,10m
. -
OlderThan
: Deletes only errors that are older than a set date. The value must be a date. -
OlderThanPeriod
: Deletes only errors that are older than a given time period, compared to the current time. The value must be a valid time expression, for example,1d
,5h
,10m
. -
ForProcess
: Deletes only errors that are related to a process definition. The value must be the identifier of the process definiton. -
ForProcessInstance
: Deletes only errors that are related to a process instance. The value must be the identifier of the process instance. -
ForDeployment
: Deletes only errors that are related to a deployment identifier. The value must be the deployment identifier.
-
9.7. Event listeners in the jBPM engine
Every time that a process or task changes to a different point in its lifecycle, the jBPM engine generates an event. You can develop a class that receives and processes such events. This class is called an event listener.
The jBPM engine passes an event object to this class. The object provides access to related information. For example, if the event is related to a process node, the object provides access to the process instance and the node instance.
9.7.1. Interfaces for event listeners
You can use the following interfaces to develop event listeners for the jBPM engine.
9.7.1.1. Interfaces for process event listeners
You can develop a class that implements the ProcessEventListener
interface. This class can listen to process-related events, such as starting or completing a process or entering and leaving a node.
The following source code shows the different methods of the ProcessEventListener
interface:
ProcessEventListener
interfacepublic interface ProcessEventListener
extends
EventListener {
/**
* This listener method is invoked right before a process instance is being started.
* @param event
*/
void beforeProcessStarted(ProcessStartedEvent event);
/**
* This listener method is invoked right after a process instance has been started.
* @param event
*/
void afterProcessStarted(ProcessStartedEvent event);
/**
* This listener method is invoked right before a process instance is being completed (or aborted).
* @param event
*/
void beforeProcessCompleted(ProcessCompletedEvent event);
/**
* This listener method is invoked right after a process instance has been completed (or aborted).
* @param event
*/
void afterProcessCompleted(ProcessCompletedEvent event);
/**
* This listener method is invoked right before a node in a process instance is being triggered
* (which is when the node is being entered, for example when an incoming connection triggers it).
* @param event
*/
void beforeNodeTriggered(ProcessNodeTriggeredEvent event);
/**
* This listener method is invoked right after a node in a process instance has been triggered
* (which is when the node was entered, for example when an incoming connection triggered it).
* @param event
*/
void afterNodeTriggered(ProcessNodeTriggeredEvent event);
/**
* This listener method is invoked right before a node in a process instance is being left
* (which is when the node is completed, for example when it has performed the task it was
* designed for).
* @param event
*/
void beforeNodeLeft(ProcessNodeLeftEvent event);
/**
* This listener method is invoked right after a node in a process instance has been left
* (which is when the node was completed, for example when it performed the task it was
* designed for).
* @param event
*/
void afterNodeLeft(ProcessNodeLeftEvent event);
/**
* This listener method is invoked right before the value of a process variable is being changed.
* @param event
*/
void beforeVariableChanged(ProcessVariableChangedEvent event);
/**
* This listener method is invoked right after the value of a process variable has been changed.
* @param event
*/
void afterVariableChanged(ProcessVariableChangedEvent event);
/**
* This listener method is invoked right before a process/node instance's SLA has been violated.
* @param event
*/
default void beforeSLAViolated(SLAViolatedEvent event) {}
/**
* This listener method is invoked right after a process/node instance's SLA has been violated.
* @param event
*/
default void afterSLAViolated(SLAViolatedEvent event) {}
/**
* This listener method is invoked when a signal is sent
* @param event
*/
default void onSignal(SignalEvent event) {}
/**
* This listener method is invoked when a message is sent
* @param event
*/
default void onMessage(MessageEvent event) {}
}
You can implement any of these methods to process the corresponding event.
For the definition of the event classes that the jBPM engine passes to the methods, see the org.kie.api.event.process
package in the Java documentation.
You can use the methods of the event class to retrieve other classes that contain all information about the entities involved in the event.
The following example is a part of a node-related event, such as afterNodeLeft()
, and retrieves the process instance and node type.
WorkflowProcessInstance processInstance = event.getNodeInstance().getProcessInstance()
NodeType nodeType = event.getNodeInstance().getNode().getNodeType()
9.7.1.2. Interfaces for task lifecycle event listeners
You can develop a class that implements the TaskLifecycleEventListener
interface. This class can listen to events related to the lifecycle of tasks, such as assignment of an owner or completion of a task.
The following source code shows the different methods of the TaskLifecycleEventListener
interface:
TaskLifecycleEventListener
interfacepublic interface TaskLifeCycleEventListener extends EventListener {
public enum AssignmentType {
POT_OWNER,
EXCL_OWNER,
ADMIN;
}
public void beforeTaskActivatedEvent(TaskEvent event);
public void beforeTaskClaimedEvent(TaskEvent event);
public void beforeTaskSkippedEvent(TaskEvent event);
public void beforeTaskStartedEvent(TaskEvent event);
public void beforeTaskStoppedEvent(TaskEvent event);
public void beforeTaskCompletedEvent(TaskEvent event);
public void beforeTaskFailedEvent(TaskEvent event);
public void beforeTaskAddedEvent(TaskEvent event);
public void beforeTaskExitedEvent(TaskEvent event);
public void beforeTaskReleasedEvent(TaskEvent event);
public void beforeTaskResumedEvent(TaskEvent event);
public void beforeTaskSuspendedEvent(TaskEvent event);
public void beforeTaskForwardedEvent(TaskEvent event);
public void beforeTaskDelegatedEvent(TaskEvent event);
public void beforeTaskNominatedEvent(TaskEvent event);
public default void beforeTaskUpdatedEvent(TaskEvent event){};
public default void beforeTaskReassignedEvent(TaskEvent event){};
public default void beforeTaskNotificationEvent(TaskEvent event){};
public default void beforeTaskInputVariableChangedEvent(TaskEvent event, Map<String, Object> variables){};
public default void beforeTaskOutputVariableChangedEvent(TaskEvent event, Map<String, Object> variables){};
public default void beforeTaskAssignmentsAddedEvent(TaskEvent event, AssignmentType type, List<OrganizationalEntity> entities){};
public default void beforeTaskAssignmentsRemovedEvent(TaskEvent event, AssignmentType type, List<OrganizationalEntity> entities){};
public void afterTaskActivatedEvent(TaskEvent event);
public void afterTaskClaimedEvent(TaskEvent event);
public void afterTaskSkippedEvent(TaskEvent event);
public void afterTaskStartedEvent(TaskEvent event);
public void afterTaskStoppedEvent(TaskEvent event);
public void afterTaskCompletedEvent(TaskEvent event);
public void afterTaskFailedEvent(TaskEvent event);
public void afterTaskAddedEvent(TaskEvent event);
public void afterTaskExitedEvent(TaskEvent event);
public void afterTaskReleasedEvent(TaskEvent event);
public void afterTaskResumedEvent(TaskEvent event);
public void afterTaskSuspendedEvent(TaskEvent event);
public void afterTaskForwardedEvent(TaskEvent event);
public void afterTaskDelegatedEvent(TaskEvent event);
public void afterTaskNominatedEvent(TaskEvent event);
public default void afterTaskReassignedEvent(TaskEvent event){};
public default void afterTaskUpdatedEvent(TaskEvent event){};
public default void afterTaskNotificationEvent(TaskEvent event){};
public default void afterTaskInputVariableChangedEvent(TaskEvent event, Map<String, Object> variables){};
public default void afterTaskOutputVariableChangedEvent(TaskEvent event, Map<String, Object> variables){};
public default void afterTaskAssignmentsAddedEvent(TaskEvent event, AssignmentType type, List<OrganizationalEntity> entities){};
public default void afterTaskAssignmentsRemovedEvent(TaskEvent event, AssignmentType type, List<OrganizationalEntity> entities){};
}
You can implement any of these methods to process the corresponding event.
For the definition of the event class that the jBPM engine passes to the methods, see the org.kie.api.task
package in the Java documentation.
You can use the methods of the event class to retrieve the classes representing the task, task context, and task metadata.
9.7.2. Timing of calls to event listeners
A number of event listener calls are before
and after
events, for example, beforeNodeLeft()
and afterNodeLeft()
, beforeTaskActivatedEvent()
and afterTaskActivatedEvent()
.
The before
and after
event calls typically act like a stack. If event A directly causes event B, the following sequence of calls happens:
-
Before A
-
Before B
-
After B
-
After A
For example, if leaving node X triggers node Y, all event calls related to triggering node Y occur between the beforeNodeLeft
and afterNodeLeft
calls for node X.
In the same way, if starting a process directly causes some nodes to start, all nodeTriggered
and nodeLeft
event calls occur between the beforeProcessStarted
and afterProcessStarted
calls.
This approach reflects cause and effect relationships between events. However, the timing and order of after
event calls are not always intuitive. For example, an afterProcessStarted
call can happen after the afterNodeLeft
calls for some nodes in the process.
In general, to be notified when a particular event occurs, use the before
call for the event. Use an after
call only if you want to make sure that all processing related to this event has ended, for example, when you want to be notified when all steps associated with starting a particular process instance have been completed.
Depending on the type of node, some nodes might only generate nodeLeft
calls and others might only generate nodeTriggered
calls. For example, catch intermediate event nodes do not generate nodeTriggered
calls because they are not triggered by another process node. Similarly, throw intermediate event nodes do not generate nodeLeft
calls because these nodes do not have an outgoing connection to another node.
9.7.3. Practices for development of event listeners
The jBPM engine calls event listeners during processing of events or tasks. The calls happen within jBPM engine transactions and block execution. Therefore, the event listener can affect the logic and performance of the jBPM engine.
To ensure minimal disruption, follow the following guidelines:
-
Any action must be as short as possible.
-
A listener class must not have a state. The jBPM engine can destroy and re-create a listener class at any time.
-
If the listener modifies any resource that exists outside the scope of the listener method, ensure that the resource is enlisted in the current transaction. The transaction might be rolled back. In this case, if the modified resource is not a part of the transaction, the state of the resource becomes inconsistent.
Database-related resources provided by Red Hat JBoss EAP are always enlisted in the current transaction. In other cases, check the JTA information for the runtime environment that you are using.
-
Do not use logic that relies on the order of execution of different event listeners.
-
Do not include interactions with different entities outside the jBPM engine within a listener. For example, do not include REST calls for notification of events. Instead, use process nodes to complete such calls. An exception is the output of logging information; however, a logging listener must be as simple as possible.
-
You can use a listener to modify the state of the process or task that is involved in the event, for example, to change its variables.
-
You can use a listener to interact with the jBPM engine, for example, to send signals or to interact with process instances that are not involved in the event.
9.7.4. Registration of event listeners
The KieSession
class implements the RuleRuntimeEventManager
interface that provides methods for registering, removing, and listing event listeners, as shown in the following list.
RuleRuntimeEventManager
interface void addEventListener(AgendaEventListener listener);
void addEventListener(RuleRuntimeEventListener listener);
void removeEventListener(AgendaEventListener listener);
void removeEventListener(RuleRuntimeEventListener listener);
Collection<AgendaEventListener> getAgendaEventListeners();
Collection<RuleRuntimeEventListener> getRuleRintimeEventListeners();
However, in a typical case, do not use these methods.
If you are using the RuntimeManager
interface, you can use the RuntimeEnvironment
class to register event listeners.
If you are using the Services API, you can add fully qualified class names of event listeners to the META-INF/services/org.jbpm.services.task.deadlines.NotificationListener
file in your project. The Services API also registers some default listeners, including org.jbpm.services.task.deadlines.notifications.impl.email.EmailNotificationListener
, which can send email notifications for events.
To exclude a default listener, you can add the fully qualified name of the listener to the org.kie.jbpm.notification_listeners.exclude
JVM system property.
9.7.5. KieRuntimeLogger
event listener
The KieServices
package contains the KieRuntimeLogger
event listener that you can add to your KIE session. You can use this listener to create an audit log. This log contains all the different events that occurred at runtime.
These loggers are intended for debugging purposes. They might be too detailed for business-level process analysis. |
The listener implements the following logger types:
-
Console logger: This logger writes out all the events to the console. The fully qualified class name for this logger is
org.drools.core.audit.WorkingMemoryConsoleLogger
. -
File logger: This logger writes out all the events to a file using an XML representation. You can use the log file in an IDE to generate a tree-based visualization of the events that occurred during execution. The fully qualified class name for this logger is
org.drools.core.audit.WorkingMemoryFileLogger
.The file logger writes the events to disk only when closing the logger or when the number of events in the logger reaches a predefined level. Therefore, it is not suitable for debugging processes at runtime.
-
Threaded file logger: This logger writes the events to a file after a specified time interval. You can use this logger to visualize the progress in real time while debugging processes. The fully qualified class name for this logger is
org.drools.core.audit.ThreadedWorkingMemoryFileLogger
.
When creating a logger, you must pass the KIE session as an argument. The file loggers also require the name of the log file to be created. The threaded file logger requires the interval in milliseconds after which the events are saved.
Always close the logger at the end of your application.
The following example shows the use of the file logger.
import org.kie.api.KieServices;
import org.kie.api.logger.KieRuntimeLogger;
...
KieRuntimeLogger logger = KieServices.Factory.get().getLoggers().newFileLogger(ksession, "test");
// add invocations to the jBPM engine here,
// e.g. ksession.startProcess(processId);
...
logger.close();
The log file that is created by the file-based loggers contains an XML-based overview of all the events that occurred during the runtime of the process.
9.8. jBPM engine configuration
You can use several control parameters available to alter the jBPM engine default behavior to suit the requirements of your environment.
Set these parameters as JVM system properties, usually with the -D
option when starting a program such as an application server.
Name | Possible values | Default value | Description |
---|---|---|---|
|
String |
Alternative JNDI name to be used when there is no access to the default name ( NOTE: The name must be valid for the given runtime environment. Do not use this variable if there is no access to the default user transaction JNDI name. |
|
|
|
|
Enable multiple incoming and outgoing sequence flows support for activities |
|
String |
/ |
Alternative class path location of the business calendar configuration file |
|
Long |
2000 |
Specifies the delay for overdue timers to allow proper initialization, in milliseconds |
|
String |
Alternative comparator class to enable starting a process by name,
by default the |
|
|
|
|
Enable or disable loop iteration tracking for advanced loop support when using XOR gateways |
|
String |
|
Alternative JNDI name for the mail session used by Task Deadlines |
|
String |
/ |
Alternative class path location for a user group callback implementation (LDAP, DB) |
|
String |
|
Alternative location of the |
|
String |
/ |
Alternative class path location of the user info configuration (used by |
|
String |
|
Alternative separator of actors and groups for user tasks |
|
String |
Location of the Quartz configuration file to activate the Quartz-based timer service |
|
|
String |
|
Location to store data files produced by the jBPM engine |
|
Integer |
|
Thread pool size for the jBPM engine executor |
|
Integer |
3 |
Number of retries attempted by the jBPM engine executor in case of an error |
|
Integer |
0 |
Frequency used to check for pending jobs by the jBPM engine executor, in seconds. If the value is |
|
|
|
Disable the jBPM engine executor |
|
String |
|
Fully qualified name of the class that implements |
|
String |
Fully qualified names of event listeners that must be excluded even if they would otherwise be used. Separate multiple names with commas. For example, you can add |
|
|
String |
Fully qualified names of event listeners that must be included. Separate multiple names with commas. If you set this property, only the listeners in this property are included and all other listeners are excluded. |
10. Processes
10.1. What is BPMN 2.0
"The primary goal of BPMN is to provide a notation that is readily understandable by all business users, from the business analysts that create the initial drafts of the processes, to the technical developers responsible for implementing the technology that will perform those processes, and finally, to the business people who will manage and monitor those processes." |
The Business Process Model and Notation (BPMN) 2.0 specification is an OMG specification that not only defines a standard on how to graphically represent a business process (like BPMN 1.x), but now also includes execution semantics for the elements defined, and an XML format on how to store (and share) process definitions.
jBPM6 allows you to execute processes defined using the BPMN 2.0 XML format. That means that you can use all the different jBPM6 tooling to model, execute, manage and monitor your business processes using the BPMN 2.0 format for specifying your executable business processes. Actually, the full BPMN 2.0 specification also includes details on how to represent things like choreographies and collaboration. The jBPM project however focuses on that part of the specification that can be used to specify executable processes.
Executable processes in BPMN consist of different types of nodes being connected to each other using sequence flows. The BPMN 2.0 specification defines three main types of nodes:
-
Events: They are used to model the occurrence of a particular event. This could be a start event (that is used to indicate the start of the process), end events (that define the end of the process, or of that subflow) and intermediate events (that indicate events that might occur during the execution of the process).
-
Activities: These define the different actions that need to be performed during the execution of the process. Different types of tasks exist, depending on the type of activity you are trying to model (e.g. human task, service task, etc.) and activities could also be nested (using different types of sub-processes).
-
Gateways: Can be used to define multiple paths in the process. Depending on the type of gateway, these might indicate parallel execution, choice, etc.
jBPM6 does not implement all elements and attributes as defined in the BPMN 2.0 specification. We do however support a significant subset, including the most common node types that can be used inside executable processes. This includes (almost) all elements and attributes as defined in the "Common Executable" subclass of the BPMN 2.0 specification, extended with some additional elements and attributes we believe are valuable in that context as well. The full set of elements and attributes that are supported can be found below, but it includes elements like:
-
Flow objects
-
Events
-
Start Event (None, Conditional, Signal, Message, Timer)
-
End Event (None, Terminate, Error, Escalation, Signal, Message, Compensation)
-
Intermediate Catch Event (Signal, Timer, Conditional, Message)
-
Intermediate Throw Event (None, Signal, Escalation, Message, Compensation)
-
Non-interrupting Boundary Event (Escalation, Signal, Timer, Conditional, Message)
-
Interrupting Boundary Event (Escalation, Error, Signal, Timer, Conditional, Message, Compensation)
-
-
Activities
-
Script Task
-
Task
-
Service Task
-
User Task
-
Business Rule Task
-
Manual Task
-
Send Task
-
Receive Task
-
Reusable Sub-Process (Call Activity)
-
Embedded Sub-Process
-
Event Sub-Process
-
Ad-Hoc Sub-Process
-
Data-Object
-
-
Gateways
-
Diverging
-
Exclusive
-
Inclusive
-
Parallel
-
Event-Based
-
-
Converging
-
Exclusive
-
Inclusive
-
Parallel
-
-
-
Lanes
-
-
Data
-
Java type language
-
Process properties
-
Embedded Sub-Process properties
-
Activity properties
-
-
Connecting objects
-
Sequence flow
-
For example, consider the following "Hello World" BPMN 2.0 process, which does nothing more than writing out a "Hello World" statement when the process is started.
An executable version of this process expressed using BPMN 2.0 XML would look something like this:
<?xml version="1.0" encoding="UTF-8"?>
<definitions id="Definition"
targetNamespace="http://www.example.org/MinimalExample"
typeLanguage="http://www.java.com/javaTypes"
expressionLanguage="http://www.mvel.org/2.0"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
xmlns:tns="http://www.jboss.org/drools">
<process processType="Private" isExecutable="true" id="com.sample.HelloWorld" name="Hello World" >
<!-- nodes -->
<startEvent id="_1" name="StartProcess" />
<scriptTask id="_2" name="Hello" >
<script>System.out.println("Hello World");</script>
</scriptTask>
<endEvent id="_3" name="EndProcess" >
<terminateEventDefinition/>
</endEvent>
<!-- connections -->
<sequenceFlow id="_1-_2" sourceRef="_1" targetRef="_2" />
<sequenceFlow id="_2-_3" sourceRef="_2" targetRef="_3" />
</process>
<bpmndi:BPMNDiagram>
<bpmndi:BPMNPlane bpmnElement="Minimal" >
<bpmndi:BPMNShape bpmnElement="_1" >
<dc:Bounds x="15" y="91" width="48" height="48" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_2" >
<dc:Bounds x="95" y="88" width="83" height="48" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_3" >
<dc:Bounds x="258" y="86" width="48" height="48" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="_1-_2" >
<di:waypoint x="39" y="115" />
<di:waypoint x="75" y="46" />
<di:waypoint x="136" y="112" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_2-_3" >
<di:waypoint x="136" y="112" />
<di:waypoint x="240" y="240" />
<di:waypoint x="282" y="110" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
To create your own process using BPMN 2.0 format, you can
-
The jBPM Designer is an open-source web-based editor that supports the BPMN 2.0 format. We have embedded it into Business Central for BPMN 2.0 process visualization and editing. You could use the Designer (either standalone or integrated) to create / edit BPMN 2.0 processes and then export them to BPMN 2.0 format or save them into repository and import them so they can be executed.
-
A new BPMN2 Eclipse plugin is being created to support the full BPMN2 specification.
-
You can always manually create your BPMN 2.0 process files by writing the XML directly. You can validate the syntax of your processes against the BPMN 2.0 XSD, or use the validator in the Eclipse plugin to check both syntax and completeness of your model.
-
Drools Eclipse Process editor has been deprecated in favor of BPMN2 Modeler for process modeling. It can still be used for limited number of supported elements but should be faced out as it is not being developed any more.
Create a new Process file using the Drools Eclipse plugin wizard and in the last page of the wizard, make sure you select Drools 5.1 code compatibility. This will create a new process using the BPMN 2.0 XML format. Note however that this is not exactly a BPMN 2.0 editor, as it still uses different attributes names etc. It does however save the process using valid BPMN 2.0 syntax. Also note that the editor does not support all node types and attributes that are already supported in the jBPM engine.
The following code fragment shows you how to load a BPMN2 process into your KIE base …
private static KnowledgeBase createKnowledgeBase() throws Exception {
KieHelper kieHelper = new KieHelper();
KieBase kieBase = kieHelper
.addResource(ResourceFactory.newClassPathResource("sample.bpmn2"))
.build();
return kieBase;
}
... and how to execute this process …
KieBase kbase = createKnowledgeBase();
KieSession ksession = kbase.newKieSession();
ksession.startProcess("com.sample.HelloWorld");
For more detail, check out the chapter on the API and the basics.
10.2. Business processes
A business process is a diagram that describes the order for a series of steps that must be executed and consists of predefined nodes and connections. Each node represents one step in the process while the connections specify how to transition from one node to another.
A typical business process consists of the following components:
-
The header section that comprises global elements such as the name of the process, imports, and variables
-
The nodes section that contains all the different nodes that are part of the process
-
The connections section that links these nodes to each other to create a flow chart
jBPM contains the legacy process designer and the new process designer for creating business process diagrams. The new process designer has an improved layout and feature set and continues to be developed. Until all features of the legacy process designer are completely implemented in the new process designer, both designers are available in Business Central for you to use.
10.2.1. Creating a business process in Business Central
The process designer is the jBPM process modeler. The output of the modeler is a BPMN 2.0 process definition file. The definition is used as input for the jBPM jBPM engine, which creates a process instance based on the definition.
The procedures in this section provide a general overview of how to create a simple business process.
-
You have created or imported a jBPM project.
-
You have created the required users. User privileges and settings are controlled by the roles assigned to a user and the groups that a user belongs to.
-
In Business Central, go to Menu → Design → Projects.
-
Click the project name to open the project’s asset list.
-
Click Add Asset → Business Process.
-
In the Create new Business Process wizard, enter the following values:
-
Business Process: New business process name
-
Package: Package location for your new business process, for example
com.myspace.myProject
-
-
Click Ok to open the process designer.
-
In the upper-right corner, click the Properties icon and add your business process property information, such as process data and variables:
-
Scroll down and expand Process Data.
-
Click next to Process Variables and define the process variables that you want to use in your business process.
Table 8. General process properties Label Description Name
Enter the name of the process.
Documentation
Describes the process. The text in this field is included in the process documentation, if applicable.
ID
Enter an identifier for this process, such as
orderItems
.Package
Enter the package location for this process in your jBPM project, such as
org.acme
.ProcessType
Specify whether the process is public or private (or null, if not applicable).
Version
Enter the artifact version for the process.
Ad hoc
Select this option if this process is an ad hoc sub-process.
Process Instance Description
Enter a description of the purpose of the process.
Imports
Click to open the Imports window and add any data object classes required for your process.
Executable
Select this option to make the process executable part of your jBPM project.
SLA Due Date
Enter the service level agreement (SLA) expiration date.
Process Variables
Add any process variables for the process. Process variables are visible within the specific process instance. Process variables are initialized at process creation and destroyed on process completion. Variable Tags provide greater control over variable behavior, for example whether the variable is
required
orreadonly
. For more information about variable tags, see Variables.Metadata Attributes
Add any custom metadata attribute name and value that you want to use for custom event listeners, such as a listener to implement some action when a metadata attribute is present.
Global Variables
Add any global variables for the process. Global variables are visible to all process instances and assets in a project. Global variables are typically used by business rules and constraints, and are created dynamically by the rules or constraints.
The Metadata Attributes entries are similar to Process Variables tags in that they enable new
metaData
extensions to BPMN diagrams. However, process variable tags modify the behavior of specific process variables, such as whether a certain variable isrequired
orreadonly
, whereas metadata attributes are key-value definitions that modify the behavior of the overall process.For example, the following custom metadata attribute
riskLevel
and valuelow
in a BPMN process correspond to a custom event listener for starting the process:Figure 42. Example metadata attribute and value in the BPMN modelerExample metadata attribute and value in the BPMN file<bpmn2:process id="approvals" name="approvals" isExecutable="true" processType="Public"> <bpmn2:extensionElements> <tns:metaData name="riskLevel"> <tns:metaValue><![CDATA[low]]></tns:metaValue> </tns:metaData> </bpmn2:extensionElements>
Example event listener with metadata valuepublic class MyListener implements ProcessEventListener { ... @Override public void beforeProcessStarted(ProcessStartedEvent event) { Map < String, Object > metadata = event.getProcessInstance().getProcess().getMetaData(); if (metadata.containsKey("low")) { // Implement some action for that metadata attribute } } }
-
-
In the process designer canvas, use the left toolbar to drag and drop BPMN components to define your business process logic, connections, events, tasks, or other elements.
A task and event in jBPM expect one incoming and one outgoing flow. If you want to design a business process with multiple incoming and multiple outgoing flows, then consider redesigning the business process using gateways. Using gateways makes the logic apparent, which a sequence flow is executing. Therefore, gateways are considered as a best practice for multiple connections.
However, if it is a must to use multiple connections for a task or an event, then you must set the JVM (Java virtual machine) system property
jbpm.enable.multi.con
totrue
. When Business Central and KIE Server run on different servers, then ensure that both of them contains thejbpm.enable.multi.con
system property as enabled otherwise, the jBPM engine throws an exception. -
After you add and define all components of the business process, click Save to save the completed business process.
10.2.1.1. Creating business rules tasks
Business rules tasks are used to make decisions through a Decision Model and Notation (DMN) model or rule flow group.
-
Create a business process.
-
In the process designer, select the Activities tool from the tool palette.
-
Select Business Rule.
-
Click a blank area of the process designer canvas.
-
If necessary, in the upper-right corner of the screen, click the Properties icon.
-
Add or define the task information listed in the following table as required.
Table 9. Business rule task parameters Label Description Name
The name of the business rule task. You can also double-click the business rule task shape to edit the name.
Rule Language
The output language for the task. Select Decision Model and Notation (DMN) or Drools (DRL).
Rule Flow Group
The rule flow group associated with this business task. Select a rule flow group from the list or specify a new rule flow group.
On Entry Action
A Java, JavaScript, or MVEL script that specifies an action at the start of the task.
On Exit Action
A Java, JavaScript, or MVEL script that specifies an action at the end of the task.
Is Async
Select if this task should be invoked asynchronously. Make tasks asynchronous if they cannot be executed instantaneously, for example a task performed by an outside service.
AdHoc Autostart
Select if this is an ad hoc task that should be started automatically. AdHoc Autostart enables the task to automatically start when the process or case instance is created instead of being starting by a start task. It is often used in case management.
SLA Due Date
The date that the service level agreement (SLA) expires.
Assignments
Click to add local variables.
Metadata Attributes
Add any custom metadata attribute name and value that you want to use for custom event listeners, such as a listener to implement some action when a metadata attribute is present.
The Metadata Attributes enable the new
metaData
extensions to BPMN diagrams and modify the behavior of the overall task. -
Click Save.
10.2.1.2. Creating script tasks
Script tasks are used to execute a piece of code written in Java, JavaScript, or MVEL. They contain code snippets that specify the action of the script task. You can include global and process variables in your scripts.
Note that MVEL accepts any valid Java code and additionally provides support for nested access of parameters. For example, the MVEL equivalent of the Java call person.getName()
is person.name
. MVEL also provides other improvements over Java and MVEL expressions are generally more convenient for business users.
-
Create a business process.
-
In the process designer, select the Activities tool from the tool palette.
-
Select Script.
-
Click a blank area of the process designer canvas.
-
If necessary, in the upper-right corner of the screen, click the Properties icon.
-
Add or define the task information listed in the following table as required.
Table 10. Script task parameters Label Description Name
The name of the script task. You can also double-click the script task shape to edit the name.
Documentation
Enter a description of the task. The text in this field is included in the process documentation. Click the Documentation tab in the upper-left side of the process designer canvas to view the process documentation.
Script
Enter a script in Java, JavaScript, or MVEL to be executed by the task, and select the script type.
Is Async
Select if this task should be invoked asynchronously. Make tasks asynchronous if they cannot be executed instantaneously, for example a task performed by an outside service.
AdHoc Autostart
Select if this is an ad hoc task that should be started automatically. AdHoc Autostart enables the task to automatically start when the process or case instance is created instead of being starting by a start task. It is often used in case management.
Metadata Attributes
Add any custom metadata attribute name and value that you want to use for custom event listeners, such as a listener to implement some action when a metadata attribute is present.
The Metadata Attributes enable the new
metaData
extensions to BPMN diagrams and modify the behavior of the overall task. -
Click Save.
10.2.1.3. Creating service tasks
A service task is a task that executes an action based on a web service call or in a Java class method. Examples of service tasks include sending emails and logging messages when performing these tasks. You can define the parameters (input) and results (output) associated with a service task. You can also define wrapped parameters that contain all inputs into a single object. To define wrapped parameters, create a new work item handler using Wrapped` : `True
in the data assignment. A Service Task should have one incoming connection and one outgoing connection.
-
In Business Central, select the Admin icon in the top-right corner of the screen and select Artifacts.
-
Click Upload to open the Artifact upload window.
-
Choose the
.jar
file and click .The
.jar
file contains data types (data objects) and Java classes for web service and Java service tasks respectively. -
Create a project you want to use.
-
Go to your project Settings → Dependencies.
-
Click Add from repository, locate the uploaded
.jar
file, and click Select. -
Open your project Settings → Work Item Handler.
-
Enter the following values in the given fields:
-
Name -
Service Task
-
Value -
new org.jbpm.process.workitem.bpmn2.ServiceTaskHandler(ksession, classLoader)
-
-
Save the project.
Example of creating web service taskThe default implementation of a service task in the BPMN2 specification is a web service. The web service support is based on the Apache CXF dynamic client, which provides a dedicated service task handler that implements the
WorkItemHandler
interface:org.jbpm.process.workitem.bpmn2.ServiceTaskHandler
To create a service task using web service, you must configure the web service:
-
Create a business process.
-
If necessary, in the upper-right corner of the screen, click the Properties icon.
-
Click in the Imports property to open the Imports window.
-
Click +Add next to the WSDL Imports to import the required WSDL (Web Services Description Language) values. For example:
-
Location: http://localhost:8080/sample-ws-1/SimpleService?wsdl
The location points to the WSDL file of your service.
-
Namespace: http://bpmn2.workitem.process.jbpm.org/
The namespace must match
targetNamespace
from your WSDL file.
-
-
In the process designer, select the Activities tool from the tool palette.
-
Select Service Task.
-
Click a blank area of the process designer canvas.
-
Add or define the task information listed in the following table as required.
Table 11. Web service task parameters Label Description Name
The name of the service task. You can also double-click the service task shape to edit the name.
Documentation
Enter a description of the task. The text in this field is included in the process documentation. Click the Documentation tab in the upper-left side of the process designer canvas to view the process documentation.
Implementation
Specify a web service.
Interface
The service used to implement the script, such as
CountriesPortService
.Operation
The operation that is called by the interface, such as
getCountry
.Assignments
Click to add local variables.
AdHoc Autostart
Select if this is an ad hoc task that should be started automatically. AdHoc Autostart enables the task to automatically start when the process or case instance is created instead of being starting by a start task. It is often used in case management.
Is Async
Select if this task should be invoked asynchronously. Make tasks asynchronous if they cannot be executed instantaneously, for example a task performed by an outside service.
Is Multiple Instance
Select if this task has multiple instances.
MI Execution mode
Select if the multiple instances execute in parallel or sequentially.
MI Collection input
Specify a variable that represents a collection of elements for which new instances are created, such as
inputCountryNames
.MI Data Input
Specify the input data assignment that is transferred to a web service, such as
Parameter
.MI Collection output
The array list in which values returned from the web service task is stored, such as
outputCountries
.MI Data Output
Specify the output data assignment for the web service task, which stores the result of class execution on the server, such as
Result
.MI Completion Condition (mvel)
Specify the MVEL expression that is evaluated on each completed instance to check if the specified multiple instance node can complete.
On Entry Action
A Java, JavaScript, or MVEL script that specifies an action at the start of the task.
On Exit Action
A Java, JavaScript, or MVEL script that specifies an action at the end of the task.
SLA Due Date
The date that the service level agreement (SLA) expires.
Metadata Attributes
Add any custom metadata attribute name and value that you want to use for custom event listeners, such as a listener to implement some action when a metadata attribute is present.
The Metadata Attributes enable the new
metaData
extensions to BPMN diagrams and modify the behavior of the overall task.
Example of creating Java service taskWhen you create a service task using Java method, then the method can only contain one parameter and returns a single value. To create a service task using a Java method, you must add the Java class to the dependencies of the project:
-
Create a business process.
-
In the process designer, select the Activities tool from the tool palette.
-
Select Service Task.
-
Click a blank area of the process designer canvas.
-
If necessary, in the upper-right corner of the screen, click the Properties icon.
-
Add or define the task information listed in the following table as required.
Table 12. Java service task parameters Label Description Name
The name of the service task. You can also double-click the service task shape to edit the name.
Documentation
Enter a description of the task. The text in this field is included in the process documentation. Click the Documentation tab in the upper-left side of the process designer canvas to view the process documentation.
Implementation
Specify the task is implemented in Java.
Interface
The class used to implement the script, such as
org.xyz.HelloWorld
.Operation
The method that is called by the interface, such as
sayHello
.Assignments
Click to add local variables.
AdHoc Autostart
Select if this is an ad hoc task that should be started automatically. AdHoc Autostart enables the task to automatically start when the process or case instance is created instead of being starting by a start task. It is often used in case management.
Is Async
Select if this task should be invoked asynchronously. Make tasks asynchronous if they cannot be executed instantaneously, for example a task performed by an outside service.
Is Multiple Instance
Select if this task has multiple instances.
MI Execution mode
Select if the multiple instances execute in parallel or sequentially.
MI Collection input
Specify a variable that represents a collection of elements for which new instances are created, such as
InputCollection
.MI Data Input
Specify the input data assignment that is transferred to a Java class. For example, you can set the input data assignments as
Parameter
andParameterType
.ParameterType
represents the type ofParameter
and sends arguments to the execution of Java method.MI Collection output
The array list in which values returned from the Java class is stored, such as
OutputCollection
.MI Data Output
Specify the output data assignment for Java service task, which stores the result of class execution on the server, such as
Result
.MI Completion Condition (mvel)
Specify the MVEL expression that is evaluated on each completed instance to check if the specified multiple instance node can complete. For example,
OutputCollection.size() <= 3
indicates more than three people are not addressed.On Entry Action
A Java, JavaScript, or MVEL script that specifies an action at the start of the task.
On Exit Action
A Java, JavaScript, or MVEL script that specifies an action at the end of the task.
SLA Due Date
The date that the service level agreement (SLA) expires.
Metadata Attributes
Add any custom metadata attribute name and value that you want to use for custom event listeners, such as a listener to implement some action when a metadata attribute is present.
The Metadata Attributes enable the new
metaData
extensions to BPMN diagrams and modify the behavior of the overall task.
-
-
Click Save.
10.2.1.4. Creating user tasks
User tasks are used to include human actions as input to the business process.
-
Create a business process.
-
In the process designer, select the Activities tool from the tool palette.
-
Select User.
-
Drag and drop a user task onto the process designer canvas.
-
If necessary, in the upper-right corner of the screen, click the Properties icon.
-
Add or define the task information listed in the following table as required.
Table 13. User task parameters Label Description Name
The name of the user task. You can also double-click the user task shape to edit the name.
Documentation
Enter a description of the task. The text in this field is included in the process documentation. Click the Documentation tab in the upper-left side of the process designer canvas to view the process documentation.
Task Name
The name of the human task.
Subject
Enter a subject for the task.
Actors
The actors responsible for executing the human task. Click Add to add a row then select an actor from the list or click New to add a new actor.
Groups
The groups responsible for executing the human task. Click Add to add a row then select a group from the list or click New to add a new group.
Assignments
Local variables for this task. Click to open the Task Data I/O window then add data inputs and outputs as required. You can also add MVEL expressions as data input and output assignments. For more information about MVEL language, see Language Guide for 2.0.
Reassignments
Specify a different actor to complete this task.
Notifications
Click to specify notifications associated with the task.
Is Async
Select if this task should be invoked asynchronously. Make tasks asynchronous if they cannot be executed instantaneously, for example a task performed by an outside service.
Skippable
Select if this task is not mandatory.
Priority
Specify a priority for the task.
Description
Enter a description for the human task.
Created By
The user that created this task.
AdHoc Autostart
Select if this is an ad hoc task that should be started automatically. AdHoc Autostart enables the task to automatically start when the process or case instance is created instead of being starting by a start task. It is often used in case management.
Multiple Instance
Select if this task has multiple instances.
On Entry Action
A Java, JavaScript, or MVEL script that specifies an action at the start of the task.
On Exit Action
A Java, JavaScript, or MVEL script that specifies an action at the end of the task.
Content
The content of the script.
SLA Due Date
The date that the service level agreement (SLA) expires.
Metadata Attributes
Add any custom metadata attribute name and value that you want to use for custom event listeners, such as a listener to implement some action when a metadata attribute is present.
The Metadata Attributes enable the new
metaData
extensions to BPMN diagrams and modify the behavior of the overall task. -
Click Save.
10.2.1.5. Copying elements from one business process to another business process
You can copy individual elements from one business process to another business process in Business Central.
-
In the business process designer canvas, click and drag the cursor to select the elements that you want to copy.
-
Click in the upper-right toolbar to copy your selection.
-
Switch into the second business process where you want to add the copied elements.
-
In the second business process, create any process variables that are used in the business process that you want to copy. The variable
Name
andType
parameters must be identical in order to preserve variable mapping. -
Click to paste your selection.
-
Click Save to save the updated business process.
10.2.1.6. Making a copy of a business process
You can make a copy of a business process in Business Central and modify the copied process as needed.
-
In the business process designer, click Copy in the upper-right toolbar.
-
In the Make a Copy window, enter a new name for the copied business process, select the target package, and optionally add a comment.
-
Click Make a Copy.
-
Modify the copied business process as needed and click Save to save the updated business process.
10.2.1.7. Resizing elements and using the zoom function to view business processes
You can resize individual elements in a business process and zoom in or out to modify the view of your business process.
-
In the business process designer, select the element and click the red dot in the lower-right corner of the element.
-
Drag the red dot to resize the element.
Figure 43. Resize an element -
To zoom in or out to view the entire diagram, click the plus or minus sign on the lower-right side of the canvas.
Figure 44. Enlarge or shrink a business process
10.2.2. Deploying a business process in Business Central
After you design your business process in Business Central, you can build and deploy your project in Business Central to make the process available to KIE Server.
-
KIE Server is deployed and connected to Business Central.
-
In Business Central, go to Menu → Design → Projects.
-
Click the project that you want to deploy.
-
Click Deploy.
You can also select the Build & Install option to build the project and publish the KJAR file to the configured Maven repository without deploying to a KIE Server. In a development environment, you can click Deploy to deploy the built KJAR file to a KIE Server without stopping any running instances (if applicable), or click Redeploy to deploy the built KJAR file and replace all instances. The next time you deploy or redeploy the built KJAR, the previous deployment unit (KIE container) is automatically updated in the same target KIE Server. In a production environment, the Redeploy option is disabled and you can click Deploy only to deploy the built KJAR file to a new deployment unit (KIE container) on a KIE Server.
To configure the KIE Server environment mode, set the
org.kie.server.mode
system property toorg.kie.server.mode=development
ororg.kie.server.mode=production
. To configure the deployment behavior for a corresponding project in Business Central, go to project Settings → General Settings → Version and toggle the Development Mode option. By default, KIE Server and all new projects in Business Central are in development mode. You cannot deploy a project with Development Mode turned on or with a manually addedSNAPSHOT
version suffix to a KIE Server that is in production mode.To review project deployment details, click View deployment details in the deployment banner at the top of the screen or in the Deploy drop-down menu. This option directs you to the Menu → Deploy → Execution Servers page.
10.2.3. Executing a business process in Business Central
After you build and deploy the project that contains your business process, you can execute the defined functionality for the business process.
As an example, this procedure uses the Mortgage_Process sample project in Business Central. In this scenario, you input data into a mortgage application form acting as the mortgage broker. The MortgageApprovalProcess business process runs and determines whether or not the applicant has offered an acceptable down payment based on the decision rules defined in the project. The business process either ends the rule testing or requests that the applicant increase the down payment to proceed. If the application passes the business rule testing, the bank approver reviews the application and either approves or denies the loan.
-
KIE Server is deployed and connected to Business Central.
-
In Business Central, go to Menu → Projects and select a space. The default space is MySpace.
-
In the upper-right corner of the window, click the arrow next to Add Project and select Try Samples.
-
Select the Mortgage_Process sample and click Ok.
-
On the project page, select Mortgage_Process.
-
On the Mortgage_Process page, click Build.
-
After the project has built, click Deploy.
-
Go to Menu → Manage → Process Definitions.
-
Click anywhere in the MortgageApprovalProcess row to view the process details.
-
Click the Diagram tab to view the business process diagram in the editor.
-
Click New Process Instance to open the Application form and input the following values into the form fields:
-
Down Payment:
30000
-
Years of amortization:
10
-
Name:
Ivo
-
Annual Income:
60000
-
SSN:
123456789
-
Age of property:
8
-
Address of property:
Brno
-
Locale:
Rural
-
Property Sale Price:
50000
-
-
Click Submit to start a new process instance. After starting the process instance, the Instance Details view opens.
-
Click the Diagram tab to view the process flow within the process diagram. The state of the process is highlighted as it moves through each task.
-
Click Menu → Manage → Tasks.
For this example, the user or users working on the corresponding tasks are members of the following groups:
-
approver: For the Qualify task
-
broker: For the Correct Data and Increase Down Payment tasks
-
manager: For the Final Approval task
-
-
As the approver, review the Qualify task information, click Claim and then Start to start the task, and then select Is mortgage application in limit? and click Complete to complete the task flow.
-
In the Tasks page, click anywhere in the Final Approval row to open the Final Approval task.
-
Click Claim to claim responsibility for the task, and click Complete to finalize the loan approval process.
The Save and Release buttons are only used to either pause the approval process and save the instance if you are waiting on a field value, or to release the task for another user to modify. |
10.2.4. Process definitions and process instances in Business Central
A process definition is a Business Process Model and Notation (BPMN) 2.0 file that serves as a container for a process and its BPMN diagram. The process definition shows all of the available information about the business process, such as any associated sub-processes or the number of users and groups that are participating in the selected definition.
A process definition also defines the import
entry for imported processes that the process definition uses, and the relationship
entries.
<definitions id="Definition"
targetNamespace="http://www.jboss.org/drools"
typeLanguage="http://www.java.com/javaTypes"
expressionLanguage="http://www.mvel.org/2.0"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"Rule Task
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd"
xmlns:g="http://www.jboss.org/drools/flow/gpd"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
xmlns:tns="http://www.jboss.org/drools">
<process>
PROCESS
</process>
<bpmndi:BPMNDiagram>
BPMN DIAGRAM DEFINITION
</bpmndi:BPMNDiagram>
</definitions>
After you have created, configured, and deployed your project that includes your business processes, you can view the list of all the process definitions in Business Central Menu ā Manage ā Process Definitions. You can refresh the list of deployed process definitions at any time by clicking the refresh button in the upper-right corner.
The process definition list shows all the available process definitions that are deployed into the platform. Click any of the process definitions listed to show the corresponding process definition details. This displays information about the process definition, such as if there is a sub-process associated with it, or how many users and groups exist in the process definition. The Diagram tab in the process definition details page contains the BPMN2-based diagram of the process definition.
Within each selected process definition, you can start a new process instance for the process definition by clicking the New Process Instance button in the upper-right corner. Process instances that you start from the available process definitions are listed in Menu → Manage → Process Instances.
You can also define the default pagination option for all users under the Manage drop-down menu (Process Definition, Process Instances, Tasks, Jobs, and Execution Errors) and in Menu → Track → Task Inbox.
10.2.4.1. Starting a process instance from the process definitions page
You can start a process instance in Menu → Manage → Process Definitions. This is useful for environments where you are working with several projects or process definitions at the same time.
-
A project with a process definition has been deployed in Business Central.
-
In Business Central, go to Menu → Manage → Process Definitions.
-
Select the process definition for which you want to start a new process instance from the list. The details page of the definition opens.
-
Click New Process Instance in the upper-right corner to start a new process instance.
-
Provide any required information for the process instance.
-
Click Submit to create the process instance.
-
View the new process instance in Menu → Manage → Process Instances.
10.2.4.2. Starting a process instance from the process instances page
You can create new process instances or view the list of all the running process instances in Menu → Manage → Process Instances.
-
A project with a process definition has been deployed in Business Central.
-
In Business Central, go to Menu → Manage → Process Instances.
-
Click New Process Instance in the upper-right corner and select the process definition for which you want to start a new process instance from the drop-down list.
-
Provide any information required to start a new process instance.
-
Click Start to create the process instance.
The new process instance appears in the Manage Process Instances list.
10.2.4.3. Generating process documentation in Business Central
In the process designer in Business Central, you can view and print a report of the process definition. The process documentation summarizes the components, data, and visual flow of the process in a format (PDF) that you can print and share more easily.
-
In Business Central, navigate to a project that contains a business process and select the process.
-
In the process designer, click the Documentation tab to view the summary of the process file, and click Print in the top-right corner of the window to print the PDF report.
Figure 45. Generate process documentation
10.2.4.4. Process definitions in XML
You can create processes directly in XML format using the BPMN 2.0 specifications. The syntax of these XML processes is defined using the BPMN 2.0 XML Schema Definition.
A process XML file consists of the following core sections:
-
process
: This is the top part of the process XML that contains the definition of the different nodes and their properties. The process XML file consists of exactly one<process>
element. This element contains parameters related to the process (its type, name, ID, and package name), and consists of three subsections: a header section where process-level information such as variables, globals, imports, and lanes are defined, a nodes section that defines each of the nodes in the process, and a connections section that contains the connections between all the nodes in the process. -
BPMNDiagram
: This is the lower part of the process XML file that contains all graphical information, such as the location of the nodes. The nodes section contains a specific element for each node and defines the various parameters and any sub-elements for that node type.
The following process XML file fragment shows a simple process that contains a sequence of a start event, a script task that prints "Hello World"
to the console, and an end event:
<?xml version="1.0" encoding="UTF-8"?>
<definitions
id="Definition"
targetNamespace="http://www.jboss.org/drools"
typeLanguage="http://www.java.com/javaTypes"
expressionLanguage="http://www.mvel.org/2.0"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd"
xmlns:g="http://www.jboss.org/drools/flow/gpd"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
xmlns:tns="http://www.jboss.org/drools">
<process processType="Private" isExecutable="true" id="com.sample.hello" name="Hello Process">
<!-- nodes -->
<startEvent id="_1" name="Start" />
<scriptTask id="_2" name="Hello">
<script>System.out.println("Hello World");</script>
</scriptTask>
<endEvent id="_3" name="End" >
<terminateEventDefinition/>
</endEvent>
<!-- connections -->
<sequenceFlow id="_1-_2" sourceRef="_1" targetRef="_2" />
<sequenceFlow id="_2-_3" sourceRef="_2" targetRef="_3" />
</process>
<bpmndi:BPMNDiagram>
<bpmndi:BPMNPlane bpmnElement="com.sample.hello" >
<bpmndi:BPMNShape bpmnElement="_1" >
<dc:Bounds x="16" y="16" width="48" height="48" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_2" >
<dc:Bounds x="96" y="16" width="80" height="48" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_3" >
<dc:Bounds x="208" y="16" width="48" height="48" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="_1-_2" >
<di:waypoint x="40" y="40" />
<di:waypoint x="136" y="40" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_2-_3" >
<di:waypoint x="136" y="40" />
<di:waypoint x="232" y="40" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
10.2.5. Invoking a Decision Model and Notation (DMN) service in a business process
You can use Decision Model and Notation (DMN) to model a decision service graphically in a decision requirements diagram (DRD) in Business Central and then invoke that DMN service as part of a business process in Business Central. Business processes interact with DMN services by identifying the DMN service and mapping business data between DMN inputs and the business process properties.
As an illustration, this procedure uses an example TrainStation project that defines train routing logic. This example project contains the following data object and DMN components designed in Business Central for the routing decision logic:
Train
objectpublic class Train {
private String departureStation;
private String destinationStation;
private BigDecimal railNumber;
// Getters and setters
}
Compute Rail
DMN modelRail
DMN decision tabletTrain
DMN data typeFor more information about creating DMN models in Business Central, see Decision Model and Notation (DMN) in the Drools documentation.
-
All required data objects and DMN model components are defined in the project.
-
In Business Central, go to Menu → Design → Projects and click the project name.
-
Select or create the business process asset in which you want to invoke the DMN service.
-
In the process designer, use the left toolbar to drag and drop BPMN components as usual to define your overall business process logic, connections, events, tasks, or other elements.
-
To incorporate a DMN service in the business process, add a Business Rule task from the left toolbar or from the start-node options and insert the task in the relevant location in the process flow.
For this example, the following
Accept Train
business process incorporates the DMN service in theRoute To Rail
node:Figure 49. ExampleAccept Train
business process with a DMN service -
Select the business rule task node that you want to use for the DMN service, click Properties in the upper-right corner of the process designer, and under Implementation/Execution, define the following fields:
-
Rule Language: Select
DMN
. -
Namespace: Enter the unique namespace from the DMN model file. Example:
https://www.drools.org/kie-dmn
-
Decision Name: Enter the name of the DMN decision node that you want to invoke in the selected process node. Example:
Rail
-
DMN Model Name: Enter the DMN model name. Example:
Compute Rail
When you explore the root node, ensure that the Namespace and DMN Model Name fields consist of the same value in BPMN as DMN diagram.
-
-
Under Data Assignments → Assignments, click the Edit icon and add the DMN input and output data to define the mapping between the DMN service and the process data.
For the
Route To Rail
DMN service node in this example, you add an input assignment forTrain
that corresponds to the input node in the DMN model, and add an output assignment forRail
that corresponds to the decision node in the DMN model. The Data Type must match the type that you set for that node in the DMN model, and the Source and Target definition is the relevant variable or field for the specified object.Figure 50. Example input and output mapping for theRoute To Rail
DMN service node -
Click Save to save the data input and output data.
-
Define the remainder of your business process according to how you want the completed DMN service to be handled.
For this example, the Properties → Implementation/Execution → On Exit Action value is set to the following code to store the rail number after the
Route To Rail
DMN service is complete:Example code forOn Exit Action
train.setRailNumber(rail);
If the rail number is not computed, the process reaches a
No Appropriate Rail
end error node that is defined with the following condition expression:Figure 51. Example condition forNo Appropriate Rail
end error nodeIf the rail number is computed, the process reaches an
Accept Train
script task that is defined with the following condition expression:Figure 52. Example condition forAccept Train
script task nodeThe
Accept Train
script task also uses the following script in Properties → Implementation/Execution → Script to print a message about the train route and current rail:com.myspace.trainstation.Train t = (com.myspace.trainstation.Train) kcontext.getVariable("train"); System.out.println("Train from: " + t.getDepartureStation() + ", to: " + t.getDestinationStation() + ", is on rail: " + t.getRailNumber());
-
After you define your business process with the incorporated DMN service, save your process in the process designer, deploy the project, and run the corresponding process definition to invoke the DMN service.
For this example, when you deploy the TrainStation project and run the corresponding process definition, you open the process instance form for the
Accept Train
process definition and set thedeparture station
anddestination station
fields to test the execution:Figure 53. Example process instance form for theAccept Train
process definitionAfter the process is executed, a message appears in the server log with the train route that you specified:
Example server log output for theAccept Train
processTrain from: Zagreb, to: Belgrade, is on rail: 1
10.3. BPMN2 tasks in process designer
A task is an automatic activity that is defined in the process model and the smallest unit of work in a process flow. The following task types defined in the BPMN2 specification are available in the jBPM process designer palette:
-
Business rule task
-
Script task
-
User task
-
Service task
-
None task
Business rule task |
|
Script task |
|
User task |
|
Service task |
|
None task |
In addition, the BPMN2 specification provides the ability to create custom tasks. For more information about custom tasks, see BPMN2 custom tasks in process designer.
A business rule task defines a way to make a decision either through a DMN model or a rule flow group.
When a process reaches a business rule task defined by a DMN model, the jBPM engine executes the DMN model decision with the inputs provided.
When a process reaches a business rule task defined by a rule flow group, the jBPM engine begins executing the rules in the defined rule flow group. When there are no more active rules in the rule flow group, the execution continues to the next element. During the rule flow group execution, new activations belonging to the active rule flow group can be added to the agenda because these activations are changed by other rules.
A script task represents a script to be executed during the process execution.
The associated script can access process variables and global variables. Review the following list before using a script task:
-
Avoid low-level implementation details in the process. A script task can be used to manipulate variables, but consider using a service task or a custom task when modelling more complex operations.
-
Ensure that the script is executed immediately, otherwise use an asynchronous service task.
-
Avoid contacting external services through a script task. Use a service task to model communication with an external service.
-
Ensure scripts do not throw exceptions. Runtime exceptions should be caught and managed, for example, inside the script or transformed into signals or errors that can then be handled inside the process.
When a script task is reached during execution, the script is executed and the outgoing flow is taken.
User tasks are tasks in the process workflow that cannot be performed automatically by the system and therefore require the intervention of a human user, the actor.
On execution, the User task element is instantiated as a task that appears in the list of tasks of one or more actors. If a User task element defines the Groups
attribute, it is displayed in task lists of all users that are members of the group. Any user who is a member of the group can claim the task.
After it is claimed, the task disappears from the task list of the other users.
User tasks are implemented as domain-specific tasks and serve as a base for custom tasks.
Service tasks are tasks that do not require human interaction. They are completed automatically by an external software service.
None tasks are completed on activation. This is a conceptual model only. A none task is never actually executed by an IT system.
10.4. BPMN2 sub-processes in process designer
A sub-process is an activity that contains nodes. You can embed part of the main process within a sub-process. You can also include variable definitions within the sub-process. These variables are accessible to all nodes inside the sub-process.
A sub-process must have at least one incoming connection and one outgoing connection. A terminate end event inside a sub-process ends the sub-process instance but does not automatically end the parent process instance. A sub-process ends when there are no more active elements in it.
The following sub-process types are supported in jBPM:
-
Embedded sub-process: A sub-process that is a part of the parent process execution and shares the parent process data, along with declaring its own local sub-process variables.
-
Ad hoc sub-process: A sub-process that has no strict element execution order.
-
Reusable sub-process: A sub-process that is independent of its parent process.
-
Event sub-process: A sub-process that is only triggered on a start event or a timer.
-
Multi-instance sub-process: A sub-process that is instantiated multiple times.
In the following example, the Place order sub-process checks whether sufficient stock is available to place the order and updates the stock information if the order can be placed. The customer is then notified through the main process based on whether or not the order was placed.
An embedded sub-process encapsulates a part of the process. It must contain a start event and at least one end event. Note that the element enables you to define local sub-process variables that are accessible to all elements inside this container.
An ad hoc sub-process or process contains a number of embedded inner activities and is intended to be executed with a more flexible ordering compared to the typical process flow. Unlike regular processes, an ad hoc sub-process does not contain a complete, structured BPMN2 diagram description, for example, from start event to end event. Instead, the ad hoc sub-process contains only activities, sequence flows, gateways, and intermediate events. An ad hoc sub-process can also contain data objects and data associations. The activities within the ad hoc sub-processes are not required to have incoming and outgoing sequence flows. However, you can specify sequence flows between some of the contained activities. When used, sequence flows provide the same ordering constraints as in a regular process. To have any meaning, intermediate events must have outgoing sequence flows and they can be triggered multiple times while the ad hoc sub-process is active.
Reusable sub-processes appear collapsed within the parent process. To configure a reusable sub-process, select the reusable sub-process, click , and expand Implementation/Execution. Set the following properties:
-
Called Element: The ID of the sub-process that the activity calls and instantiates.
-
Independent: If selected, the sub-process is started as an independent process. If not selected, the active sub-process is canceled when the parent process is terminated.
-
Abort Parent: If selected, non-independent reusable sub-processes can abort the parent process when there is an error during the execution of the called process instance. For example, when there’s an error when trying to invoke the sub-process or when the sub-process instance is aborted. This property is visible only when the Independent property is not selected. The following rules apply:
-
If the reusable sub-process is independent, Abort parent is not available.
-
If the reusable sub-process is not independent, Abort parent is available.
-
-
Wait for completion: If selected, the specified On Exit Action is not performed until the called sub-process instance is terminated. The parent process execution continues when the On Exit Action completes. This property is selected (set to
true
) by default. -
Is Async: Select if the task should be invoked asynchronously and cannot be executed instantly.
-
Multiple Instance: Select to execute the sub-process elements a specified number of times. If selected, the following options are available:
-
MI Execution mode: Indicates if the multiple instances execute in parallel or sequentially. If set to Sequential, new instances are not created until the previous instance completes.
-
MI Collection input: Select a variable that represents a collection of elements for which new instances are created. The sub-process is instantiated as many times as the size of the collection.
-
MI Data Input: Specifies the name of the variable containing the selected element in the collection. The variable is used to access elements in the collection.
-
MI Collection output: Optional variable that represents the collection of elements that will gather the output of the multi-instance node.
-
MI Data Output: Specifies the name of the variable that is added to the output collection that you selected in the MI Collection output property.
-
MI Completion Condition (mvel): MVEL expression that is evaluated on each completed instance to check if the specified multiple instance node can complete. If it evaluates to
true
, all remaining instances are canceled.
-
-
On Entry Action: A Java or MVEL script that specifies an action at the start of the task.
-
On Exit Action: A Java or MVEL script that specifies an action at the end of the task.
-
SLA Due Date: The date that the service level agreement (SLA) expires. You can specify the duration in days, minutes, seconds, and milliseconds. For example,
1m
value in SLA due date field indicates one minute. -
Metadata Attributes: Add any custom metadata attribute name and value that you want to use for custom event listeners, such as a listener to implement some action when a metadata attribute is present.
You can open the sub-process in a new editor in Business Central by clicking the Place order task in the main process and then clicking the Open Sub-process task icon.
An event sub-process becomes active when its start event is triggered. It can interrupt the parent process context or run in parallel with it.
With no outgoing or incoming connections, only an event or a timer can trigger the sub-process. The sub-process is not part of the regular control flow. Although self-contained, it is executed in the context of the bounding process.
Use an event sub-process within a process flow to handle events that happen outside of the main process flow. For example, while booking a flight, two events may occur:
-
Cancel booking (interrupting)
-
Check booking status (non-interrupting)
You can model both of these events using the event sub-process.
A multiple instances sub-process is instantiated multiple times when its execution is triggered. The instances are created sequentially or parallelly. If you set the sequential mode, a new sub-process instance is created only after the previous instance has finished. However, when you set the parallel mode, all the sub-process instances are created at once.
A multiple instances sub-process has one incoming connection and one outgoing connection.
10.5. BPMN2 custom tasks in process designer
The BPMN2 specification supports the ability to extend the bpmn2:task
element to create custom tasks in a software implementation. Similar to standard BPMN tasks, custom tasks identify actions to be completed in a business process model, but they also include specialized functionality, such as compatibility with an external service of a specific type (REST, email, or web service) or checkpoint behavior within a process (milestone).
jBPM provides the following predefined custom tasks under Custom Tasks in the BPMN modeler palette:
Custom task type | Custom task node |
---|---|
Rest |
|
Log |
|
WebService |
|
Milestone |
|
DecisionTask |
|
BusinessRuleTask |
|
KafkaPublishMessages |
For more information about enabling or disabling custom tasks in Business Central, see Domain Specific Processes in the jBPM documentation.
In the BPMN modeler, you can configure the following general properties for a selected custom task:
Label | Description |
---|---|
Name |
Identifies the name of the task. You can also double-click the task node to edit the name. |
Documentation |
Describes the task. The text in this field is included in the process documentation, if applicable. |
Is Async |
Determines whether this task is invoked asynchronously. |
AdHoc Autostart |
Determines whether this is an ad hoc task that is started automatically. This option enables the task to automatically start when the process is created instead of being started by a signal event. |
On Entry Action |
Defines a Java, JavaScript, or MVEL script that directs an action at the start of the task. |
On Exit Action |
Defines a Java, JavaScript, or MVEL script that directs an action at the end of the task. |
SLA Due Date |
Specifies the duration (string type) when the service level agreement (SLA) expires. You can specify the duration in days, minutes, seconds, and milliseconds. For example, |
Assignments |
Defines data input and output for the task. |
Metadata Attributes |
Defines the custom metadata attribute name and value that you want to use for custom event listeners, such as a listener to implement some action when a metadata attribute is present. The Metadata Attributes enable the new |
A rest custom task is used to invoke a remote RESTful service or perform an HTTP request from a process.
To use the rest custom task, you can set the URL, HTTP method, and credentials in the process modeler. When a process reaches a rest custom task, it generates an HTTP request and returns the response as a string.
You can click Assignments in the Properties panel to open the REST Data I/O window. In the REST Data I/O window, you can configure the data input and output as required. For example, to execute a rest custom task, enter the following data inputs in Data Inputs and Assignments fields:
-
Url: Endpoint URL for the REST service. This attribute is mandatory.
-
Method: Method of the endpoint called, such as
GET
, andPOST
. The default value isGET
. -
ContentType: Data type when sending data. This attribute is mandatory for
POST
andPUT
requests. -
ContentTypeCharset: Character set for the
ContentType
. -
Content: Data you want to send. This attribute supports backward compatibility, use the ContentData attribute instead.
-
ContentData: Data you want to send. This attribute is mandatory for
POST
andPUT
requests. -
ConnectTimeout: Connection timeout (in seconds). The default value is 60000 milliseconds. You must provide the input value in milliseconds.
-
ReadTimeout: Timeout (in seconds) on response. The default value is 60000 milliseconds. You must provide the input value in milliseconds.
-
Username: User name for authentication.
-
Password: Password for authentication.
-
AuthUrl: URL that is handling authentication.
-
AuthType: Type of URL that is handling authentication.
-
HandleResponseErrors (Optional): Instructs handler to throw errors in case of an unsuccessful response codes (except 2XX).
-
ResultClass: Valid name of the class to which the response is unmarshalled. If not provided, then the raw response is returned in a string format.
-
AcceptHeader: Value of the accept header.
-
AcceptCharset: Character set of the accept header.
-
Headers: Headers to pass for REST call, such as
content-type=text/html
.
You can add the following data output in Data Outputs and Assignments to store the output of the task execution:
-
Result: Output variable (object type) of the rest custom task.
An email custom task is used to send an email from a process. It contains email body associated with it.
When an email custom task is activated, the email data is assigned to the data input property of the task. An email custom task completes when the associated email is sent.
You can click Assignments in the Properties panel to open the Email Data I/O window. In the Email Data I/O window, you can configure the data input as required. For example, to execute an email custom task, enter the following data inputs in Data Inputs and Assignments fields:
-
Body: Body of the email.
-
From: Email address of the sender.
-
Subject: Subject of the email.
-
To: Email address of the recipient. You can specify multiple email addresses separated by semicolon (;).
-
Template (Optional): Template to generate body of the email. The
Template
attribute overrides theBody
parameter, if entered. -
Reply-To: Email address to which reply message is sent.
-
Cc: Email address of the copied recipient. You can specify multiple email addresses separated by semicolon (;).
-
Bcc: Email address of the blind copied recipient. You can specify multiple email addresses separated by semicolon (;).
-
Attachments: Email attachment to send along with the email.
-
Debug: Flag to enable the debug logging.
A log custom task is used to log a message from a process. When a business process reaches a log custom task, the message data is assigned to the data input property.
A log custom task completes when the associated message is logged. You can click Assignments in the Properties panel to open the Log Data I/O window. In the Log Data I/O window, you can configure the data input as required. For example, to execute a log custom task, enter the following data inputs in Data Inputs and Assignments fields:
-
Message: Log message from the process.
A web service custom task is used to invoke a web service from a process. This custom task serves as a web service client with the web service response stored as a string.
To invoke a web service from a process, you must use the correct task type. You can click Assignments in the Properties panel to open the WS Data I/O window. In the WS Data I/O window, you can configure the data input and output as required. For example, to execute a web service task, enter the following data inputs in Data Inputs and Assignments fields:
-
Endpoint: Endpoint location of the web service to invoke.
-
Interface: Name of a service, such as
Weather
. -
Mode: Mode of a service, such as
SYNC
,ASYNC
, orONEWAY
. -
Namespace: Namespace of the web service, such as
http://ws.cdyne.com/WeatherWS/
. -
Operation: Method name to call.
-
Parameter: Object or array to be sent for the operation.
-
Url: URL of the web service, such as
http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL
.
You can add the following data output in Data Outputs and Assignments to store the output of the task execution:
-
Result: Output variable (object type) of the web service task.
A milestone represents a single point of achievement within a process instance. You can use milestones to flag certain events to trigger other tasks or track the progress of the process.
Milestones are useful for Key Performance Indicator (KPI) tracking or for identifying the tasks that are still to be completed. Milestones can occur at the end of a stage in a process or they can be the result of achieving other milestones.
Milestones can reach the following states during process execution:
-
Active
: A milestone condition has been defined for the milestone node but it has not been met. -
Completed
: A milestone condition has been met (if applicable), the milestone has been achieved, and the process can proceed to the next task or can end.
You can click Assignments in the Properties panel to open the Milestone Data I/O window. In the Milestone Data I/O window, you can configure the data input as required. For example, to execute a milestone, enter the following data inputs in Data Inputs and Assignments fields:
-
Condition: Condition for the milestone to meet. For example, you can enter a Java expression (string data type) that uses a process variable.
A decision task is used to execute a DMN diagram and invoke a decision engine service from a process. By default, a decision task maps to the DMN decision.
You can use decision tasks to make an operational decision in a process. Decision tasks are useful for identifying key decisions in a process that need to be made.
You can click Assignments in the Properties panel to open the Decision Task Data I/O window. In the Decision Task Data I/O window, you can configure the data input as required. For example, to execute a decision task, enter the following data inputs in Data Inputs and Assignments fields:
-
Decision: Decision for a process to make.
-
Language: Language of the decision task, defaults to DMN.
-
Model: Name of the DMN model.
-
Namespace: Namespace of the DMN model.
A business rule task is used to evaluate a DRL rule and invoke a decision engine service from a process. By default, a business rule task maps to the DRL rules.
You can use business rule tasks to evaluate key business rules in a business process. You can click Assignments in the Properties panel to open the Business Rule Task Data I/O window. In the Business Rule Task Data I/O window, you can configure the data input as required. For example, to execute a business rule task, enter the following data inputs in Data Inputs and Assignments fields:
-
KieSessionName: Name of the KIE session.
-
KieSessionType: Type of the KIE session.
-
Language: Language of the business rule task, defaults to DRL.
A Kafka work item is used to send events to a Kafka topic. This custom task includes a work item handler, which uses the Kafka producer to send messages to a specific Kafka server topic. For example, KafkaPublishMessages
task publishes messages from a process to a Kafka topic.
You can click Assignments in the Properties panel to open the KafkaPublishMessages Data I/O window. In the KafkaPublishMessages Data I/O window, you can configure the data input and output as required. For example, to execute a Kafka work item, enter the following data inputs in Data Inputs and Assignments fields:
-
Key: Key of the Kafka message to be sent.
-
Topic: Name of a Kafka topic.
-
Value: Value of the Kafka message to be sent.
You can add the following data output in Data Outputs and Assignments to store the output of the work item execution:
-
Result: Output variable (string type) of the work item.
10.6. BPMN2 events in process designer
An event is something that happens to a business process. BPMN2 supports three categories of events:
-
Start
-
End
-
Intermediate
A start event catches an event trigger, an end event throws an event trigger, and an intermediate event can both catch and throw event triggers.
The following business process diagram shows examples of events:
In this example, the following events occurred:
-
The ATM Card Inserted signal start event is triggered when the signal is received.
-
The timeout intermediate event is an interrupting event based on a timer trigger. This means that the Wait for PIN sub-process is canceled when the timer event is triggered.
-
Depending on the inputs to the process, either end event associated with the Validate User Pin task or the end event associated with the Inform User of Timeout task ends the process.
10.6.1. Start events
Use start events to indicate the start of a business process. A start event cannot have an incoming sequence flow and must have only one outgoing sequence flow. You can use none start events in top-level processes, embedded sub-process, callable sub-processes, and event sub-processes.
All start events, with the exception of the none start event, are catch events. For example, a signal start event starts the process only when the referenced signal (event trigger) is received. You can configure start events in event sub-processes to be interrupting or non-interrupting. An interrupting start event for an event sub-process stops or interrupts the execution of the containing or parent process. A non-interrupting start event does not stop or interrupt the execution of the containing or parent process.
Start event type | Top-level | sub-processes | |
---|---|---|---|
Interrupt |
Non-interrupt |
||
The none start event is a start event without a trigger condition. A process or a sub-process can contain at most one none start event, which is triggered on process or sub-process start by default, and the outgoing flow is taken immediately.
When you use a none start event in a sub-process, the execution of the process flow is transferred from the parent process into the sub-process and the none start event is triggered. This means that the token (the current location within the process flow) is passed from the parent process into the sub-process activity and the none start event of the sub-process generates a token of its own.
The conditional start event is a start event with a Boolean condition definition. The execution is triggered when the condition is first evaluated to false
and then to true
. The process execution starts only if the condition is evaluated to true
after the start event has been instantiated.
A process can contain multiple conditional start events.
A compensation start event is used to start a compensation event sub-process when using a sub-process as the target activity of a compensation intermediate event.
A process or sub-process can contain multiple error start events, which are triggered when an error object with a particular ErrorRef
property is received.
The error object can be produced by an error end event. It indicates an incorrect process ending. The process instance with the error start event starts execution after it has received the respective error object. The error start event is executed immediately upon receiving the error object and its outgoing flow is taken.
The escalation start event is a start event that is triggered by an escalation with a particular escalation code. Processes can contain multiple escalation start events. The process instance with an escalation start event starts its execution when it receives the defined escalation object. The process is instantiated and the escalation start event is executed immediately and its outgoing flow is taken.
A process or an event sub-process can contain multiple message start events, which are triggered by a particular message. The process instance with a message start event only starts its execution from this event after it has received the respective message. After the message is received, the process is instantiated and its message start event is executed immediately (its outgoing flow is taken).
Because a message can be consumed by an arbitrary number of processes and process elements, including no elements, one message can trigger multiple message start events and therefore instantiate multiple processes.
The signal start event is triggered by a signal with a particular signal code. A process can contain multiple signal start events. The signal start event only starts its execution within the process instance after the instance has received the respective signal. Then, the signal start event is executed and its outgoing flow is taken.
The timer start event is a start event with a timing mechanism. A process can contain multiple timer start events, which are triggered at the start of the process, after which the timing mechanism is applied.
When you use a timer start event in a sub-process, execution of the process flow is transferred from the parent process into the sub-process and the timer start event is triggered. The token is taken from the parent sub-process activity and the timer start event of the sub-process is triggered and waits for the timer to trigger. After the time defined by the timing definition has been reached, the outgoing flow is taken.
10.6.2. Intermediate events
Intermediate events drive the flow of a business process. Intermediate events are used to either catch or throw an event during the execution of the business process. These events are placed between the start and end events and can also be used on the boundary of an activity, like a sub-process or a human task, as a catch event. In the BPMN modeler, you can set a data output in the Data Output and Assignments field for a boundary event, which is used in a further process to access the process instance details. Note that the compensation events do not support the feature of setting a data output variable.
For example, you can set the following data output variables for a boundary event:
-
nodeInstance
: Carries the node instance details to use in a further process when the boundary event is triggered. -
signal
: Carries the name of the signal. -
event
: Carries the event details. -
workItem
: Carries the work item details. This variable can be set for work item or user task.
The boundary catch events can be configured as interrupting or non-interrupting. An interrupting boundary catch event cancels the bound activity whereas a non-interrupting event does not.
An intermediate event handles a particular situation that occurs during process execution. The situation is a trigger for an intermediate event. In a process, intermediate events with one outgoing flow can be placed on an activity boundary.
If the event occurs while the activity is being executed, the event triggers its execution to the outgoing flow. One activity may have multiple boundary intermediate events. Note that depending on the behavior you require from the activity with the boundary intermediate event, you can use either of the following intermediate event types:
-
Interrupting: The activity execution is interrupted and the execution of the intermediate event is triggered.
-
Non-interrupting: The intermediate event is triggered and the activity execution continues.
Intermediate event type | Catching | Boundary | Throwing | |
---|---|---|---|---|
Interrupt |
Non-interrupt |
|||
A message intermediate event is an intermediate event that enables you to manage a message object. Use one of the following events:
-
A throwing message intermediate event produces a message object based on the defined properties.
-
A catching message intermediate event listens for a message object with the defined properties.
A timer intermediate event enables you to delay workflow execution or to trigger the workflow execution periodically. It represents a timer that can trigger one or multiple times after a specified period of time. When the timer intermediate event is triggered, the timer condition, which is the defined time, is checked and the outgoing flow is taken. When the timer intermediate event is placed in the process workflow, it has one incoming flow and one outgoing flow. Its execution starts when the incoming flow transfers to the event. When a timer intermediate event is placed on an activity boundary, the execution is triggered at the same time as the activity execution.
The timer is canceled if the timer element is canceled, for example by completing or aborting the enclosing process instance.
A conditional intermediate event is an intermediate event with a boolean condition as its trigger. The event triggers further workflow execution when the condition evaluates to true
and its outgoing flow is taken.
The event must define the Expression
property. When a conditional intermediate event is placed in the process workflow, it has one incoming flow, one outgoing flow, and its execution starts when the incoming flow transfers to the event. When a conditional intermediate event is placed on an activity boundary, the execution is triggered at the same time as the activity execution. Note that if the event is non-interrupting, the event triggers continuously while the condition is true
.
A signal intermediate event enables you to produce or consume a signal object. Use either of the following options:
-
A throwing signal intermediate event produces a signal object based on the defined properties.
-
A catching signal intermediate event listens for a signal object with the defined properties.
An error intermediate event is an intermediate event that can be used only on an activity boundary. It enables the process to react to an error end event in the respective activity.
The activity must not be atomic. When the activity finishes with an error end event that produces an error object with the respective ErrorCode
property, the error intermediate event catches the error object and execution continues to its outgoing flow.
A compensation intermediate event is a boundary event attached to an activity in a transaction sub-process. It can finish with a compensation end event or a cancel end event. The compensation intermediate event must be associated with a flow, which is connected to the compensation activity.
The activity associated with the boundary compensation intermediate event is executed if the transaction sub-process finishes with the compensation end event. The execution continues with the respective flow.
An escalation intermediate event is an intermediate event that enables you to produce or consume an escalation object. Depending on the action the event element should perform, you need to use either of the following options:
-
A throwing escalation intermediate event produces an escalation object based on the defined properties.
-
A catching escalation intermediate event listens for an escalation object with the defined properties.
A link intermediate event is an intermediate event that makes the process diagram easier to understand without adding additional logic to the process. Link intermediate event is limited to a single process level, for example, link intermediate event cannot connect a parent process with a sub-process.
Use either of the following options:
-
A throwing link intermediate event produces a link object based on the defined properties.
-
A catching link intermediate event listens for a link object with the defined properties.
10.6.3. End events
End events are used to end a business process and may not have any outgoing sequence flows. There may be multiple end events in a business process. All end events, with the exception of the none and terminate end events, are throw events.
End events indicate the completion of a business process. An end event is a node that ends a particular workflow. It has one or more incoming sequence flows and no outgoing flow.
A process must contain at least one end event.
During run time, an end event finishes the process workflow. The end event can finish only the workflow that reached it, or all workflows in the process instance, depending on the end event type.
End event | Icon |
---|---|
The none end event specifies that no other special behavior is associated with the end of the process.
When a flow enters a message end event, the flow finishes and the end event produces a message as defined in its properties.
A throwing signal end event is used to finish a process or sub-process flow. When the execution flow enters the element, the execution flow finishes and produces a signal identified by its SignalRef
property.
The throwing error end event finishes the incoming workflow, which means consumes the incoming token, and produces an error object. Any other running workflows in the process or sub-process remain uninfluenced.
A compensation end event is used to finish a transaction sub-process and trigger the compensation defined by the compensation intermediate event attached to the boundary of the sub-process activities.
The escalation end event finishes the incoming workflow, which means consumes the incoming token, and produces an escalation signal as defined in its properties, triggering the escalation process.
The terminate end event finishes all execution flows in the specified process instance. Activities being executed are canceled. The sub-process instance terminates if it reaches a terminate end event.
10.7. BPMN2 gateways in process designer
Gateways are used to create or synchronize branches in the workflow using a set of conditions called the gating mechanism. BPMN2 supports two types of gateways:
-
Converging gateways, merging multiple flows into one flow
-
Diverging gateways, splitting one flow into multiple flows
One gateway cannot have multiple incoming and multiple outgoing flows.
In the following business process diagram, the XOR gateway evaluates only the incoming flow whose condition evaluates to true:
In this example, the customer details are verified by a user and the process is assigned to a user for approval. If approved, an approval notification is sent to the user. If the event of the request is rejected, a rejection notification is sent to the user.
Element type | Icon |
---|---|
exclusive (XOR) |
|
Inclusive |
|
Parallel |
|
Event |
In an exclusive diverging gateway, only the first incoming flow whose condition evaluates to true is chosen. In a converging gateway, the next node is triggered for each triggered incoming flow.
The gateway triggers exactly one outgoing flow. The flow with the constraint evaluated to true and the lowest priority number is taken.
Ensure that at least one of the outgoing flows evaluates to true at run time. Otherwise, the process instance terminates with a runtime exception. |
The converging gateway enables a workflow branch to continue to its outgoing flow as soon as it reaches the gateway. When one of the incoming flows triggers the gateway, the workflow continues to the outgoing flow of the gateway. If it is triggered from more than one incoming flow, it triggers the next node for each trigger.
With an inclusive diverging gateway, the incoming flow is taken and all outgoing flows that evaluate to true are taken.
Connections with lower priority numbers are triggered before triggering higher priority connections. Priorities are evaluated but the BPMN2 specification does not guarantee the priority order. Avoid depending on the priority
attribute in your workflow.
Ensure that at least one of the outgoing flows evaluates to true at run time. Otherwise, the process instance terminates with a runtime exception. |
A converging inclusive gateway merges all incoming flows previously created by an inclusive diverging gateway. It acts as a synchronizing entry point for the inclusive gateway branches.
Use a parallel gateway to synchronize and create parallel flows. With a parallel diverging gateway, the incoming flow is taken, all outgoing flows are taken simultaneously. With a converging parallel gateway, the gateway waits until all incoming flows have entered and only then triggers the outgoing flow.
An event-based gateway is only diverging and enables you to react to possible events as opposed to the data-based exclusive gateway, which reacts to the process data. The outgoing flow is taken based on the event that occurs. Only one outgoing flow is taken at a time. The gateway might act as a start event, where the process is instantiated only if one of the intermediate events connected to the event-based gateway occurs.
10.8. BPMN2 connecting objects in process designer
Connecting objects create an association between two BPMN2 elements. When a connecting object is directed, the association is sequential and indicates that one of the elements is executed immediately before the other, within an instance of the process. Connecting objects can start and end at the top, bottom, right, or left of the process elements being associated. The OMG BPMN2 specification allows you to use your discretion, placing connecting objects in a way that makes the process behavior easy to understand and follow.
BPMN2 supports two main types of connecting objects:
-
Sequence flows: Connect elements of a process and define the order in which those elements are executed within an instance.
-
Association flows: Connect the elements of a process without execution semantics. Association flows can be undirected or unidirectional.
The new process designer supports only undirected association flows. The legacy designer supports one direction and Unidirectional flows. |
10.9. BPMN2 swimlanes in process designer
Swimlanes are process elements that visually group tasks related to one group or user. You can use user tasks in combination with swimlanes to assign multiple user tasks to the same actor, due to Autoclaim
property of the swimlanes. When a potential owner of a group claims the first task in a swimlane, then other tasks are directly assigned to the same owner. Therefore, the claim for other tasks is not needed by the remaining owners of the group. The Autoclaim
property enables the auto-assignment of the tasks that are related to a swimlane.
If the remaining user tasks in a swimlane contain multiple predefined ActorIds , then the user tasks are not assigned automatically.
|
In the following example, an analyst lane consists of two user tasks:
The Group field in the Update Customer Details and Resolve Customer Issue tasks contain the value analyst
. When the process is started, and the Update Customer Details task is claimed, started, or completed by an analyst, and the Resolve Customer Issue task is claimed and assigned to the user who completed the first task. However, if only the Update Customer Details task contains the analyst group assigned, and the second task contains no user or group assignments, and the process stops after the first task completes.
You can disable the Autoclaim
property of the swimlanes. If the Autoclaim
property is disabled, then the tasks related to a swimlane are not assigned automatically. By default, the value of Autoclaim
property is set as true
. If needed, you can also change the default value for the Autoclaim
property from project settings in Business Central or using the deployment descriptor file.
To change the default value of Autoclaim
property of swimlanes in Business Central:
-
Go to project Settings.
-
Open Deployment → Environment entries.
-
Enter the following values in the given fields:
-
Name -
Autoclaim
-
Value -
"falseā
-
If you want to set the environment entry in the XML deployment descriptor, add the following code to the kie-deployment-descriptor.xml
file:
<environment-entries>
..
<environment-entry>
<resolver>mvel</resolver>
<identifier>new String ("false")</identifier>
<parameters/>
<name>Autoclaim</name>
</environment-entry>
..
</environment-entries>
10.10. BPMN2 artifacts in process designer
Artifacts are used to provide additional information about a process. An artifact is any object depicted in the BPMN2 diagram that is not part of the process workflow. Artifacts have no incoming or outgoing flow objects.The purpose of artifacts is to provide additional information required to understand the diagram. The artifacts table lists the artifacts supported in the legacy process designer.
Artifact type | Description |
---|---|
Group |
Organizes tasks or processes that have significance in the overall process. Group artifacts are not supported in the new process designer. |
Text annotation |
Provides additional textual information for the BPMN2 diagram. |
Data object |
Displays the data flowing through a process in the BPMN2 diagram. |
10.10.1. Creating data object
Data objects represent, for example, documents used in a process in physical and digital form. Data objects appear as a page with a folded top right corner. The following procedure is a generic overview of creating a data object.
In jBPM 7.59.0, limited support for data objects is provided that excludes support for data inputs, data outputs, and associations. |
-
Create a business process.
-
In the process designer, select the Artifacts → Data Object from the tool palette.
-
Either drag and drop a data object onto the process designer canvas or click a blank area of the canvas.
-
If necessary, in the upper-right corner of the screen, click the Properties icon.
-
Add or define the data object information listed in the following table as required.
Table 22. Data object parameters Label Description Name
The name of the data object. You can also double-click the data object shape to edit the name.
Metadata Attributes
Add any custom metadata attribute name and value that you want to use for custom event listeners, such as a listener to implement some action when a metadata attribute is present.
The Metadata Attributes enable the new
metaData
extensions to BPMN diagrams and modify the behavior of the overall data object.Type
Select a type of the data object.
When you define a data type for a data object, you can use the same data type for other data type fields in Properties, such as Imports and Data Assignments. -
Click Save.
10.11. Variables
Variables store data that is used during runtime. Process designer uses three types of variables:
Global variables are visible to all process instances and assets in a particular session. They are intended to be used primarily by business rules and by constraints and are created dynamically by rules or constraints.
Process variables are defined as properties in the BPMN2 definition file and are visible within the process instance. They are initialized at process creation and destroyed on process completion.
Local variables are associated with and available within specific process elements, such as activities. They are initialized when the element context is initialized, that is, when the execution workflow enters the node and execution of the onEntry
action has finished, if applicable. They are destroyed when the element context is destroyed, that is, when the execution workflow leaves the element.
An element, such as a process, sub-process, or task can only access variables in its own and parent contexts. An element cannot access a variable defined in the element’s child element. Therefore, when an elements requires access to a variable during runtime, its own context is searched first.
If the variable cannot be found directly in the element’s context, the immediate parent context is searched. The search continues until the process context is reached. In case of global variables, the search is performed directly on the session container.
If the variable cannot be found, a read access request returns null
and a write access produces an error message, and the process continues its execution.
Variables are searched for based on their ID.
10.11.1. Variable tags
For greater control over variable behavior, you can tag process variables and local variables in the BPMN process file. Tags are simple string values that you add as metadata to a specific variable.
jBPM supports the following tags for process variables and local variables:
-
required
: Sets the variable as a requirement in order to start a process instance. If a process instance starts without the required variable, jBPM generates aVariableViolationException
error. -
readonly
: Indicates that the variable is for informational purposes only and can be set only once during process instance execution. If the value of a read-only variable is modified at any time, jBPM generates aVariableViolationException
error. -
restricted
: A special tag that is used with theVariableGuardProcessEventListener
to indicate that permission is granted to modify the variable based on the required and the existing role.VariableGuardProcessEventListener
is extended fromDefaultProcessEventListener
and supports two different constructors:-
VariableGuardProcessEventListener
public VariableGuardProcessEventListener(String requiredRole, IdentityProvider identityProvider) { this("restricted", requiredRole, identityProvider); }
-
VariableGuardProcessEventListener
public VariableGuardProcessEventListener(String tag, String requiredRole, IdentityProvider identityProvider) { this.tag = tag; this.requiredRole = requiredRole; this.identityProvider = identityProvider; }
Therefore, you must add an event listener to the session with the allowed role name and identity provider that returns the user role as shown in the following example:
ksession.addEventListener(new VariableGuardProcessEventListener("AdminRole", myIdentityProvider));
In the previous example, the
VariableGuardProcessEventListener
method verifies if a variable is tagged with a security constraint tag (restricted
). If the user does not have the required role, then jBPM generates aVariableViolationException
error. -
The variable tags that appear in the Business Central UI, for example internal , input , output , business-relevant , and tracked are not supported in jBPM.
|
You can add the tag directly to the BPMN process source file as a customTags
metadata property with the tag value defined in the format ![CDATA[TAG_NAME]]
.
For example, the following BPMN process applies the required
tag to an approver
process variable:
<bpmn2:property id="approver" itemSubjectRef="ItemDefinition_9" name="approver">
<bpmn2:extensionElements>
<tns:metaData name="customTags">
<tns:metaValue><![CDATA[required]]></tns:metaValue>
</tns:metaData>
</bpmn2:extensionElements>
</bpmn2:property>
You can use more than one tag for a variable where applicable. You can also define custom variable tags in your BPMN files to make variable data available to jBPM process event listeners. Custom tags do not influence the jBPM runtime as the standard variable tags do and are for informational purposes only. You define custom variable tags in the same customTags
metadata property format that you use for standard jBPM variable tags.
10.11.2. Defining global variables
Global variables exist in a knowledge session and can be accessed and are shared by all assets in that session. They belong to the particular session of the Knowledge Base and they are used to pass information to the engine. Every global variable defines its ID and item subject reference. The ID serves as the variable name and must be unique within the process definition. The item subject reference defines the data type the variable stores.
The rules are evaluated at the moment the fact is inserted.
Therefore, if you are using a global variable to constrain a fact pattern and the global is not set, the system returns a |
Global variables are initialized either when the process with the variable definition is added to the session or when the session is initialized with globals as its parameters.
Values of global variables can typically be changed during the assignment, which is a mapping between a process variable and an activity variable. The global variable is then associated with the local activity context, local activity variable, or by a direct call to the variable from a child context.
-
You have created a project in Business Central and it contains at least one business process asset.
-
Open a business process asset.
-
Click a blank area of the process designer canvas.
-
Click the Properties icon on the upper-right side of the screen to open the Properties panel.
-
If necessary, expand the Process section.
-
In the Global Variables sub-section, click the plus icon.
-
Enter a name for the variable in the Name box.
-
Select a data type from the Data Type menu.
10.11.3. Defining process variables
Process variables are defined as properties in the BPMN2 definition file and are visible within the process instance. They are initialized at process creation and destroyed on process completion.
A process variable is a variable that exists in a process context and can be accessed by its process or its child elements. Process variables belong to a particular process instance and cannot be accessed by other process instances. Every process variable defines its ID and item subject reference: the ID serves as the variable name and must be unique within the process definition. The item subject reference defines the data type the variable stores.
Process variables are initialized when the process instance is created. Their value can be changed by the process activities using the Assignment, when the global variable is associated with the local Activity context, local Activity variable, or by a direct call to the variable from a child context.
Note that process variables should be mapped to local variables.
-
You have created a project in Business Central and it contains at least one business process asset.
-
Open a business process asset.
-
Click a blank area of the process designer canvas.
-
Click the Properties icon on the upper-right side of the screen to open the Properties panel.
-
If necessary, expand the Process Data section.
-
In the Process Variables sub-section, click the plus icon.
-
Enter a name for the variable in the Name box.
-
Select a data type from the Data Type menu.
10.11.4. Defining local variables
Local variables are available within their process element, such as an activity. They are initialized when the element context is initialized, that is, when the execution workflow enters the node and execution of the onEntry
action has finished, if applicable. They are destroyed when the element context is destroyed, that is, when the execution workflow leaves the element.
Values of local variables can be mapped to global or process variables. This enables you to maintain relative independence of the parent element that accommodates the local variable. Such isolation might help prevent technical exceptions.
A local variable is a variable that exists in a child element context of a process and can be accessed only from within this context. Local variables belong to the particular element of a process.
For tasks, with the exception of the Script task, you can define Data Input Assignments
and Data Output Assignments
in the Assignments property. Data Input Assignment defines variables that enter the Task and therefore provide the entry data needed for the task execution. The Data Output Assignments can refer to the context of the Task after execution to acquire output data.
User Tasks present data related to the actor that is executing the User Task. Additionally, User Tasks also request the actor to provide result data related to the execution.
To request and provide the data, use task forms and map the data in the Data Input Assignment parameter to a variable. Map the data provided by the user in the Data Output Assignment parameter if you want to preserve the data as output.
-
You have created a project in Business Central and it contains at least one business process asset that has at least one task that is not a script task.
-
Open a business process asset.
-
Select a task that is not a script task.
-
Click the Properties icon on the upper-right side of the screen to open the Properties panel.
-
Click the box under the Assignments sub-section. The Task Data I/O dialog box opens.
-
Click Add next to Data Inputs and Assignments or Data Outputs and Assignments.
-
Enter a name for the local variable in the Name box.
-
Select a data type from the Data Type menu.
-
Select a source or target then click Save.
10.11.5. Editing process variable values
After starting a process instance, you can edit process variable values in Business Central. The supported variables types are: Boolean, Float, Integer, and Enums.
-
You have created a project in Business Central and have started a process instance.
-
In Business Central, go to Menu → Manage → Process Instances.
-
Select the Process Variables tab and click Edit for the variable name that you want to edit.
-
Add or change the Variable Value and click Save.
10.12. Action scripts
Action scripts are pieces of code that define the Script
property or the interceptor action of an element. Action scripts can access the global variables, process variables, and predefined variable kcontext
. kcontext is an instance of the ProcessContext
interface. For more information about kcontext
variable, see the ProcessContext
Javadoc.
Java and MVEL are supported as dialects for action script definitions. MVEL accepts valid Java code and additionally provides support for nested access to parameters. For example, the MVEL call person.name
is equivalent of Java call person.getName()
.
// Java dialect
System.out.println(person.getName());
// MVEL dialect
System.out.println(person.name);
You can also use action scripts to view information about process instances. For example, use the following commands to:
-
Return the ID of a process instance:
System.out.println(kcontext.getProcessInstance().getId());
-
Return the parent process instance ID if a process instance has a parent:
System.out.println(kcontext.getProcessInstance().getParentProcessInstanceId());
-
Return the ID of a process definition related to a process instance:
System.out.println(kcontext.getProcessInstance().getProcessId());
-
Return the name of a process definition related to a process instance:
System.out.println(kcontext.getProcessInstance().getProcessName());
-
Return the state of a process instance:
System.out.println(kcontext.getProcessInstance().getState());
To set a process variable in an action script, use kcontext.setVariable("VARIABLE_NAME", "VALUE")
.
10.13. Timers
You can use timers to trigger logic after a certain period or to repeat specific actions at regular intervals. Timers wait for a predefined amount of time before triggering once or repeatedly.
10.13.1. Supported timers for jBPM
jBPM supports two types of timers:
-
Quartz: Recommended for use with Spring Boot and Tomcat
-
EJB: Recommended for use with Red Hat JBoss EAP, both on-premise and Red Hat OpenShift Container Platform
Do not use timers for the following business strategies:
|
10.13.2. Configuring timers with delay and period
You can set a timer with delay and a certain period. The delay specifies the waiting time after the node activation, and the period defines the time between the subsequent trigger activation. The period value 0
results in a one-shot timer. You can specify the delay and period expression in [#d][#h][#m][#s][#[ms]]
form, indicating the number of days, hours, minutes, seconds, and milliseconds (default). For example, the expression 1h
indicates one hour waiting time before triggering the timer again.
10.13.3. Configuring timers with ISO-8601 date format
You can configure timers with ISO-8601 date format that supports both one-shot timers and repeatable timers. You can define timers as date and time representation, time duration, or repeating intervals. For example:
-
Date
2020-12-24T20:00:00.000+02:00
signifies that timer is triggered exactly on Christmas at 8:00 p.m. -
Duration
PT1S
signifies that timer is triggered once after one second. -
Repeating intervals
R/PT1S
signifies that timer is triggered every second with any limit. Alternatively,R5/PT1S
triggers the timer five times every second.
10.13.4. Configuring timers with process variables
You can also specify timers using process variables, consisting of the string representation of delay and period or ISO8601 date format. When you specify #{variable}
, the engine parses the expression and replaces the expression value with the variable. In a process, you can use timers using the following ways:
-
Add a timer event to a process flow. The process activation starts the timer and when the timer is triggered (once or repeatedly), it activates the successor of the timer node. Subsequently, the outgoing connection of a timer with a positive period value is triggered multiple times. When a timer node is canceled, the associated timer is also canceled and no more triggers occur.
-
Associate timer as a boundary event with a sub-process or task.
10.13.5. Updating timers in a running process instance
In some cases, the scheduled timer needs to be rescheduled to accommodate the new requirements, such as changing delay, period, or repeat limit. Updating a timer includes many low-level operations, therefore, jBPM provides the following command to perform the low-level operations related to updating a timer as an atomic operation. The following command ensures that all the operations are performed within the same transaction.
org.jbpm.process.instance.command.UpdateTimerCommand
Only boundary timer events and intermediate timer events are supported to update. |
You can reschedule the timer by specifying the two mandatory parameters and one of the three optional parameter sets of the UpdateTimerCommand
class.
Parameter or parameter set | Type |
---|---|
process instance ID (Mandatory) |
|
timer node name (Mandatory) |
|
delay (Optional) |
|
period (Optional) |
|
repeat limit (Optional) |
|
// Start the process instance and record its ID:
long id = kieSession.startProcess(BOUNDARY_PROCESS_NAME).getId();
// Set the timer delay to 3 seconds:
kieSession.execute(new UpdateTimerCommand(id, BOUNDARY_TIMER_ATTACHED_TO_NAME, 3));
10.14. Constraints
A constraint is a boolean expression that is evaluated when an element containing a constraint is executed. You can use constraints in various parts of your process, such as in a diverging gateway.
jBPM supports two types of constraints, including:
-
Code constraints: Constraints that are defined in Java, Javascript, Drools, or MVEL. Code constraints can access the data in the working memory, including the global and process variables. The following code constraint examples contain
person
as a variable in a process:Example Java code constraintreturn person.getAge() > 20;
Example MVEL code constraintreturn person.age > 20;
Example Javascript code constraintperson.age > 20
-
Rule constraints: Constraints that are defined in the form of DRL rule conditions. Rule constraints can access the data in the working memory, including global variables. However, rule constraints cannot access the variables directly in a process but using a process instance. To retrieve the reference of the parent process instance, use the
processInstance
variable of the typeWorkflowProcessInstance
.You can insert a process instance into the session and update it if necessary, for example, using Java code or an on-entry, on-exit, or explicit action in your process. The following example shows a rule constraint, searching for a person with the same name as the value of the
name
variable in the process.Example rule constraint with process variable assignmentprocessInstance : WorkflowProcessInstance() Person( name == ( processInstance.getVariable("name") ) ) # add more constraints here ...
10.15. BPMN process fluent API for Business Central processes
jBPM provides a BPMN process fluent API that enables you to create business processes using factories. You can also manually validate the business process that you created using process fluent API. The process fluent API is defined in the org.kie.api.fluent
package.
Therefore, instead of using BPMN2 XML standard, you can use the process fluent API to create business processes in a few lines of code.
10.15.1. Example requests with the BPMN process fluent API
The following example includes BPMN process fluent API requests for basic interactions with a business process. For more examples, see the process fluent API source in GitHub.
- Creating and interacting with Business Central business processes
-
The following example shows basic business process with a script task, an exception handler, and a variable:
Example request to create and interact with a Business Central business processProcess process = // Create process builder factory.processBuilder(processId) // package and name .packageName("org.jbpm") .name("My process") // start node .startNode(1).name("Start").done() // Add variable of type string .variable(var("pepe", String.class)) // Add exception handler .exceptionHandler(IllegalArgumentException.class, Dialect.JAVA, "System.out.println(\"Exception\");") // script node in Java language that prints "action" .actionNode(2).name("Action") .action(Dialect.JAVA, "System.out.println(\"Action\");").done() // end node .endNode(3).name("End").done() // connections .connection(1, 2) .connection(2, 3) .build();
In this example, a
ProcessBuilderFactory
reference is obtained and then, usingprocessBuilder(String processId)
method, aProcessBuilder
instance is created, which is associated with the given process Id. TheProcessBuilder
instance enables you to build a definition of the created process using the fluent API.A business process consists of three components:
-
Header: The header section contains global elements such as the name of the process, imports, and variables.
In the previous example, the header contains the name and version of the process and the package name.
-
Nodes: The nodes section contains all the different nodes that are part of the process.
In the previous example, nodes are added to the process by calling the
startNode()
,actionNode()
, andendNode()
methods. These methods return a specificNodeBuilder
that allows you to set the properties of that node. After the code finishes configuring that specific node, thedone()
method returns theNodeContainerBuilder
to add more nodes, if necessary. -
Connections: The connections section links the nodes to create a flow chart.
In the previous example, once you add all the nodes, you must connect them by creating connections between them. You can call the
connection()
method, which links the nodes.
Finally, you can call the
build()
method and obtain the generated process definition. Thebuild()
method also validates the process definition and throws an exception if the process definition is not valid. -
10.15.2. Example requests to execute a business process
Once you create a valid process definition instance, you can execute it using a combination of public and internal KIE APIs. To execute a process, create a Resource
, which is used to create a KieBase
. Using the KieBase
, you can create a KieSession
to execute the process.
The following example uses ProcessBuilderFactory.toBytes
process to create a ByteArrayResource
resource.
// Build resource from Process
KieResources resources = ServiceRegistry.getInstance().get(KieResources.class);
Resource res = resources
.newByteArrayResource(factory.toBytes(process))
ā.setSourcePath("/tmp/processFactory.bpmn2"); // source path or target path must be set to be added into kbase
ā// Build kie base from this resource using KIE API
āKieServices ks = KieServices.Factory.get();
āKieRepository kr = ks.getRepository();
āKieFileSystem kfs = ks.newKieFileSystem();
ākfs.write(res);
āKieBuilder kb = ks.newKieBuilder(kfs);
ākb.buildAll(); // kieModule is automatically deployed to KieRepository if successfully built.
āKieContainer kContainer = ks.newKieContainer(kr.getDefaultReleaseId());
āKieBase kbase = kContainer.getKieBase();
ā// Create kie session using KieBase
āKieSessionConfiguration conf = ...;
āEnvironment env = ....;
āKieSession ksession = kbase.newKieSession(conf,env);
ā// execute process using same process Id that is used to obtain ProcessBuilder instance
āksession.startProcess(processId)
10.16. Testing a business process
A business process can be updated dynamically, which can cause errors, therefore testing a process business is also a part of the business process life cycle similar to any other development artifact.
The unit test for a business process ensures that the process behaves as expected in a specific use case. For example, you can test an output based on a particular input. To simplify unit testing, jBPM includes the org.jbpm.test.JbpmJUnitBaseTestCase
class.
The JbpmJUnitBaseTestCase
performs as a base test case class, which is used for jBPM related tests. The JbpmJUnitBaseTestCase
provides the following usage areas:
-
JUnit life cycle methods
Table 24. JUnit life cycle methods Method Description setUp
This method is annotated as
@Before
. It configures a data source andEntityManagerFactory
and deletes the session ID of a singleton.tearDown
This method is annotated as
@After
. It removes history, closesEntityManagerFactory
and a data source, and disposesRuntimeManager
andRuntimeEngines
. -
Knowledge base and knowledge session management methods: To create a session, create
RuntimeManager
andRuntimeEngine
. Use the following methods to create and disposeRuntimeManager
:Table 25. RuntimeManager
andRuntimeEngine
management methodsMethod Description createRuntimeManager
Creates
RuntimeManager
for a given set of assets and selected strategy.disposeRuntimeManager
Disposes
RuntimeManager
that is active in the scope of the test.getRuntimeEngine
Creates new
RuntimeEngine
for the given context. -
Assertions: To test the state of assets, use the following methods:
Table 26. RuntimeManager
andRuntimeEngine
Management MethodsAssertion Description assertProcessInstanceActive(long processInstanceId, KieSession ksession)
Verifies whether a process instance with the given
processInstanceId
is active.assertProcessInstanceCompleted(long processInstanceId)
Verifies whether a process instance with the given
processInstanceId
is completed. You can use this method if session persistence is enabled, otherwise useassertProcessInstanceNotActive(long processInstanceId, KieSession ksession)
.assertProcessInstanceAborted(long processInstanceId)
Verifies whether a process instance with the given
processInstanceId
is aborted. You can use this method if session persistence is enabled, otherwise useassertProcessInstanceNotActive(long processInstanceId, KieSession ksession)
.assertNodeExists(ProcessInstance process, String… nodeNames)
Verifies whether the specified process contains the given nodes.
assertNodeActive(long processInstanceId, KieSession ksession, String… name)
Verifies whether a process instance with the given
processInstanceId
contains at least one active node with the specified node names.assertNodeTriggered(long processInstanceId, String… nodeNames)
Verifies whether a node instance is triggered for each given node during the execution of the specified process instance.
assertProcessVarExists(ProcessInstance process, String… processVarNames)
Verifies whether the given process contains the specified process variables.
assertProcessNameEquals(ProcessInstance process, String name)
Verifies whether the given name matches the specified process name.
assertVersionEquals(ProcessInstance process, String version)
Verifies whether the given process version matches the specified process version.
-
Helper methods: Use following methods to create a new
RuntimeManager
andRuntimeEngine
for a given set of processes with or without using persistence. For more information about persistence, see jBPM engine in jBPM.Table 27. RuntimeManager
andRuntimeEngine
Management MethodsMethod Description setupPoolingDataSource
Configures a data source.
getDs
Returns the configured data source.
getEmf
Returns the configured
EntityManagerFactory
.getTestWorkItemHandler
Returns a test work item handler that can be registered in addition to the default work item handler.
clearHistory
Clears the history log.
The following example contains a start event, a script task, and an end event. The example JUnit test creates a new session, starts the hello.bpmn
process, and verifies whether the process instance is completed and the StartProcess
, Hello
, and EndProcess
nodes are executed.
hello.bpmn
Processpublic class ProcessPersistenceTest extends JbpmJUnitBaseTestCase {
public ProcessPersistenceTest() {
super(true, true);
}
@Test
public void testProcess() {
createRuntimeManager("hello.bpmn");
RuntimeEngine runtimeEngine = getRuntimeEngine();
KieSession ksession = runtimeEngine.getKieSession();
ProcessInstance processInstance = ksession.startProcess("com.sample.bpmn.hello");
assertProcessInstanceNotActive(processInstance.getId(), ksession);
assertNodeTriggered(processInstance.getId(), "StartProcess", "Hello", "EndProcess");
}
}
JbpmJUnitBaseTestCase
supports all predefined RuntimeManager
strategies as part of the unit testing. Therefore, it is enough to specify the strategy that is used when you create a RuntimeManager
as part of a single test.
The following example shows the use of the PerProcessInstance strategy in a task service to manage user tasks:
public class ProcessHumanTaskTest extends JbpmJUnitBaseTestCase {
private static final Logger logger = LoggerFactory.getLogger(ProcessHumanTaskTest.class);
public ProcessHumanTaskTest() {
super(true, false);
}
@Test
public void testProcessProcessInstanceStrategy() {
RuntimeManager manager = createRuntimeManager(Strategy.PROCESS_INSTANCE, "manager", "humantask.bpmn");
RuntimeEngine runtimeEngine = getRuntimeEngine(ProcessInstanceIdContext.get());
KieSession ksession = runtimeEngine.getKieSession();
TaskService taskService = runtimeEngine.getTaskService();
int ksessionID = ksession.getId();
ProcessInstance processInstance = ksession.startProcess("com.sample.bpmn.hello");
assertProcessInstanceActive(processInstance.getId(), ksession);
assertNodeTriggered(processInstance.getId(), "Start", "Task 1");
manager.disposeRuntimeEngine(runtimeEngine);
runtimeEngine = getRuntimeEngine(ProcessInstanceIdContext.get(processInstance.getId()));
ksession = runtimeEngine.getKieSession();
taskService = runtimeEngine.getTaskService();
assertEquals(ksessionID, ksession.getId());
// let John execute Task 1
List<TaskSummary> list = taskService.getTasksAssignedAsPotentialOwner("john", "en-UK");
TaskSummary task = list.get(0);
logger.info("John is executing task {}", task.getName());
taskService.start(task.getId(), "john");
taskService.complete(task.getId(), "john", null);
assertNodeTriggered(processInstance.getId(), "Task 2");
// let Mary execute Task 2
list = taskService.getTasksAssignedAsPotentialOwner("mary", "en-UK");
task = list.get(0);
logger.info("Mary is executing task {}", task.getName());
taskService.start(task.getId(), "mary");
taskService.complete(task.getId(), "mary", null);
assertNodeTriggered(processInstance.getId(), "End");
assertProcessInstanceNotActive(processInstance.getId(), ksession);
}
}
10.16.1. Testing integration with external services
Business processes often include the invocation of external services. Unit testing of a business process enables you to register test handlers that verify whether the specific services are requested correctly, and also provide test responses for the requested services.
To test the interaction with external services, use the default TestWorkItemHandler
handler. You can register the TestWorkItemHandler
to collect all the work items of a particular type. Also, TestWorkItemHandler
contains data related to a task. A work item represents one unit of work, such as sending a specific email or invoking a specific service. The TestWorkItemHandler
verifies whether a specific work item is requested during an execution of a process, and the associated data is correct.
The following example shows how to verify an email task and whether an exception is raised if the email is not sent. The unit test uses a test handler that is executed when an email is requested and enables you to test the data related to the email, such as the sender and recipient. Once the abortWorkItem()
method notifies the engine about the email delivery failure, the unit test verifies that the process handles such case by generating an error and logging the action. In this case, the process instance is eventually aborted.
public void testProcess2() {
createRuntimeManager("sample-process.bpmn");
RuntimeEngine runtimeEngine = getRuntimeEngine();
KieSession ksession = runtimeEngine.getKieSession();
TestWorkItemHandler testHandler = getTestWorkItemHandler();
ksession.getWorkItemManager().registerWorkItemHandler("Email", testHandler);
ProcessInstance processInstance = ksession.startProcess("com.sample.bpmn.hello2");
assertProcessInstanceActive(processInstance.getId(), ksession);
assertNodeTriggered(processInstance.getId(), "StartProcess", "Email");
WorkItem workItem = testHandler.getWorkItem();
assertNotNull(workItem);
assertEquals("Email", workItem.getName());
assertEquals("me@mail.com", workItem.getParameter("From"));
assertEquals("you@mail.com", workItem.getParameter("To"));
ksession.getWorkItemManager().abortWorkItem(workItem.getId());
assertProcessInstanceNotActive(processInstance.getId(), ksession);
assertNodeTriggered(processInstance.getId(), "Gateway", "Failed", "Error");
}
11. Human Tasks
11.1. Introduction
An important aspect of business processes is human task management. While some of the work performed in a process can be executed automatically, some tasks need to be executed by human actors.
jBPM supports a special human task node inside processes for modeling this interaction with human users. This human task node allows process designers to define the properties related to the task that the human actor needs to execute, like for example the type of task, the actor(s), or the data associated with the task.
jBPM also includes a so-called human task service, a back-end service that manages the life cycle of these tasks at runtime. The jBPM implementation is based on the WS-HumanTask specification. Note however that this implementation is fully pluggable, meaning that users can integrate their own human task solution if necessary.
In order to have human actors participate in your processes, you first need to (1) include human task nodes inside your process to model the interaction with human actors, (2) integrate a task management component (like for example the WS-HumanTask based implementation provided by jBPM) and (3) have end users interact with a human task client to request their task list and claim and complete the tasks assigned to them. Each of these three elements will be discussed in more detail in the next sections.
11.2. Creating user tasks
User tasks are used to include human actions as input to the business process.
-
Create a business process.
-
In the process designer, select the Activities tool from the tool palette.
-
Select User.
-
Drag and drop a user task onto the process designer canvas.
-
If necessary, in the upper-right corner of the screen, click the Properties icon.
-
Add or define the task information listed in the following table as required.
Table 28. User task parameters Label Description Name
The name of the user task. You can also double-click the user task shape to edit the name.
Documentation
Enter a description of the task. The text in this field is included in the process documentation. Click the Documentation tab in the upper-left side of the process designer canvas to view the process documentation.
Task Name
The name of the human task.
Subject
Enter a subject for the task.
Actors
The actors responsible for executing the human task. Click Add to add a row then select an actor from the list or click New to add a new actor.
Groups
The groups responsible for executing the human task. Click Add to add a row then select a group from the list or click New to add a new group.
Assignments
Local variables for this task. Click to open the Task Data I/O window then add data inputs and outputs as required. You can also add MVEL expressions as data input and output assignments. For more information about MVEL language, see Language Guide for 2.0.
Reassignments
Specify a different actor to complete this task.
Notifications
Click to specify notifications associated with the task.
Is Async
Select if this task should be invoked asynchronously. Make tasks asynchronous if they cannot be executed instantaneously, for example a task performed by an outside service.
Skippable
Select if this task is not mandatory.
Priority
Specify a priority for the task.
Description
Enter a description for the human task.
Created By
The user that created this task.
AdHoc Autostart
Select if this is an ad hoc task that should be started automatically. AdHoc Autostart enables the task to automatically start when the process or case instance is created instead of being starting by a start task. It is often used in case management.
Multiple Instance
Select if this task has multiple instances.
On Entry Action
A Java, JavaScript, or MVEL script that specifies an action at the start of the task.
On Exit Action
A Java, JavaScript, or MVEL script that specifies an action at the end of the task.
Content
The content of the script.
SLA Due Date
The date that the service level agreement (SLA) expires.
Metadata Attributes
Add any custom metadata attribute name and value that you want to use for custom event listeners, such as a listener to implement some action when a metadata attribute is present.
The Metadata Attributes enable the new
metaData
extensions to BPMN diagrams and modify the behavior of the overall task. -
Click Save.
11.2.1. Setting the user task assignment strategy
The user task assignment strategy is used to automatically assign the tasks to a suitable user. The assignment strategy allows more efficient task allocation based on the associated properties, such as potential owners, task priority, and task data. org.jbpm.task.assignment.strategy
is the system property for the user task assignment strategy in jBPM. You can also explicitly define an assignment strategy for a user task in Business Central.
-
You have created a project in Business Central.
-
You must set the
org.jbpm.task.assignment.enabled
system property totrue
.
-
Create a business process.
For more information about creating a business process in Business Central, see Creating a business process in Business Central.
-
Create a user task.
For more information about creating a user task in Business Central, see Creating user tasks.
-
In the upper-right corner of the screen, click the Properties icon.
-
Expand Implementation/Execution and click below to Assignments, to open the Data I/O window.
-
Add a data input with the name
AssignmentStrategy
, with the typeString
, and with the constant source, such as the strategy name.If AssignmentStrategy
is set as null, then no assignment strategy is used for the task. -
Click Ok.
The
AssignmentStrategy
variable is added as a data input to the user task.
11.2.2. BPMN2 swimlanes in process designer
Swimlanes are process elements that visually group tasks related to one group or user. You can use user tasks in combination with swimlanes to assign multiple user tasks to the same actor, due to Autoclaim
property of the swimlanes. When a potential owner of a group claims the first task in a swimlane, then other tasks are directly assigned to the same owner. Therefore, the claim for other tasks is not needed by the remaining owners of the group. The Autoclaim
property enables the auto-assignment of the tasks that are related to a swimlane.
If the remaining user tasks in a swimlane contain multiple predefined ActorIds , then the user tasks are not assigned automatically.
|
In the following example, an analyst lane consists of two user tasks:
The Group field in the Update Customer Details and Resolve Customer Issue tasks contain the value analyst
. When the process is started, and the Update Customer Details task is claimed, started, or completed by an analyst, and the Resolve Customer Issue task is claimed and assigned to the user who completed the first task. However, if only the Update Customer Details task contains the analyst group assigned, and the second task contains no user or group assignments, and the process stops after the first task completes.
You can disable the Autoclaim
property of the swimlanes. If the Autoclaim
property is disabled, then the tasks related to a swimlane are not assigned automatically. By default, the value of Autoclaim
property is set as true
. If needed, you can also change the default value for the Autoclaim
property from project settings in Business Central or using the deployment descriptor file.
To change the default value of Autoclaim
property of swimlanes in Business Central:
-
Go to project Settings.
-
Open Deployment → Environment entries.
-
Enter the following values in the given fields:
-
Name -
Autoclaim
-
Value -
"falseā
-
If you want to set the environment entry in the XML deployment descriptor, add the following code to the kie-deployment-descriptor.xml
file:
<environment-entries>
..
<environment-entry>
<resolver>mvel</resolver>
<identifier>new String ("false")</identifier>
<parameters/>
<name>Autoclaim</name>
</environment-entry>
..
</environment-entries>
11.3. Configuring emails in task notification
Earlier it was possible to send notifications only to users or group of users in Business Central. Now you can directly add any email addresses as well.
You have created a project in Business Central.
-
Create a business process.
For more information about creating a business process in Business Central, see Creating a business process in Business Central.
-
Create a user task.
For more information about creating a user task in Business Central, see Creating user tasks.
-
In the upper-right corner of the screen, click the Properties icon.
-
Expand Implementation/Execution and click next to Notifications, to open the Notifications window.
-
Click Add.
-
In the Notifications window, enter an email address in the To: email(s) field to set the recipients of the task notification emails.
You can add multiple email addresses separated by comma.
-
Enter the subject and body of the email.
-
Click Ok.
You can see the added email addresses in the To: email(s) column in the Notifications window.
-
Click Ok.
11.4. BPMN2 user task life cycle in process designer
You can trigger a user task element during the process instance execution to create a user task. The user task service of the task execution engine executes the user task instance. The process instance continues the execution only when the associated user task is completed or aborted. A user task life cycle is as follows:
-
When a process instance enters a user task element, the user task is in the
Created
stage. -
Created
stage is a transient stage and the user task enters theReady
stage immediately. The task appears in the task list of all the actors who are allowed to execute the task. -
When an actor claims the user task, the task becomes
Reserved
.
If a user task has a single potential actor, the task is assigned to that actor upon creation. |
-
When an actor who claimed the user task starts the execution, the status of the user task changes to
InProgress
. -
Once an actor completes the user task, the status changes to
Completed
orFailed
depending on the execution outcome.
There are also several other life cycle methods, including:
-
Delegating or forwarding a user task so the user task is assigned to another actor.
-
Revoking a user task, then the user task is no longer claimed by a single actor but is available to all actors who are allowed to take it.
-
Suspending and resuming a user task.
-
Stopping a user task that is in progress.
-
Skipping a user task, in which the execution of the task is suspended.
For more information about the user task life cycle, refer Web Services Human Task.
11.5. BPMN2 task permission matrix in process designer
The user task permission matrix summarizes the actions that are allowed for specific user roles. The user roles are as follows:
-
Potential owner: User who can claim the task, which was claimed earlier and is released and forwarded. The tasks with
Ready
status can be claimed, and the potential owner becomes the actual owner of the task. -
Actual owner: User who claims the task and progresses the task to completion or failure.
-
Business administrator: Super user who can modify the status or progress with the task at any point of the task life cycle.
The following permission matrix represents the authorizations for all operations that modify a task.
-
+
indicates that the user role is allowed to do the specified operation. -
-
indicates that the user role is not allowed to do the specified operation, or the operation does not match with the user’s role.
Operation | Potential owner | Actual owner | Business administrator |
---|---|---|---|
activate |
|
|
|
claim |
|
|
|
complete |
|
|
|
delegate |
|
|
|
fail |
|
|
|
forward |
|
|
|
nominate |
|
|
|
release |
|
|
|
remove |
|
|
|
resume |
|
|
|
skip |
|
|
|
start |
|
|
|
stop |
|
|
|
suspend |
|
|
|
11.6. Task Service and The jBPM engine
As far as the jBPM engine is concerned, human tasks are similar to any other external service that needs to be invoked and are implemented as a domain-specific service. (For more on domain-specific services, see the chapter on them here.) Because a human task is an example of such a domain-specific service, the process itself only contains a high-level, abstract description of the human task to be executed and a work item handler that is responsible for binding this (abstract) task to a specific implementation.
Users can plug in any human task service implementation, such as the one that’s provided by jBPM, or they may register their own implementation. In the next paragraphs, we will describe the human task service implementation provided by jBPM.
The jBPM project provides a default implementation of a human task service based on the WS-HumanTask specification. If you do not need to integrate jBPM with another existing implementation of a human task service, you can use this service. The jBPM implementation manages the life cycle of the tasks (creation, claiming, completion, etc.) and stores the state of all the tasks, task lists, and other associated information. It also supports features like internationalization, calendar integration, different types of assignments, delegation, escalation and deadlines. The code for the implementation itself can be found in the jbpm-human-task module.
The jBPM task service implementation is based on the WS-HumanTask (WS-HT) specification. This specification defines (in detail) the model of the tasks, the life cycle, and many other features. It is very comprehensive and the first version can be found here.
11.7. Task Service API
The human task service exposes a Java API for managing the life cycle of tasks. This allows clients to integrate (at a low level) with the human task service. Note that end users should probably not interact with this low-level API directly, but use one of the more user-friendly task clients (see below) instead. These clients offer a graphical user interface to request task lists, claim and complete tasks, and manage tasks in general. The task clients listed below use the Java API to internally interact with the human task service. Of course, the low-level API is also available so that developers can use it in their code to interact with the human task service directly.
A task service (interface org.kie.api.task.TaskService) offers the following methods (among others) for managing the life cycle of human tasks:
...
void start( long taskId, String userId );
void stop( long taskId, String userId );
void release( long taskId, String userId );
void suspend( long taskId, String userId );
void resume( long taskId, String userId );
void skip( long taskId, String userId );
void delegate(long taskId, String userId, String targetUserId);
void complete( long taskId, String userId, Map<String, Object> results );
...
If you take a look at the method signatures you will notice that almost all of these methods take the following arguments:
-
taskId: The id of the task that we are working with. This is usually extracted from the currently selected task in the user task list in the user interface.
-
userId: The id of the user that is executing the action. This is usually the id of the user that is logged in into the application.
There is also an internal interface that you should check for more methods to interact with the Task Service, this interface is internal until it gets tested. Future version of the External (public) interface can include some of the methods proposed in the InternalTaskService interface. If you want to make use of the methods provided by this interface you need to manually cast to InternalTaskService. One method that can be useful from this interface is getTaskContent():
Map<String, Object> getTaskContent( long taskId );
This method saves you from doing all the boiler plate of getting the ContentMarshallerContext to unmarshall the serialized version of the task content. If you only want to use the stable/public APIs you can just copy what this method does:
Task taskById = taskQueryService.getTaskInstanceById(taskId);
Content contentById = taskContentService.getContentById(taskById.getTaskData().getDocumentContentId());
ContentMarshallerContext context = getMarshallerContext(taskById);
Object unmarshalledObject = ContentMarshallerHelper.unmarshall(contentById.getContent(), context.getEnvironment(), context.getClassloader());
if (!(unmarshalledObject instanceof Map)) {
throw new IllegalStateException(" The Task Content Needs to be a Map in order to use this method and it was: "+unmarshalledObject.getClass());
}
Map<String, Object> content = (Map<String, Object>) unmarshalledObject;
return content;
Because the content of the Task can be any Object, the previous method assume that you are storing a Map of objects to work. If you are storing other than a Map you should do the correspondent checks.
11.7.1. Task event listener
Task service supports task listeners to be invoked upon various life cycle events happening on given task instance. In majority of cases task event listeners are used to intercept certain operation to perform additional logic - like storing task information in separate tables for business activity monitoring needs.
Task event listeners are pluggable and users can provide their own implementation of org.kie.api.task.TaskLifeCycleEventListener
interface. There are beforeTask* and afterTask* methods that are invoked upon given event occurred on a task instance.
TaskEvent (org.kie.api.task.TaskEvent
) is the only argument available to the listener that provides access to:
-
Task instance that the event correspond to
-
TaskContext that provides access to services for further processing needs such as TaskPersistenceContext
In many cases implementors of task event listener need to have access to task variables (either input or output or both) to perform required operations. It can be done as described above (using various services and content marshaller helper) though that in many cases leads to code duplication in multiple listeners thus an extended support was added in 6.5 to simply use TaskContext to obtain that information.
loadTaskVariables(Task task);
Method loadTaskVariables
can be used to populate both input and output variables of a given task by simple and single method call. That method is "no op" in case task variables are already set on a task.
To improve performance task variables are automatically set when they are available - usually given by caller on task service:
-
when task is created it usually has input variables, these variables are then set on Task instance so there is no need to use loadTaskVariables method as only task input variables are available when task is being created - applies to beforeTaskAdded and afterTaskAdded events handling
-
when task is completed it usually has output variables, these variables are set on a task so there is no need to use loadTaskVariables method if only task output variables are required.
Other than that loadTaskVariables should be used to populate task variables.
It’s enough to call it once (like in beforeTask) method of the listener as they will be available to both beforeTask* and afterTask* methods then. |
11.7.2. Data model of task service
Below is the database model used by task service with all tables and their relationship illustrated.
11.8. Interacting with the Task Service
In order to get access to the Task Service API it is recommended to let the Runtime Manager to make sure that everything is setup correctly. Look at the Runtime Manager section for more information. From the API perspective you should be doing something like this:
// ...
RuntimeEngine engine = runtimeManager.getRuntimeEngine(EmptyContext.get());
KieSession kieSession = engine.getKieSession();
// Start a process
kieSession.startProcess("CustomersRelationship.customers", params);
// Do Task Operations
TaskService taskService = engine.getTaskService();
List<TaskSummary> tasksAssignedAsPotentialOwner = taskService.getTasksAssignedAsPotentialOwner("mary", "en-UK");
// Claim Task
taskService.claim(taskSummary.getId(), "mary");
// Start Task
taskService.start(taskSummary.getId(), "mary");
// ...
If you use this approach, there is no need to register the Task Service with the jBPM engine. The Runtime Manager will do that for you automatically. If you don’t use the Runtime Manager, you will be responsible for setting the LocalHTWorkItemHandler in the session in order to get the Task Service notifying the jBPM engine when a task is completed, or the jBPM engine notifying that a task has been created.
In jBPM 6.x the Task Service runs locally to the jBPM engine and for that reason multiple light clients can be created for different jBPM engine instances. All the clients will be sharing the same database (backend storage for the tasks).
11.9. Experimental features
11.9.1. SubTasks
The "Subtasks" feature is an experimental feature in the task service. This feature allows one task to have sub-tasks in a parent-child relationship. The parent task can auto-complete depending on the state of its children (and the subtask strategy used).
You can use it by setting the parentId
of a task, either when creating the task manually via the
task service or otherwise by setting the ParentId
parameter of the task definition in the BPMN2
process definition.
12. Persistence and Transactions
12.1. Persistence and transactions in the jBPM engine
The jBPM engine implements persistence for process states. The implementation uses the JPA framework with an SQL database backend. It can also store audit log information in the database.
The jBPM engine also enables transactional execution of processes using the JTA framework, relying on the persistence backend to support the transactions.
12.2. Persistence of process runtime states
The jBPM engine supports persistent storage of the runtime state of running process instances. Because it stores the runtime states, it can continue execution of a process instance if the jBPM engine stopped or encountered a problem at any point.
The jBPM engine also persistently stores the process definitions and the history logs of current and previous process states.
You can use the persistence.xml
file, specified by the JPA framework, to configure persistence in an SQL database. You can plug in different persistence strategies. For more information about the persistence.xml
file, see Configuration in the persistence.xml
file.
By default, if you do not configure persistence in the jBPM engine, process information, including process instance states, is not made persistent.
When the jBPM engine starts a process, it creates a process instance, which represents the execution of the process in that specific context. For example, when executing a process that processes a sales order, one process instance is created for each sales request.
The process instance contains the current runtime state and context of a process, including current values of any process variables. However, it does not include information about the history of past states of the process, as this information is not required for ongoing execution of a process.
When the runtime state of process instances is made persistent, you can restore the state of execution of all running processes in case the jBPM engine fails or is stopped. You can also remove a particular process instance from memory and then restore it at a later time.
If you configure the jBPM engine to use persistence, it automatically stores the runtime state into the database. You do not need to trigger persistence in the code.
When you restore the state of the jBPM engine from a database, all instances are automatically restored to their last recorded state. Process instances automatically resume execution if they are triggered, for example, by an expired timer, the completion of a task that was requested by the process instance, or a signal being sent to the process instance. You do not need to load separate instances and trigger their execution manually.
The jBPM engine also automatically reloads process instances on demand.
12.2.1. Safe points for persistence
The jBPM engine saves the state of a process instance to persistent storage at safe points during the execution of the process.
When a process instance is started or resumes execution from a previous wait state, the jBPM engine continues the execution until no more actions can be performed. If no more actions can be performed, it means that the process has completed or else has reached a wait state. If the process contains several parallel paths, all the paths must reach a wait state.
This point in the execution of the process is considered a safe point. At this point, the jBPM engine stores the state of the process instance, and of any other process instances that were affected by the execution, to persistent storage.
12.2.2. Binary runtime persistence data model
The runtime persistence data is internal. As a general rule, do not access the database tables directly and, most importantly, do not modify it. Changing the runtime state information for process instances without using the jBPM engine might have unexpected consequences. Use a history log to analyze information about the current or past states of process instances.
In rare cases it might be useful to query internal database tables directly if you have a specific need to do so.
The jBPM engine uses a binary persistence mechanism, otherwise known as marshalling, which converts the state of the process instance into a binary dataset. The same mechanism is also applied to the session state and any work item states.
When the process instance state is persisted, the jBPM engine completes two steps:
-
First, it transforms the process instance information into a binary blob. For performance reasons, the jBPM engine uses a custom serialization mechanism and not standard Java serialization.
-
Next, it stores the blob alongside metadata about this process instance. This metadata includes the process instance ID, process ID, and process start date, as well as other data.
Apart from process instance states, the jBPM engine stores some state information for the session, including the state of timer jobs and the session data for evaluating business rules. The jBPM engine stores the session state as a separate binary blob, along with metadata that includes the ID of the session.
To restore the state of a session, reload the session with a particular ID using the ksession.getId()
method.
Binary datasets that represent process instance states are usually relatively small, because they contain only the minimal execution state of the process instance. For a simple process instance, the state usually includes the nodes that are currently executing and any existing variable values.
The sessioninfo
entity contains the state of the knowledge session in which the process instance is running.
Field | Description | Nullable |
---|---|---|
|
The primary key |
NOT NULL |
|
The last time that the entity was saved to the database |
|
|
The binary dataset containing the state of the session |
NOT NULL |
|
The start time of the session |
|
|
The version field that serves as its optimistic lock value |
The processinstanceinfo
entity contains the state of the process instance.
Field | Description | Nullable |
---|---|---|
|
The primary key |
NOT NULL |
|
The last time that the entity was saved to the database |
|
|
The last time that the entity was retrieved (read) from the database |
|
|
The name (ID) of the process |
|
|
The binary dataset containing the state of the process instance |
NOT NULL |
|
The start time of the process |
|
|
An integer representing the state of the process instance |
NOT NULL |
|
The version field that serves as its optimistic lock value |
The eventtypes
entity contains information about events that a process instance will undergo or has undergone.
Field | Description | Nullable |
---|---|---|
|
This column references the |
NOT NULL |
|
A text field related to an event that the process has undergone |
The workiteminfo
entity contains the state of a work item.
Field | Description | Nullable |
---|---|---|
|
The primary key |
NOT NULL |
|
The creation date of the work item |
|
|
The name of the work item |
|
|
The (primary key) ID of the process. There is no foreign key constraint on this field. |
NOT NULL |
|
An integer representing the state of the work item |
NOT NULL |
|
The version field that serves as its optimistic lock value |
|
|
The binary dataset containing the state of the work item |
NOT NULL |
The CorrelationKeyInfo
entity contains information about correlation keys assigned to the given process instance. The relationship is loose, because this table is optional, used only when correlation capabilities are required.
Field | Description | Nullable |
---|---|---|
|
The primary key |
NOT NULL |
|
The assigned name of the correlation key |
|
|
The ID of the process instance which is assigned to this correlation key |
NOT NULL |
|
The version field that serves as its optimistic lock value |
The CorrelationPropertyInfo
entity contains information about correlation properties for the given correlation key that is assigned to the given process instance.
Field | Description | Nullable |
---|---|---|
|
The primary key |
NOT NULL |
|
The name of the property |
|
|
The value of the property |
NOT NULL |
|
The version field that serves as its optimistic lock value |
|
|
Foreign key to map to the correlation key |
NOT NULL |
The ContextMappingInfo
entity contains information about contextual information mapped to a ksession.
This entity is an internal part of the RuntimeManager
class and can be considered optional when RuntimeManager
is not used.