68.3. 与 Spring 集成
虽然可以通过几种方式将流程引擎与 Spring 框架一起使用,但最常使用两种方法
- 直接使用 Runtime Manager API
- 使用进程引擎服务
这两种方法都经过测试并有效。
如果您的应用程序只需要使用一个运行时管理器,请使用直接运行时管理器 API,因为这是在 Spring 应用程序中使用流程引擎的最简单方法。
如果您的应用程序需要使用运行时管理器的多个实例,请使用进程引擎服务,通过提供动态运行时环境来封装最佳实践。
68.3.1. 在 Spring 中直接使用运行时管理器 API
运行时管理器在同步过程中管理进程引擎和任务服务。有关运行时管理器的详情,请参考 第 66.2 节 “运行时管理器”。
Red Hat Process Automation Manager 不支持使用 Spring MVC 应用程序中的 EJB 计时器。
要在 Spring 框架中设置运行时管理器,请使用以下 factoryan:
-
org.kie.spring.factorybeans.RuntimeEnvironmentFactoryBean
-
org.kie.spring.factorybeans.RuntimeManagerFactoryBean
-
org.kie.spring.factorybeans.TaskServiceFactoryBean
这些 factoryan 提供了一种标准方法来为您的 Spring 应用程序配置 spring.xml
文件。
68.3.1.1. RuntimeEnvironmentFactoryBean
bean
RuntimeEnvironmentFactoryBean
工厂 bean 生成 RuntimeEnvironment
的实例。创建 RuntimeManager
实例需要这些实例。
bean 支持创建带有不同默认配置的以下 RuntimeEnvironment
实例类型:
-
DEFAULT
:运行时管理器的默认设置或最常用的配置 -
EMPTY
:您可以手动配置完全空环境 -
DEFAULT_IN_MEMORY
:与 DEFAULT 相同的配置,但没有运行时引擎的持久性 -
DEFAULT_KJAR
:与 DEFAULT 相同的配置,但资产从 KJAR 工件(由发行版本 ID 或 GAV 值标识)中加载 -
DEFAULT_KJAR_CL
:配置基于 KJAR 构件中的kmodule.xml
描述符构建
必要属性取决于所选的类型。但是,所有类型都必须显示相关信息。这个要求意味着必须提供以下信息之一:
-
knowledgeBase
-
资产
-
releaseId
-
GroupId, artifactId, version
对于 DEFAULT
、DEFAULT_KJAR
和 DEFAULT_KJAR_CL
类型,还必须通过提供以下参数来配置持久性:
- 实体管理器工厂
- 事务管理器
事务管理器必须是 Spring 事务管理器,因为基于此事务管理器对持久性和事务支持进行配置。
另外,您还可以提供一个 EntityManager
实例,而不是从 EntityManagerFactory
创建新实例,例如,您可以使用 Spring 的共享实体管理器。
所有其他属性都是可选的。它们可以覆盖由所选运行时环境类型决定的默认值。
68.3.1.2. RuntimeManageronnectionFactoryyBean
bean
RuntimeManagerFactoryBean
factoryan 根据提供的 RuntimeEnvironment
实例生成给定类型的 RuntimeManager
实例。
支持的类型与运行时管理器策略对应:
-
单例
-
PER_REQUEST
-
PER_PROCESS_INSTANCE
如果没有指定类型,默认类型是 SINGLETON
。
标识符是一个强制属性,因为每个运行时管理器都必须唯一标识。此工厂创建的所有实例都会被缓存,因此可以使用 destroy 方法正确处理它们(关闭()
)。
68.3.1.3. TaskServiceFactoryBean
an
TaskServiceFactoryBean
factoryan 根据给定属性生成 TaskService
实例。您必须提供以下强制属性:
- 实体管理器工厂
- 事务管理器
事务管理器必须是 Spring 事务管理器,因为基于此事务管理器对持久性和事务支持进行配置。
另外,您还可以提供一个 EntityManager
实例,而不是从 EntityManagerFactory
创建新实例,例如,您可以使用 Spring 的共享实体管理器。
您还可以为任务服务实例设置额外的可选属性:
-
userGroupCallback
:任务服务必须使用的UserGroupCallback
的实施,默认值为MVELUserGroupCallbackImpl
-
UserInfo
:任务服务必须使用的 UserInfo 实施,默认值为DefaultUserInfo
-
侦听器
:TaskLifeCycleEventListener
监听器列表,必须在各种任务中获得通知
此 factoryan 创建任务服务的一个实例。按照设计,此实例必须在 Spring 环境中的所有 Bean 中共享。
68.3.1.4. 使用 Spring 应用程序配置示例运行时管理器
以下流程是 Spring 应用程序中的一个运行时管理器的完整配置示例。
流程
配置实体管理器工厂和事务管理器:
在
spring.xml
文件中配置实体管理器工厂和事务管理器<bean id="jbpmEMF" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="org.jbpm.persistence.spring.jta"/> </bean> <bean id="jbpmEM" class="org.springframework.orm.jpa.support.SharedEntityManagerBean"> <property name="entityManagerFactory" ref="jbpmEMF"/> </bean> <bean id="narayanaUserTransaction" factory-method="userTransaction" class="com.arjuna.ats.jta.UserTransaction" /> <bean id="narayanaTransactionManager" factory-method="transactionManager" class="com.arjuna.ats.jta.TransactionManager" /> <bean id="jbpmTxManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManager" ref="narayanaTransactionManager" /> <property name="userTransaction" ref="narayanaUserTransaction" /> </bean>
这些设置定义了以下持久性配置:
- JTA 事务管理器(由 Narayana JTA 提供支持,用于单元测试或 servlet 容器)
-
org.jbpm.persistence.spring.jta
persistence 单元的实体管理器工厂
配置业务流程资源:
在
spring.xml
文件中配置业务流程资源<bean id="process" factory-method="newClassPathResource" class="org.kie.internal.io.ResourceFactory"> <constructor-arg> <value>jbpm/processes/sample.bpmn</value> </constructor-arg> </bean>
这些设置定义可用于执行的单个进程。资源名称是
sample.bpmn
,它必须在类路径上可用。您可以将类路径用作包含尝试进程引擎的资源的简单方法。使用实体管理器、事务管理器和资源配置
RuntimeEnvironment
实例:在
spring.xml
文件中配置RuntimeEnvironment
实例<bean id="runtimeEnvironment" class="org.kie.spring.factorybeans.RuntimeEnvironmentFactoryBean"> <property name="type" value="DEFAULT"/> <property name="entityManagerFactory" ref="jbpmEMF"/> <property name="transactionManager" ref="jbpmTxManager"/> <property name="assets"> <map> <entry key-ref="process"><util:constant static-field="org.kie.api.io.ResourceType.BPMN2"/></entry> </map> </property> </bean>
这些设置定义了运行时管理器的默认运行时环境。
根据环境创建一个
RuntimeManager
实例:<bean id="runtimeManager" class="org.kie.spring.factorybeans.RuntimeManagerFactoryBean" destroy-method="close"> <property name="identifier" value="spring-rm"/> <property name="runtimeEnvironment" ref="runtimeEnvironment"/> </bean>
结果
在这些步骤后,您可以使用运行时管理器使用实体管理器和 JTA 事务管理器在 Spring 环境中执行进程。
您可以在 存储库 中找到针对不同策略的完整 Spring 配置文件。
68.3.1.5. Spring 框架中的运行时管理器的额外配置选项
除了使用 EntityManagerFactory
类和 JTA 事务管理器的配置外,如 第 68.3.1.4 节 “使用 Spring 应用程序配置示例运行时管理器” 所述,您还可以使用 Spring 框架中的运行时管理器的其他配置选项:
-
JTA 和
SharedEntityManager
类 -
本地持久性单元和
实体管理器工厂
类 -
本地持久性单元和
SharedEntityManager
类
如果您的应用程序配置了本地持久性单元,并使用 AuditService
服务查询进程引擎历史记录数据,您必须将 org.kie.api.runtime.EnvironmentName.USE_LOCAL_TRANSACTIONS
环境条目添加到 RuntimeEnvironment
实例配置:
spring.xml
文件中为本地持久性单元的 RuntimeEnvironment
实例配置
<bean id="runtimeEnvironment" class="org.kie.spring.factorybeans.RuntimeEnvironmentFactoryBean"> ... <property name="environmentEntries" ref="env" /> </bean> ... <util:map id="env" key-type="java.lang.String" value-type="java.lang.Object"> <entry> <key> <util:constant static-field="org.kie.api.runtime.EnvironmentName.USE_LOCAL_TRANSACTIONS" /> </key> <value>true</value> </entry> </util:map>
68.3.2. 使用 Spring 处理引擎服务
您可能想要创建一个动态的 Spring 应用程序,您可以在不重启应用程序的情况下添加和删除业务资产,如流程定义、数据模型、规则和表单。
在这种情况下,使用流程引擎服务。进程引擎服务被设计为与框架无关,单独的模块可在所需框架的附加中实现。
jbpm-kie-services
模块包含服务的代码逻辑。Spring 应用程序可以使用这些纯 Java 服务。
您必须在 Spring 应用程序中添加的唯一代码来配置流程引擎服务,这是 IdentityProvider
接口的实现。这种实现取决于您的安全配置。以下实现示例使用 Spring Security,但可能没有涵盖 Spring 应用程序的所有可用安全功能。
使用 Spring Security 实施 IdentityProvider
接口
import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.kie.internal.identity.IdentityProvider; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; public class SpringSecurityIdentityProvider implements IdentityProvider { public String getName() { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null && auth.isAuthenticated()) { return auth.getName(); } return "system"; } public List<String> getRoles() { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null && auth.isAuthenticated()) { List<String> roles = new ArrayList<String>(); for (GrantedAuthority ga : auth.getAuthorities()) { roles.add(ga.getAuthority()); } return roles; } return Collections.emptyList(); } public boolean hasRole(String role) { return false; } }
68.3.2.1. 使用 Spring 应用程序配置流程引擎服务
以下流程是 Spring 应用程序内处理引擎服务的完整配置示例。
流程
配置转换:
在
spring.xml
文件中配置事务<context:annotation-config /> <tx:annotation-driven /> <tx:jta-transaction-manager /> <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
配置 JPA 和持久性:
在
spring.xml
文件中配置 JPA 和持久性<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" depends-on="transactionManager"> <property name="persistenceXmlLocation" value="classpath:/META-INF/jbpm-persistence.xml" /> </bean>
配置安全性和用户和组群信息供应商:
在
spring.xml
文件中配置安全性和组信息提供程序<util:properties id="roleProperties" location="classpath:/roles.properties" /> <bean id="userGroupCallback" class="org.jbpm.services.task.identity.JBossUserGroupCallbackImpl"> <constructor-arg name="userGroups" ref="roleProperties"></constructor-arg> </bean> <bean id="identityProvider" class="org.jbpm.spring.SpringSecurityIdentityProvider"/>
配置运行时管理器工厂。这个因素是 Spring 上下文了解,因此它能够以正确的方式与 Spring 容器交互,并支持必要的服务,包括事务命令服务和任务服务:
在
spring.xml
文件中配置运行时管理器工厂<bean id="runtimeManagerFactory" class="org.kie.spring.manager.SpringRuntimeManagerFactoryImpl"> <property name="transactionManager" ref="transactionManager"/> <property name="userGroupCallback" ref="userGroupCallback"/> </bean> <bean id="transactionCmdService" class="org.jbpm.shared.services.impl.TransactionalCommandService"> <constructor-arg name="emf" ref="entityManagerFactory"></constructor-arg> </bean> <bean id="taskService" class="org.kie.spring.factorybeans.TaskServiceFactoryBean" destroy-method="close"> <property name="entityManagerFactory" ref="entityManagerFactory"/> <property name="transactionManager" ref="transactionManager"/> <property name="userGroupCallback" ref="userGroupCallback"/> <property name="listeners"> <list> <bean class="org.jbpm.services.task.audit.JPATaskLifeCycleEventListener"> <constructor-arg value="true"/> </bean> </list> </property> </bean>
将流程引擎服务配置为 Spring Bean:
在
spring.xml
文件中将进程引擎服务配置为 Spring Bean<!-- Definition service --> <bean id="definitionService" class="org.jbpm.kie.services.impl.bpmn2.BPMN2DataServiceImpl"/> <!-- Runtime data service --> <bean id="runtimeDataService" class="org.jbpm.kie.services.impl.RuntimeDataServiceImpl"> <property name="commandService" ref="transactionCmdService"/> <property name="identityProvider" ref="identityProvider"/> <property name="taskService" ref="taskService"/> </bean> <!-- Deployment service --> <bean id="deploymentService" class="org.jbpm.kie.services.impl.KModuleDeploymentService" depends-on="entityManagerFactory" init-method="onInit"> <property name="bpmn2Service" ref="definitionService"/> <property name="emf" ref="entityManagerFactory"/> <property name="managerFactory" ref="runtimeManagerFactory"/> <property name="identityProvider" ref="identityProvider"/> <property name="runtimeDataService" ref="runtimeDataService"/> </bean> <!-- Process service --> <bean id="processService" class="org.jbpm.kie.services.impl.ProcessServiceImpl" depends-on="deploymentService"> <property name="dataService" ref="runtimeDataService"/> <property name="deploymentService" ref="deploymentService"/> </bean> <!-- User task service --> <bean id="userTaskService" class="org.jbpm.kie.services.impl.UserTaskServiceImpl" depends-on="deploymentService"> <property name="dataService" ref="runtimeDataService"/> <property name="deploymentService" ref="deploymentService"/> </bean> <!-- Register the runtime data service as a listener on the deployment service so it can receive notification about deployed and undeployed units --> <bean id="data" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" depends-on="deploymentService"> <property name="targetObject" ref="deploymentService"></property> <property name="targetMethod"><value>addListener</value></property> <property name="arguments"> <list> <ref bean="runtimeDataService"/> </list> </property> </bean>
结果
您的 Spring 应用程序可以使用流程引擎服务。