搜索

67.3. 进程引擎中的事务

download PDF

流程引擎支持 Java 事务 API(JTA)事务。

进程引擎的当前版本不支持纯本地事务。

如果没有在应用程序内提供事务界限,流程引擎会在一个单独的事务中对进程引擎执行每个方法调用。

另外,您可以在应用程序代码中指定事务界限,例如,将多个命令合并到一个事务中。

67.3.1. 注册事务管理器

您必须在环境中注册事务管理器才能使用用户定义的事务。

以下示例代码注册事务管理器并使用 JTA 调用来指定事务边界。

注册事务管理器和使用事务

// Create the entity manager factory
EntityManagerFactory emf = EntityManagerFactoryManager.get().getOrCreate("org.jbpm.persistence.jpa");
TransactionManager tm = TransactionManagerServices.getTransactionManager();

// Set up the runtime environment
RuntimeEnvironment environment = RuntimeEnvironmentBuilder.Factory.get()
.newDefaultBuilder()
.addAsset(ResourceFactory.newClassPathResource("MyProcessDefinition.bpmn2"), ResourceType.BPMN2)
    .addEnvironmentEntry(EnvironmentName.TRANSACTION_MANAGER, tm)
    .get();

// Get the KIE session
RuntimeManager manager = RuntimeManagerFactory.Factory.get().newPerRequestRuntimeManager(environment);
RuntimeEngine runtime = manager.getRuntimeEngine(ProcessInstanceIdContext.get());
KieSession ksession = runtime.getKieSession();

// Start the transaction
UserTransaction ut = InitialContext.doLookup("java:comp/UserTransaction");
ut.begin();

// Perform multiple commands inside one transaction
ksession.insert( new Person( "John Doe" ) );
ksession.startProcess("MyProcess");

// Commit the transaction
ut.commit();

您必须在 root 类路径中提供 jndi.properties 文件,以创建 JNDI InitialContextonnectionFactoryy 对象,因为与事务相关的对象(如 UserTransactionTransactionManagerTransactionSynchronizationRegistry )在 JNDI 中注册。

如果您的项目包含 jbpm-test 模块,则默认已包含此文件。

否则,您必须使用以下内容创建 jndi.properties 文件:

jndi.properties 文件的内容

java.naming.factory.initial=org.jbpm.test.util.CloseSafeMemoryContextFactory
org.osjava.sj.root=target/test-classes/config
org.osjava.jndi.delimiter=/
org.osjava.sj.jndi.shared=true

此配置假设 simple-jndi:simple-jndi 工件存在于项目的类路径中。您还可以使用不同的 JNDI 实现。

默认情况下会使用 Narayana JTA 事务管理器。如果要使用不同的 JTA 事务管理器,您可以更改 persistence.xml 文件以使用所需的事务管理器。例如,如果您的应用程序在红帽 JBoss EAP 7 或更高版本上运行,您可以使用 JBoss 事务管理器。在这种情况下,更改 persistence.xml 文件中的事务管理器属性:

JBoss 事务管理器的 persistence.xml 文件中的事务管理器属性

<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" />

警告

使用 RuntimeManager 类的 Singleton 策略与 JTA 事务(UserTransaction 或 CMT)的 Singleton 创建了一个竞争条件。这个竞争条件可能会导致 IllegalStateException 异常,与 进程实例 XXX 类似的消息是断开连接

要避免这种竞争条件,在用户应用程序代码中调用事务时,请明确同步 KieSession 实例。

synchronized (ksession) {
    try {
        tx.begin();

        // use ksession
        // application logic

        tx.commit();
    } catch (Exception e) {
        //...
    }
}

67.3.2. 配置容器管理事务

例如,如果您将进程引擎嵌入到由容器管理的事务(CMT)模式中执行的应用程序中,您必须完成额外的配置。如果应用程序在没有允许 CMT 应用从 JNDI 访问 UserTransaction 实例(例如,WebSphere Application)运行,则此配置尤为重要。

流程引擎中的默认事务管理器实施依赖于 UserTransaction 查询事务状态,然后使用该状态来确定是否启动事务。在阻止访问 UserTransaction 实例的环境中,此实施会失败。

要在 CMT 环境中启用正确执行,流程引擎提供一个专用的事务管理器实施: org.jbpm.persistence.jta.ContainerManagedTransactionManager。此事务管理器要求事务处于活动状态,并且始终在调用 getStatus() 方法时返回 ACTIVE开始提交和 回滚 等操作是 no-op 方法,因为事务管理器无法在容器管理的事务模式中影响这些操作。

注意

在执行代码的过程中,必须将引擎引发的任何例外传播到容器,以确保容器在必要时回滚事务。

要配置此事务管理器,请完成此流程中的步骤。

流程

  1. 在您的代码中,在创建或载入会话前将事务管理器和持久性上下文管理器插入到环境中:

    将事务管理器和持久性上下文管理器插入到环境中

    Environment env = EnvironmentFactory.newEnvironment();
    env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
    env.set(EnvironmentName.TRANSACTION_MANAGER, new ContainerManagedTransactionManager());
    env.set(EnvironmentName.PERSISTENCE_CONTEXT_MANAGER, new JpaProcessPersistenceContextManager(env));
    env.set(EnvironmentName.TASK_PERSISTENCE_CONTEXT_MANAGER, new JPATaskPersistenceContextManager(env));

  2. persistence.xml 文件中,配置 JPA 提供程序。以下示例使用 hibernate 和 WebSphere Application Server。

    persistence.xml 文件中配置 JPA 供应商

    <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>
    <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.WebSphereJtaPlatform"/>

  3. 要分散 KIE 会话,请不要直接选择它。相反,执行 org.jbpm.persistence.jta.ContainerManagedTransactionDisposeCommand 命令。此命令可确保会话在完成当前事务时被处理。在以下示例中,ksession 是您要处理的 KieSession 对象。

    使用 ContainerManagedTransactionDisposeCommand 命令执行 KIE 会话

    ksession.execute(new ContainerManagedTransactionDisposeCommand());

    直接调整会话会导致事务完成异常,因为进程引擎注册事务同步来清理会话状态。

67.3.3. 事务重试

当进程引擎提交事务时,有时提交操作会失败,因为同时提交另一个事务。在这种情况下,进程引擎必须重试事务。

如果多次重试失败,则事务会永久失败。

您可以使用 JVM 系统属性来控制重试进程。

表 67.8. 重试提交事务的系统属性
属性默认描述

org.kie.optlock.retries

整数

5

此属性描述了进程引擎永久重试事务的次数。

org.kie.optlock.delay

整数

50

第一次重试前的延迟时间(以毫秒为单位)。

org.kie.optlock.delayFactor

整数

4

每次后续重试增加延迟时间的倍数。使用默认值时,进程引擎在第一个重试前等待 50 毫秒,在第二个重试前等待 200 毫秒,即第三个重试前 800 毫秒,以此类推。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.