Chapter 20. Persistence

Binary persistence, or marshaling, converts the state of the process instance into a binary data set. Binary persistence is a mechanism used to store and retrieve information persistently. The same mechanism is also applied to the session state and work item states.

When you enable persistence of a process instance:

  • Red Hat Process Automation Manager transforms the process instance information into binary data. Custom serialization is used instead of Java serialization for performance reasons.
  • The binary data is stored together with other process instance metadata, such as process instance ID, process ID, and the process start date.

The session can also store other forms of state, such as the state of timer jobs, or data required for business rules evaluation. Session state is stored separately as a binary data set along with the ID of the session and metadata. You can restore the session state by reloading a session with given ID. Use ksession.getId() to get the session ID.

Red Hat Process Automation Manager will persist the following when persistence is configured:

  • Session state: This includes the session ID, date of last modification, the session data that business rules would need for evaluation, state of timer jobs.
  • Process instance state: This includes the process instance ID, process ID, date of last modification, date of last read access, process instance start date, runtime data (the execution status including the node being executed, variable values, and other process instance data) and the event types.
  • Work item runtime state: This includes the work item ID, creation date, name, process instance ID, and the work item state itself.

Based on the persisted data, you can restore the state of execution of all running process instances in case of failure or to temporarily remove running instances from memory and restore them later.

20.1. Configuring safe points

To allow persistence, add the jbpm-persistence JAR files to the classpath of your application and configure the process engine to use persistence. The process engine automatically stores the runtime state in the storage when the process engine reaches a safe point.

Safe points are points where the process instance has paused. When a process instance invocation reaches a safe point in the process engine, the process engine stores any changes to the process instance as a snapshot of the process runtime data. However, when a process instance is completed, the persisted snapshot of process instance runtime data is automatically deleted.

BPMN2 safe point nodes ensure that the process engine saves the state of the process definition at the point where the execution stops and the transaction is committed. The following BPMN2 nodes are considered safe points:

  • All intermediate CATCH events

    • Timer Intermediate event
    • Error Intermediate event
    • Conditional Intermediate event
    • Compensation Intermediate event
    • Signal Intermediate event
    • Escalation Intermediate event
    • Message Intermediate event
  • User tasks
  • Custom (defined by the user) service tasks that do not complete the task in the handler

If a failure occurs and you need to restore the process engine runtime from the storage, the process instances are automatically restored and their execution resumes so there is no need to reload and trigger the process instances manually.

Consider the runtime persistence data to be internal to the process engine. You should not access persisted runtime data or modify them directly because this might have unexpected side effects.

For more information about the current execution state, refer to the history log. Query the database for runtime data only if absolutely necessary.

20.2. Session persistence entities

Sessions are persisted as SessionInfo entities. These persist the state of the runtime KIE session, and store the following data:

Table 20.1. SessionInfo

FieldDescriptionNullable

id

The primary key.

NOT NULL

lastModificationDate

The last time that entity was saved to a database.

 

rulesByteArray

The state of a session.

NOT NULL

startDate

The session start time.

 

OPTLOCK

A version field containing a lock value.

 

20.3. Process instance persistence entities

Process instances are persisted as ProcessInstanceInfo entities, which persist the state of a process instance on runtime and store the following data:

Table 20.2. ProcessInstanceInfo

FieldDescriptionNullable

instanceId

The primary key.

NOT NULL

lastModificationDate

The last time that the entity was saved to a database.

 

lastReadDate

The last time that the entity was retrieved from the database.

 

processId

The ID of the process.

 

processInstanceByteArray

The state of a process instance in form of a binary data set.

NOT NULL

startDate

The start time of the process.

 

state

An integer representing the state of a process instance.

NOT NULL

OPTLOCK

A version field containing a lock value.

 

ProcessInstanceInfo has a 1:N relationship to the EventTypes entity.

The EventTypes entity contains the following data:

Table 20.3. EventTypes

FieldDescriptionNullable

instanceId

A reference to the ProcessInstanceInfo primary key and foreign key constraint on this column.

NOT NULL

element

A finished event in the process.

 

20.4. Work item persistence entities

