15.8. Runtime Manager
15.8.1. The RuntimeManager Interface
RuntimeManager interface simplifies and empowers the usage of knowledge API in context of processes. It provides configurable strategies that control actual runtime execution and by default provides following:
- Singleton:
RuntimeManagermaintains singleKieSessionregardless of number of processes available. - Per Request:
RuntimeManagerdelivers newKieSessionfor every request. - Per Process Instance:
RuntimeManagermaintains mapping between process instance andKieSessionand always provides sameKieSessionwhenever working with given process instance.
package org.kie.api.runtime.manager;
public interface RuntimeManager {
/**
* Returns <code>RuntimeEngine</code> instance that is fully initialized:
* KiseSession is created or loaded depending on the strategy
* TaskService is initialized and attached to ksession (via listener)
* WorkItemHandlers are initialized and registered on ksession
* EventListeners (process, agenda, working memory) are initialized and added to ksession
* @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.
* ksession.dispose() shall never be used with RuntimeManager as it will break the internal
* mechanisms of the manager responsible for clear and efficient disposal.<br/>
* Dispose is not needed if <code>RuntimeEngine</code> was obtained within active JTA transaction,
* this means that when getRuntimeEngine method was invoked during active JTA transaction then dispose of
* the runtime engine will happen automatically on transaction completion.
* @param runtime
*/
void disposeRuntimeEngine(RuntimeEngine runtime);
/**
* Closes <code>RuntimeManager</code> and releases its resources. Shall always be called when
* runtime manager is not needed any more. Otherwise it will still be active and operational.
*/
void close();
}
RuntimeManager is responsible for managing and delivering instances of RuntimeEngine to the caller. In turn, RuntimeEngine encapsulates two the most important elements of JBoss BPM Suite engine:
KieSessionTaskService
RuntimeManager ensures that regardless of the strategy, it will provide same capabilities when it comes to initialization and configuration of the RuntimeEngine. This means:
- KieSession will be loaded with same factories (either in memory or JPA based)
- WorkItemHandlers will be registered on every KieSession (either loaded from db or newly created)
- Event listeners (Process, Agenda, WorkingMemory) will be registered on every
KieSession(either loaded from db or newly created) TaskServicewill be configured with:- JTA transaction manager
- Same entity manager factory as for the
KieSession UserGroupCallbackfrom environment
RuntimeManager maintains the engine disposal by providing dedicated methods to dispose RuntimeEngine when it is no more required to release any resources it might have acquired.
15.8.2. The RuntimeEngine Interface
RuntimeEngine interface provides the following methods access the engine components:
public interface RuntimeEngine {
/**
* Returns <code>KieSession</code> configured for this <code>RuntimeEngine</code>
* @return
*/
KieSession getKieSession();
/**
* Returns <code>TaskService</code> configured for this <code>RuntimeEngine</code>
* @return
*/
TaskService getTaskService();
}15.8.3. Strategies
This instructs the RuntimeManager to maintain single instance of RuntimeEngine and in turn single instance of KieSession and TaskService. Access to the RuntimeEngine is synchronized and the thread is safe although it comes with a performance penalty due to synchronization. This strategy is similar to what was available by default in JBoss Enterprise BRMS Platform version 5.x and it is considered the easiest strategy and recommended to start with. It has the following characteristics:
- Small memory footprint, that is a single instance of runtime engine and task service.
- Simple and compact in design and usage.
- Good fit for low to medium load on process engine due to synchronized access.
- Due to single
KieSessioninstance, all state objects (such as facts) are directly visible to all process instances and vice versa. - Not contextual, that is when retrieving instances of
RuntimeEnginefrom singletonRuntimeManager, Context instance is not important and usually theEmptyContext.get()method is used, although null argument is acceptable as well. - Keeps track of the ID of the
KieSessionused betweenRuntimeManagerrestarts, to ensure it uses the same session. This ID is stored as serialized file on disc in a temporary location that depends on the environment.
This instructs the RuntimeManager to provide new instance of RuntimeEngine for every request. As the RuntimeManager request considers one or more invocations within single transaction. It must return same instance of RuntimeEngine within single transaction to ensure correctness of state as otherwise the operation in one call would not be visible in the other. This is sort of a stateless strategy that provides only request scope state. Once the request is completed, the RuntimeEngineis permanently destroyed. The KieSession informationis thene removed from the database in case you used persistence. It has following characteristics:
- Completely isolated process engine and task service operations for every request.
- Completely stateless, storing facts makes sense only for the duration of the request.
- A good fit for high load, stateless processes (no facts or timers involved that shall be preserved between requests).
KieSessionis only available during life time of request and at the end is destroyed- Not contextual, that is when retrieving instances of
RuntimeEnginefrom per requestRuntimeManager, Context instance is not important and usually theEmptyContext.get()method is used, although null argument is acceptable as well.
This instructs the RuntimeManager to maintain a strict relationship between KieSession and ProcessInstance. That means that the KieSession will be available as long as the ProcessInstance that it belongs to is active. This strategy provides the most flexible approach to use advanced capabilities of the engine like rule evaluation in isolation (for given process instance only). It provides maximum performance and reduction of potential bottlenecks introduced by synchronization. Additionally, it reduces number of KieSessions to the actual number of process instances, rather than number of requests (in contrast to per request strategy). It has the following characteristics:
- Most advanced strategy to provide isolation to given process instance only.
- Maintains strict relationship between
KieSessionandProcessInstanceto ensure it will always deliver sameKieSessionfor givenProcessInstance. - Merges life cycle of
KieSessionwithProcessInstancemaking both to be disposed on process instance completion (complete or abort). - Allows to maintain data (such as facts, timers) in scope of process instance, that is, only process instance will have access to that data.
- Introduces a bit of overhead due to need to look up and load
KieSessionfor process instance. - Validates usage of
KieSession, so it can not be used for other process instances. In such cases, an exception is thrown. - Is contextual. It accepts
EmptyContext,ProcessInstanceIdContext, andCorrelationKeyContextcontext instances.
15.8.4. Usage Scenario for RuntimeManager Interface
RuntimeManager is:
- At application startup
- Build the
RuntimeManagerand keep it for entire life time of the application. It is thread safe and you can access it concurrently.
- At request
- Get
RuntimeEnginefromRuntimeManagerusing proper context instance dedicated to strategy ofRuntimeManager. - Get
KieSessionorTaskServicefromRuntimeEngine. - Perform operations on
KieSessionorTaskServicesuch asstartProcessandcompleteTask. - Once done with processing, dispose
RuntimeEngineusing theRuntimeManager.disposeRuntimeEnginemethod.
- At application shutdown
- Close
RuntimeManager.
Note
RuntimeEngine is obtained from RuntimeManager within an active JTA transaction, then there is no need to dispose RuntimeEngine at the end, as it automatically disposes the RuntimeEngine on transaction completion (regardless of the completion status commit or rollback).
15.8.5. Building RuntimeManager
RuntimeManager and get RuntimeEngine (that encapsulates KieSession and TaskService) from it:
// first configure environment that will be used by RuntimeManager
RuntimeEnvironment environment = RuntimeEnvironmentBuilder.Factory.get()
.newDefaultInMemoryBuilder()
.addAsset(ResourceFactory.newClassPathResource("BPMN2-ScriptTask.bpmn2"), ResourceType.BPMN2)
.get();
// next create RuntimeManager - in this case singleton strategy is chosen
RuntimeManager manager = RuntimeManagerFactory.Factory.get().newSingletonRuntimeManager(environment);
// then get RuntimeEngine out of manager - using empty context as singleton does not keep track
// of runtime engine as there is only one
RuntimeEngine runtime = manager.getRuntimeEngine(EmptyContext.get());
// get KieSession from runtime runtimeEngine - already initialized with all handlers, listeners, etc that were configured
// on the environment
KieSession ksession = runtimeEngine.getKieSession();
// add invocations to the process engine here,
// e.g. ksession.startProcess(processId);
// and last dispose the runtime engine
manager.disposeRuntimeEngine(runtimeEngine);
15.8.6. RuntimeEnvironment Configuration
RuntimeEnvironment.
public interface RuntimeEnvironment {
/**
* Returns <code>KieBase</code> that shall be used by the manager
* @return
*/
KieBase getKieBase();
/**
* KieSession environment that shall be used to create instances of <code>KieSession</code>
* @return
*/
Environment getEnvironment();
/**
* KieSession configuration that shall be used to create instances of <code>KieSession</code>
* @return
*/
KieSessionConfiguration getConfiguration();
/**
* Indicates if persistence shall be used for the KieSession instances
* @return
*/
boolean usePersistence();
/**
* Delivers concrete implementation of <code>RegisterableItemsFactory</code> to obtain handlers and listeners
* that shall be registered on instances of <code>KieSession</code>
* @return
*/
RegisterableItemsFactory getRegisterableItemsFactory();
/**
* Delivers concrete implementation of <code>UserGroupCallback</code> that shall be registered on instances
* of <code>TaskService</code> for managing users and groups.
* @return
*/
UserGroupCallback getUserGroupCallback();
/**
* Delivers custom class loader that shall be used by the process engine and task service instances
* @return
*/
ClassLoader getClassLoader();
/**
* Closes the environment allowing to close all depending components such as ksession factories, etc
*/
void close();
15.8.7. Building RuntimeEnvironment
RuntimeEnvironment interface provides access to the data kept as part of the environment. You can use the builder style class that provides fluent API to configure RuntimeEnvironment with predefined settings:
package org.kie.api.runtime.manager;
public 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);
RuntimeEnvironmentBuilder via RuntimeEnvironmentBuilderFactory that provides preconfigured sets of builder to simplify and help you build the environment for the RuntimeManager.
public interface RuntimeEnvironmentBuilderFactory {
/**
* Provides completely empty <code>RuntimeEnvironmentBuilder</code> instance that allows 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:
* DefaultRuntimeEnvironment
* @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:
* DefaultRuntimeEnvironment
* but it does not have persistence for process 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:
* DefaultRuntimeEnvironment
* This one is tailored to works smoothly with kjars as the notion of kbase and ksessions
* @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:
* DefaultRuntimeEnvironment
* This one is tailored to works smoothly with kjars as the notion of kbase and ksessions
* @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:
* DefaultRuntimeEnvironment
* This one is tailored to works smoothly with kjars as the notion of kbase and ksessions
* @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:
* DefaultRuntimeEnvironment
* This one is tailored to works smoothly with kjars as the notion of kbase and ksessions
* @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:
* DefaultRuntimeEnvironment
* It relies on KieClasspathContainer that requires to have kmodule.xml present in 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:
* DefaultRuntimeEnvironment
* It relies on KieClasspathContainer that requires to have kmodule.xml present in 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);KieSession, Runtime Manager also provides access to TaskService. The default builder comes with predefined set of elements that consists of:
- Persistence unit name: It is set to
org.jbpm.persistence.jpa(for both process engine and task service). - Human Task handler: This is automatically registered on the
KieSession. - JPA based history log event listener: This is automatically registered on the
KieSession. - Event listener to trigger rule task evaluation (fireAllRules): This is automatically registered on the
KieSession.
15.8.8. Registering Handlers and Listeners through RegisterableItemsFactory
RegisterableItemsFactory provides you a dedicated mechanism to create your own handlers or listeners.
/**
* 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);RegisterableItemsFactory provides a mechanism to define custom handlers and listeners. Following is a list of available implementations ordered in the hierarchy of inheritance:
org.jbpm.runtime.manager.impl.SimpleRegisterableItemsFactory: This is the simplest possible implementation that comes empty and is based on a reflection to produce instances of handlers and listeners based on given class names.org.jbpm.runtime.manager.impl.DefaultRegisterableItemsFactory: This is an extension of the simple implementation(org.jbpm.runtime.manager.impl.SimpleRegisterableItemsFactory) that introduces defaults described above and still provides same capabilities as theorg.jbpm.runtime.manager.impl.SimpleRegisterableItemsFactoryimplementation.org.jbpm.runtime.manager.impl.KModuleRegisterableItemsFactory: This is an extension of the default implementation (org.jbpm.runtime.manager.impl.DefaultRegisterableItemsFactory) that provides specific capabilities for kmodule and still provides same capabilities as the Simple implementation (org.jbpm.runtime.manager.impl.SimpleRegisterableItemsFactory).org.jbpm.runtime.manager.impl.cdi.InjectableRegisterableItemsFactory: This is an extension of the default implementation (org.jbpm.runtime.manager.impl.DefaultRegisterableItemsFactory) that is tailored for CDI environments and provides CDI style approach to finding handlers and listeners through producers.
15.8.9. Registering Handlers through Configuration Files
KieSession) work item handlers by defining them as part of CustomWorkItem.conf file and update the class path. To use this approach do the following:
- Create a file called
drools.session.confinsideMETA-INFof the root of the class path (WEB-INF/classes/META-INFfor web applications). - Add the following line to the
drools.session.conf file:drools.workItemHandlers = CustomWorkItemHandlers.conf
- Create a file called
CustomWorkItemHandlers.confinsideMETA-INFof the root of the class path (WEB-INF/classes/META-INFfor web applications). - Define custom work item handlers in MVEL format inside the
CustomWorkItemHandlers.conffile:[ "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) ]
KieSession created by the application, regardless of it using the RuntimeManager or not.
15.8.10. Registering Handlers and Listeners in CDI Environment
RuntimeManager in a CDI environment, you can use the dedicated interfaces to provide custom WorkItemHandlers and EventListeners to the RuntimeEngine.
public interface WorkItemHandlerProducer {
/**
* Returns map of (key = work item name, value work item handler instance) of work items
* to be registered on KieSession
* Parameters that might be given are as follows:
* ksessiontaskService
* runtimeManager
* @param identifier - identifier of the owner - usually RuntimeManager that allows the producer to filter out
* and provide valid instances for given owner
* @param params - 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);
}- @Process for
ProcessEventListener - @Agenda for
AgendaEventListener - @WorkingMemory for
WorkingMemoryEventListener
public interface EventListenerProducer<T> {
/**
* Returns list of instances for given (T) type of listeners
* <br/>
* Parameters that might be given are as follows:
* ksession
* taskServiceruntimeManager
* @param identifier - identifier of the owner - usually RuntimeManager that allows the producer to filter out
* and provide valid instances for given owner
* @param params - 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);
}beans.xml inside META-INF folder and update the application classpath (for example, WEB-INF/lib for web application). This enables the CDI based RuntimeManager to discover them and register on every KieSession that is created or loaded from the data store.
KieSession, TaskService, and RuntimeManager) are provided to the producers to allow handlers or listeners to be more stateful and be able to do more advanced things with the engine. You can also apply filtering based on the identifier (that is given as argument to the methods) to decide if the given RuntimeManager can receive handlers or listeners or not.
Note
RuntimeManager and retrieve RuntimeEngine (and then KieSession or TaskService) from it as that ensures a proper state.
15.8.11. Control Parameters to Alter Default Engine Behavior
Table 15.18. Table Title
| Name | Possible Values | Default Value | Description |
|---|---|---|---|
jbpm.ut.jndi.lookup | String | Alternative JNDI name to be used when there is no access to the default one (java:comp/UserTransaction). | |
jbpm.enable.multi.con | true|false | false | Enables multiple incoming/outgoing sequence flows support for activities. |
jbpm.business.calendar.properties | String | /jbpm.business.calendar.properties | Allows to provide alternative classpath location of business calendar configuration file. |
jbpm.overdue.timer.delay | Long | 2000 | Specifies delay for overdue timers to allow proper initialization, in milliseconds. |
jbpm.process.name.comparator | String | Allows to provide alternative comparator class to empower start process by name feature. If not set, NumberVersionComparator is used. | |
jbpm.loop.level.disabled | true|false | true | Allows to enable or disable loop iteration tracking, to allow advanced loop support when using XOR gateways. |
org.kie.mail.session | String | mail/jbpmMailSession | Allows to provide alternative JNDI name for mail session used by Task Deadlines. |
jbpm.usergroup.callback.properties | String | /jbpm.usergroup.callback.properties | Allows to provide alternative classpath location for user group callback implementation (LDAP, DB). |
jbpm.user.group.mapping | String | ${jboss.server.config.dir}/roles.properties | Allows to provide alternative classpath location of user info configuration (used by LDAPUserInfoImpl). |
jbpm.user.info.properties | String | /jbpm.user.info.properties | Allows to provide alternative classpath location for user group callback implementation (LDAP, DB). |
org.jbpm.ht.user.separator | String | , | Allows to provide alternative separator of actors and groups for user tasks, default is comma (,). |
org.quartz.properties | String | Allows to provide location of the quartz config file to activate quartz based timer service. | |
jbpm.data.dir | String | ${jboss.server.data.dir} is available otherwise ${java.io.tmpdir} | Allows to provide location where data files produced by JBoss BPM Suite must be stored. |
org.kie.executor.pool.size | Integer | 1 | Allows to provide thread pool size for JBoss BPM Suite executor. |
org.kie.executor.retry.count | Integer | 3 | Allows to provide number of retries attempted in case of error by JBoss BPM Suite executor. |
org.kie.executor.interval | Integer | 3 | Allows to provide frequency used to check for pending jobs by JBoss BPM Suite executor, in seconds. |
org.kie.executor.disabled | true|false | true | Enables or disable JBoss BPM Suite executor. |
15.8.12. Storing Process Variables Without Serialization
Variable Persistence Strategy - that is, it uses serialization for objects that do implement the java.io.Serializable interface but uses the Java Persistence Architecture (JPA) based JPAPlaceholderResolverStrategy class to work on objects that are entities (not implementing the java.io.Serializable interface).
Configuring Variable Persistence Strategy
// create entity manager factory
EntityManagerFactory emf = Persistence.createEntityManagerFactory("com.redhat.sample");
RuntimeEnvironment environment = RuntimeEnvironmentBuilder.Factory.get().newDefaultBuilder()
.entityManagerFactory(emf)
.addEnvironmentEntry(EnvironmentName.OBJECT_MARSHALLING_STRATEGIES,
new ObjectMarshallingStrategy[] {
// set the entity manager factory to JPA strategy so it knows how to store and read entities
new JPAPlaceholderResolverStrategy(emf),
// set the serialization based strategy as last one to deal with non entity classes
new SerializablePlaceholderResolverStrategy(ClassObjectMarshallingStrategyAcceptor.DEFAULT)})
.addAsset(ResourceFactory.newClassPathResource("example.bpmn"), ResourceType.BPMN2)
.get();
// now create the runtime manager and start using entities as part of your process
RuntimeManager manager = RuntimeManagerFactory.Factory.get().newSingletonRuntimeManager(environment);
Note
persistence.xml configuration file that will be used by the JPA strategy.
How Does the JPA Strategy Work?
@Id annotation (javax.persistence.Id) This is the unique id that is used to retrieve the variable. On the other hand, a serialization based strategy simply accepts all variables by default.
marshal() method, while the unmarshal() method will retrieve the variable from the storage.
Creating Your Own Persistence Strategy
marshal() and unmarshal() objects. These methods are part of the org.kie.api.marshalling.ObjectMarshallingStrategy interface and you can implement this interface to create a custom persistence strategy.
public interface ObjectMarshallingStrategy {
public boolean accept(Object object);
public void write(ObjectOutputStream os,
Object object) throws IOException;
public Object read(ObjectInputStream os) throws IOException, ClassNotFoundException;
public byte[] marshal(Context context,
ObjectOutputStream os,
Object object ) throws IOException;
public Object unmarshal(Context context,
ObjectInputStream is,
byte[] object,
ClassLoader classloader ) throws IOException, ClassNotFoundException;
public Context createContext();
}
read() and write() are for backwards compatibility. Use the methods accept(), marshal() and unmarshal() to create your strategy.

Where did the comment section go?
Red Hat's documentation publication system recently went through an upgrade to enable speedier, more mobile-friendly content. We decided to re-evaluate our commenting platform to ensure that it meets your expectations and serves as an optimal feedback mechanism. During this redesign, we invite your input on providing feedback on Red Hat documentation via the discussion platform.