Chapter 17. Persistence
Chapter 17. 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. 17.1. Configuring KIE Server persistence You can configure the KIE Server persistence by passing Hibernate or JPA parameters as system properties. The KIE Server can acknowledge the system properties with the following prefixes and you can use every Hibernate or JPA parameters with these prefixes: javax.persistence hibernate Procedure To configure KIE Server persistence, complete any of the following tasks: If you want to configure KIE Server persistence using Red Hat JBoss EAP configuration file, complete the following tasks: In your Red Hat Process Automation Manager installation directory, navigate to the standalone-full.xml file. For example, if you use Red Hat JBoss EAP installation for Red Hat Process Automation Manager, go to USDEAP_HOME/standalone/configuration/standalone-full.xml file. Open the standalone-full.xml file and under the <system-properties> tag, set your Hibernate or JPA parameters as system properties. Example of configuring KIE Server persistence using Hibernate parameters <system-properties> ... <property name="hibernate.hbm2ddl.auto" value="create-drop"/> ... <system-properties> Example of configuring KIE Server persistence using JPA parameters <system-properties> ... <property name="javax.persistence.jdbc.url" value="jdbc:mysql://mysql.db.server:3306/my_database?useSSL=false&serverTimezone=UTC"/> ... <system-properties> If you want to configure KIE Server persistence using command line, complete the following tasks: Pass the parameters directly from the command line using -Dkey=value as follows: Example of configuring KIE Server persistence using Hibernate parameters: Example of configuring KIE Server persistence using JPA parameters: 17.2. 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. 17.3. Session persistence entities Sessions are persisted as SessionInfo entities. These persist the state of the runtime KIE session, and store the following data: Table 17.1. SessionInfo Field Description Nullable 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. 17.4. 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 17.2. ProcessInstanceInfo Field Description Nullable 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 17.3. EventTypes Field Description Nullable instanceId A reference to the ProcessInstanceInfo primary key and foreign key constraint on this column. NOT NULL element A finished event in the process. 17.5. 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 17.4. WorkItemInfo Field Description Nullable 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 17.6. 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 17.5. CorrelationKeyInfo Field Description Nullable 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 to the process instance. Table 17.6. CorrelationPropertyInfo Field Description Nullable 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 17.7. 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 17.7. ContextMappingInfo Field Description Nullable 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 17.8. 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. 17.8.1. Configuring pessimistic locking support via code You can set the locking mechanism on a per process basis and to allow it to be pessimistic . You can make the changes 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: 1 env is an instance of org.kie.api.runtime.Environment . 2 Create your Runtime Manager by using this environment. 17.8.2. Configuring pessimistic locking support in Business Central Business Central supports pessimistic locking of processes. To set a process to use pessimistic locking in Business Central, use the following procedure: Prerequisites You have sufficient user permissions in Business Central. You have created a Business Central project. Procedure In Business Central, go to Menu Design Projects . Select your project. Click Settings tab to access the project settings. Go to Deployments Environment entries . Click Add Environment Entry . To add environment entries, enter the following values: Name : Enter your environment name. Value : Enter your environment value. Resolver type : Select the MVEL, Reflection, or Spring resolver type as per your requirement. Parameters : Add the parameters. Click Save and click Save again to confirm your changes. 17.9. Persisting process variables in a separate database schema in Red Hat Process Automation Manager When you create process variables 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 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 17.1. Persistence configuration in Business Central 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>USD{rhpam.version}</version> <scope>provided</scope> </dependency> 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> 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 Settings Deployments Marshalling Strategies and to project Settings Persistence : Figure 17.2. JPA marshaller configuration in Business Central Figure 17.3. Persistence unit and data source configuration in Business Central
<system-properties> <property name="hibernate.hbm2ddl.auto" value="create-drop"/> <system-properties> <system-properties> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://mysql.db.server:3306/my_database?useSSL=false&serverTimezone=UTC"/> <system-properties> USDEAP_HOME/bin/standalone.sh -Dhibernate.hbm2ddl.auto=create-drop USDEAP_HOME/bin/standalone.sh -Djavax.persistence.jdbc.url=jdbc:mysql://mysql.db.server:3306/my_database?useSSL=false&serverTimezone=UTC 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 @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; } } <dependency> <groupId>org.drools</groupId> <artifactId>drools-persistence-jpa</artifactId> <version>USD{rhpam.version}</version> <scope>provided</scope> </dependency> <marshalling-strategy> <resolver>mvel</resolver> <identifier>new org.drools.persistence.jpa.marshaller.JPAPlaceholderResolverStrategy("myPersistenceUnit", classLoader)</identifier> <parameters/> </marshalling-strategy> <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>