Work items are persisted as workiteminfo entities, which persist the state of the particular work item instance on runtime and store the following data:

Table 20.4. WorkItemInfo

FieldDescriptionNullable

workItemId

The primary key.

NOT NULL

name

The name of the work item.

 

processInstanceId

The (primary key) ID of the process. There is no foreign key constraint on this field.

NOT NULL

state

The state of a work item.

NOT NULL

OPTLOCK

A version field containing a lock value.

 

workitembytearay

The work item state in as a binary data set.

NOT NULL

20.5. Correlation key entities

The CorrelationKeyInfo entity contains information about the correlation key assigned to the given process instance. This table is optional. Use it only when you require correlation capabilities.

Table 20.5. CorrelationKeyInfo

FieldDescriptionNullable

keyId

The primary key.

NOT NULL

name

The assigned name of the correlation key.

 

processInstanceId

The ID of the process instance which is assigned to the correlation key.

NOT NULL

OPTLOCK

A version field containing a lock value.

 

The CorrelationPropertyInfo entity contains information about correlation properties for a correlation key assigned the process instance.

Table 20.6. CorrelationPropertyInfo

FieldDescriptionNullable

propertyId

The primary key.

NOT NULL

name

The name of the property.

 

value

The value of the property.

NOT NULL

OPTLOCK

A version field containing a lock value.

 

correlationKey_keyId

A foreign key mapped to the correlation key.

NOT NULL

20.6. Context mapping entity

The ContextMappingInfo entity contains information about the contextual information mapped to a KieSession. This is an internal part of RuntimeManager and can be considered optional when RuntimeManager is not used.

Table 20.7. ContextMappingInfo

FieldDescriptionNullable

mappingId

The primary key.

NOT NULL

CONTEXT_ID

The context identifier.

NOT NULL

KSESSION_ID

The KieSession identifier.

NOT NULL

OPTLOCK

A version field containing a lock value.

 

OWNER_ID

Holds the identifier of the deployment unit that the given mapping is associated with

 

20.7. Pessimistic Locking Support

The default locking mechanism for persistence of processes is optimistic. With multi-thread high concurrency to the same process instance, this locking strategy can result in bad performance.

This can be changed at runtime to allow the user to set locking on a per process basis and to allow it to be pessimistic (the change can be made at a per KIE Session level or Runtime Manager level as well and not just at the process level).

To set a process to use pessimistic locking, use the following configuration in the runtime environment:

import org.kie.api.runtime.Environment;
import org.kie.api.runtime.EnvironmentName;
import org.kie.api.runtime.manager.RuntimeManager;
import org.kie.api.runtime.manager.RuntimeManagerFactory;

...

env.set(EnvironmentName.USE_PESSIMISTIC_LOCKING, true);  1

RuntimeManager manager = RuntimeManagerFactory.Factory.get().newPerRequestRuntimeManager(environment);  2
1
env is an instance of org.kie.api.runtime.Environment.
2
Create your Runtime Manager by using this environment.

20.8. Persisting process variables in a separate database schema in Red Hat Process Automation Manager

When you create process variables in Red Hat Process Automation Manager to use within the processes that you define, Red Hat Process Automation Manager stores those process variables as binary data in a default database schema. You can persist process variables in a separate database schema for greater flexibility in maintaining and implementing your process data.

For example, persisting your process variables in a separate database schema can help you perform the following tasks:

  • Maintain process variables in human-readable format
  • Make the variables available to services outside of Red Hat Process Automation Manager
  • Clear the log of the default database tables in Red Hat Process Automation Manager without losing process variable data
Note

This procedure applies to process variables only. This procedure does not apply to case variables.

Prerequisites

  • You have defined processes in Red Hat Process Automation Manager for which you want to implement variables.
  • If you want to persist variables in a database schema outside of Red Hat Process Automation Manager, you have created a data source and the separate database schema that you want to use. For information about creating data sources, see Configuring Business Central settings and properties.

