如何将JBPM 7.74流程实例及KieSession持久化到数据库,实现Spring Boot启动时恢复
Spring Boot 3 + JBPM 7.74 持久化KieSession并恢复未完成流程实例
针对你在Spring Boot 3中嵌入JBPM 7.74,需要持久化KieSession到数据库并重启后恢复未完成流程的需求,以下是具体实现步骤:
1. 配置Maven依赖
确保你的pom.xml包含JBPM Spring Boot Starter、Spring Data JPA及数据库驱动:
<dependencies> <!-- JBPM Spring Boot Starter --> <dependency> <groupId>org.jbpm</groupId> <artifactId>jbpm-spring-boot-starter</artifactId> <version>7.74.0.Final</version> </dependency> <!-- Spring Data JPA --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- MySQL驱动(根据你的数据库调整) --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> </dependencies>
2. 配置数据源与JBPM持久化
在application.properties中配置数据库连接及JBPM持久化参数:
# 数据库配置 spring.datasource.url=jdbc:mysql://localhost:3306/jbpm_db?useSSL=false&serverTimezone=UTC&createDatabaseIfNotExist=true spring.datasource.username=root spring.datasource.password=your_password spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # JPA配置 spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect # JBPM持久化配置 jbpm.persistence.enabled=true jbpm.session.persistence.enabled=true jbpm.persistence.dialect=org.hibernate.dialect.MySQL8Dialect
3. 创建持久化的StatefulKieSession
编写配置类生成支持持久化的KieSession(必须用StatefulKieSession,StatelessKieSession不支持持久化):
import org.kie.api.KieBase; import org.kie.api.KieServices; import org.kie.api.runtime.KieSession; import org.kie.internal.persistence.jpa.JPAKnowledgeService; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; import jakarta.persistence.EntityManagerFactory; @Configuration @EnableTransactionManagement public class JbpmConfig { private final EntityManagerFactory entityManagerFactory; public JbpmConfig(EntityManagerFactory entityManagerFactory) { this.entityManagerFactory = entityManagerFactory; } @Bean public KieSession kieSession() { KieServices kieServices = KieServices.Factory.get(); KieBase kieBase = kieServices.getKieClasspathContainer().getKieBase(); // 构建持久化环境,绑定EntityManagerFactory和事务管理器 var environment = new java.util.HashMap<String, Object>(); environment.put(org.kie.api.runtime.EnvironmentName.ENTITY_MANAGER_FACTORY, entityManagerFactory); environment.put(org.kie.api.runtime.EnvironmentName.TRANSACTION_MANAGER, org.springframework.transaction.support.TransactionSynchronizationManager.getResourceTransactionManager()); // 创建持久化的StatefulKieSession KieSession kieSession = JPAKnowledgeService.newStatefulKnowledgeSession(kieBase, null, environment); // 注册工作项处理器(示例为人工任务处理器,根据你的流程调整) kieSession.getWorkItemManager().registerWorkItemHandler("Human Task", new org.jbpm.process.workitem.core.AbstractLogOrThrowWorkItemHandler()); return kieSession; } }
4. 启动流程实例(自动持久化)
在业务服务中注入KieSession,启动流程时添加@Transactional注解确保持久化生效:
import org.kie.api.runtime.KieSession; import org.kie.api.runtime.process.ProcessInstance; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class ProcessService { private final KieSession kieSession; public ProcessService(KieSession kieSession) { this.kieSession = kieSession; } @Transactional public Long startProcess(String processId) { ProcessInstance processInstance = kieSession.startProcess(processId); // 流程实例启动后会自动持久化到数据库,返回实例ID用于后续操作 return processInstance.getId(); } }
5. 应用重启后恢复未完成流程
编写恢复服务,在应用启动时加载所有未完成的流程实例:
import org.kie.api.KieBase; import org.kie.api.KieServices; import org.kie.api.runtime.KieSession; import org.kie.api.runtime.process.ProcessInstance; import org.kie.internal.persistence.jpa.JPAKnowledgeService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import jakarta.persistence.EntityManagerFactory; import java.util.List; @Service public class ProcessRecoveryService { private final EntityManagerFactory entityManagerFactory; private final KieBase kieBase; public ProcessRecoveryService(EntityManagerFactory entityManagerFactory, KieBase kieBase) { this.entityManagerFactory = entityManagerFactory; this.kieBase = kieBase; } @Transactional public void recoverUnfinishedProcesses() { KieServices kieServices = KieServices.Factory.get(); // 查询所有处于活跃状态的未完成流程实例 List<Long> activeProcessIds = kieServices.getStoreServices() .findProcessInstances(null, List.of(ProcessInstance.STATE_ACTIVE), null, null) .stream() .map(ProcessInstance::getId) .toList(); for (Long processId : activeProcessIds) { // 加载对应流程实例的KieSession var environment = new java.util.HashMap<String, Object>(); environment.put(org.kie.api.runtime.EnvironmentName.ENTITY_MANAGER_FACTORY, entityManagerFactory); environment.put(org.kie.api.runtime.EnvironmentName.TRANSACTION_MANAGER, org.springframework.transaction.support.TransactionSynchronizationManager.getResourceTransactionManager()); KieSession kieSession = JPAKnowledgeService.loadStatefulKnowledgeSession(processId, kieBase, null, environment); // 若流程处于等待外部信号的状态,可在此触发信号继续执行 // kieSession.signalEvent("triggerSignal", null); } } }
在Spring Boot启动类中调用恢复方法:
import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; @SpringBootApplication public class JbpmApplication { public static void main(String[] args) { SpringApplication.run(JbpmApplication.class, args); } @Bean CommandLineRunner initRecovery(ProcessRecoveryService recoveryService) { return args -> recoveryService.recoverUnfinishedProcesses(); } }
关键注意事项
- 所有操作流程的方法必须添加
@Transactional,否则持久化操作不会提交到数据库 - 确保数据库使用支持事务的存储引擎(如MySQL的InnoDB)
- 首次启动后,可将
spring.jpa.hibernate.ddl-auto改为validate,避免意外修改表结构 - 若流程包含人工任务,JBPM会自动持久化任务数据,重启后可通过任务服务查询并继续处理
- 不要使用
StatelessKieSession,它仅支持一次性流程执行,不支持持久化和状态恢复
内容的提问来源于stack exchange,提问作者Ajinkya Khedkar
相关产品推荐
相关产品推荐