Procedure

  1. In the data object file that you use as a process variable, add the following elements to configure variable persistence:

    Example Person.java object configured for variable persistence

    @javax.persistence.Entity  1
    @javax.persistence.Table(name = "Person")  2
    public class Person extends org.drools.persistence.jpa.marshaller.VariableEntity  3
    implements java.io.Serializable {  4
    
    	static final long serialVersionUID = 1L;
    
    	@javax.persistence.GeneratedValue(strategy = javax.persistence.GenerationType.AUTO, generator = "PERSON_ID_GENERATOR")
    	@javax.persistence.Id  5
    	@javax.persistence.SequenceGenerator(name = "PERSON_ID_GENERATOR", sequenceName = "PERSON_ID_SEQ")
    	private java.lang.Long id;
    
    	private java.lang.String name;
    
    	private java.lang.Integer age;
    
    	public Person() {
    	}
    
    	public java.lang.Long getId() {
    		return this.id;
    	}
    
    	public void setId(java.lang.Long id) {
    		this.id = id;
    	}
    
    	public java.lang.String getName() {
    		return this.name;
    	}
    
    	public void setName(java.lang.String name) {
    		this.name = name;
    	}
    
    	public java.lang.Integer getAge() {
    		return this.age;
    	}
    
    	public void setAge(java.lang.Integer age) {
    		this.age = age;
    	}
    
    	public Person(java.lang.Long id, java.lang.String name,
    			java.lang.Integer age) {
    		this.id = id;
    		this.name = name;
    		this.age = age;
    	}
    
    }

    1
    Configures the data object as a persistence entity.
    2
    Defines the database table name used for the data object.
    3
    Creates a separate MappedVariable mapping table that maintains the relationship between this data object and the associated process instance. If you do not need this relationship maintained, you do not need to extend the VariableEntity class. Without this extension, the data object is still persisted, but contains no additional data.
    4
    Configures the data object as a serializable object.
    5
    Sets a persistence ID for the object.

    To make the data object persistable using Business Central, navigate to the data object file in your project, click the Persistence icon in the upper-right corner of the window, and configure the persistence behavior:

    Figure 20.1. Persistence configuration in Business Central

    persistence in central
  2. In the pom.xml file of your project, add the following dependency for persistence support. This dependency contains the VariableEntity class that you configured in your data object.

    Project dependency for persistence

    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-persistence-jpa</artifactId>
      <version>${rhpam.version}</version>
      <scope>provided</scope>
    </dependency>

  3. In the ~/META-INF/kie-deployment-descriptor.xml file of your project, configure the JPA marshalling strategy and a persistence unit to be used with the marshaller. The JPA marshalling strategy and persistence unit are required for objects defined as entities.

    JPA marshaller and persistence unit configured in the kie-deployment-descriptor.xml file

    <marshalling-strategy>
      <resolver>mvel</resolver>
      <identifier>new org.drools.persistence.jpa.marshaller.JPAPlaceholderResolverStrategy("myPersistenceUnit", classLoader)</identifier>
      <parameters/>
    </marshalling-strategy>

  4. In the ~/META-INF directory of your project, create a persistence.xml file that specifies in which data source you want to persist the process variable:

    Example persistence.xml file with data source configuration

    <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:orm="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd">
        <persistence-unit name="myPersistenceUnit" transaction-type="JTA">
            <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
            <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>  1
            <class>org.space.example.Person</class>
            <exclude-unlisted-classes>true</exclude-unlisted-classes>
            <properties>
                <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
                <property name="hibernate.max_fetch_depth" value="3"/>
                <property name="hibernate.hbm2ddl.auto" value="update"/>
                <property name="hibernate.show_sql" value="true"/>
                <property name="hibernate.id.new_generator_mappings" value="false"/>
                <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform"/>
            </properties>
        </persistence-unit>
    </persistence>

    1
    Sets the data source in which the process variable is persisted

    To configure the marshalling strategy, persistence unit, and data source using Business Central, navigate to project SettingsDeploymentsMarshalling Strategies and to project SettingsPersistence:

    Figure 20.2. JPA marshaller configuration in Business Central

    jpa marhsalling strategy

    Figure 20.3. Persistence unit and data source configuration in Business Central

    persistence unit