流程引擎API和服务
引擎API是与Activiti交互的最常见方式,中心起点是ProcessEngine
,可以按照配置部分中所述的几种方法创建它。你可以从ProcessEngine
中获取包含工作流/BPM方法的各种服务,ProcessEngine
和服务对象是线程安全的,因此,你可以为整个服务器保留对其中之一的引用。
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
ManagementService managementService = processEngine.getManagementService();
IdentityService identityService = processEngine.getIdentityService();
HistoryService historyService = processEngine.getHistoryService();
FormService formService = processEngine.getFormService();
DynamicBpmnService dynamicBpmnService = processEngine.getDynamicBpmnService();
ProcessEngines.getDefaultProcessEngine()
将在首次调用时初始化并构建一个流程引擎,此后始终返回同一流程引擎,可以使用ProcessEngines.init()
和ProcessEngines.destroy()
正确创建和关闭所有流程引擎。
ProcessEngines
类将扫描所有activiti.cfg.xml
和activiti-context.xml
文件,对于所有activiti.cfg.xml
文件,将以典型的Activiti方式构建流程引擎:ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(inputStream).buildProcessEngine()
。对于所有activiti-context.xml
文件,将以Spring方式构建流程引擎:首先创建Spring应用程序上下文,然后从该应用程序上下文获得流程引擎。
所有服务都是无状态的,这意味着你可以轻松地在集群中的多个节点上运行Activiti,每个节点都访问同一数据库,而不必担心哪台计算机实际执行了先前的调用,无论在何处执行,对任何服务的任何调用都是幂等的。
RepositoryService
可能是使用Activiti引擎时需要的第一个服务,此服务提供用于管理和操纵部署和流程定义的操作。它表示流程中每个步骤的结构和行为,部署是Activiti引擎中打包的单位,一个部署可以包含多个BPMN 2.0 xml文件和任何其他资源。一个部署中包含什么的选择取决于开发人员,它的范围可以从单个流程BPMN 2.0 xml文件到整个流程包和相关资源(例如,部署hr-process可能包含与hr流程相关的所有内容)。RepositoryService
允许deploy
此类软件包,部署意味着将其上传到引擎,在引擎中检查和解析所有流程,然后将其存储到数据库中,从那时起,系统便知道该部署,并且现在可以启动该部署中包括的任何流程。
此外,这项服务还可以:
- 查询引擎已知的部署和流程定义。
- 挂起和激活整个部署或特定流程定义,挂起表示无法对其进行进一步的操作,而激活是相反的操作。
- 检索各种资源,例如部署中包含的文件或引擎自动生成的流程图。
- 检索流程定义的POJO版本,该版本可用于使用Java而不是xml自省流程。
尽管RepositoryService
的重点在于静态信息(即不变的数据,或至少没有太多变化的数据),但RuntimeService
却恰恰相反,它处理启动流程定义的新流程实例。如上所述,流程定义定义流程中不同步骤的结构和行为,流程实例就是这种流程定义的一种执行。对于每个流程定义,通常有多个实例同时运行,RuntimeService
也是用于检索和存储流程变量的服务,这是特定于给定流程实例的数据,可以由流程中的各种构造使用(例如,专用网关通常使用流程变量来确定选择哪个路径来继续该流程)。Runtimeservice
还允许查询流程实例和执行,执行是BPMN 2.0的token
概念的表示,基本上,执行是指向流程实例当前所在位置的指针,最后,只要流程实例正在等待外部触发器并且需要继续流程,就使用RuntimeService
。一个流程实例可以具有各种等待状态,并且该服务包含各种操作,以向该实例发出信号,表示已接收到外部触发器,并且该流程实例可以继续。
需要由系统的实际人工用户执行的任务是BPM引擎(如Activiti)的核心,任务周围的所有任务都分组在TaskService
中,例如:
- 查询分配给用户或组的任务
- 创建新的独立任务,这些是与流程实例无关的任务。
- 操纵任务分配给哪个用户或该任务涉及某种用户。
- 领取并完成任务,领取意味着某人决定担任该任务的受让人,这意味着该用户将完成任务,完成意味着完成任务的工作,通常,这是一种表单的填充。
IdentityService
非常简单,它允许对群组和用户进行管理(创建、更新、删除、查询等),重要的是要了解Activiti实际上不会在运行时对用户进行任何检查。例如,可以将任务分配给任何用户,但是引擎不会验证该用户是否为系统所知,这是因为Activiti引擎也可以与LDAP,Active Directory等服务结合使用。
FormService
是一项可选服务,这意味着无需它即可完美使用Activiti,而不会牺牲任何功能,该服务介绍了起始表单和任务表单的概念。起始表单是在流程实例启动之前向用户显示的表单,而任务表单是在用户想要填写表单时显示的表单,Activiti允许在BPMN 2.0流程定义中定义这些表单,该服务以一种易于使用的方式公开此数据,但是,这又是可选的,因为表单不需要嵌入流程定义中。
HistoryService
公开Activiti引擎收集的所有历史数据,在执行流程时,引擎可以保存很多数据(这是可配置的),例如流程实例的启动时间,谁执行了哪些任务,完成任务所花的时间,每个流程实例遵循的路径等,该服务主要公开查询功能以访问此数据。
使用Activiti编码自定义应用程序时,通常不需要ManagementService
,它允许检索有关数据库表和表元数据的信息,此外,它公开了作业的查询功能和管理操作。作业在Activiti中用于各种用途,例如计时器、异步延续、延迟挂起/激活等。
DynamicBpmnService
可用于更改流程定义的一部分,而无需重新部署它,例如,你可以在流程定义中更改用户任务的受让人定义,或更改服务任务的类名。
异常策略
Activiti中的基本异常是org.activiti.engine.ActivitiException
,这是未经检查的异常,API可以随时抛出此异常,但是javadocs中记录了在特定方法中发生的预期异常。
例如,TaskService中:
/**
* Called when the task is successfully executed.
* @param taskId the id of the task to complete, cannot be null.
* @throws ActivitiObjectNotFoundException when no task exists with the given id.
*/
void complete(String taskId);
在上面的示例中,如果传递的ID不存在任何任务,则将引发异常,另外,由于javadoc明确声明taskId不能为null
,所以传递null
时将引发ActivitiIllegalArgumentException
。
添加了以下在特定情况下抛出的子类,在流程执行或API调用过程中发生的所有其他错误(不符合以下可能的异常情况)均作为常规ActivitiExceptions
抛出。
-
ActivitiWrongDbException
:当Activiti引擎发现数据库模式版本与引擎版本不匹配时抛出。 -
ActivitiOptimisticLockingException
:当由于同时访问同一数据条目而在数据存储中发生乐观锁定时抛出。 -
ActivitiClassLoadingException
:当找不到要加载的类或在加载时发生错误时抛出该异常(例如JavaDelegates
、TaskListeners
等)。 -
ActivitiObjectNotFoundException
:当请求的对象或对其执行操作的对象不存在时抛出。 -
ActivitiIllegalArgumentException
:表示在Activiti API调用中提供了非法参数,在引擎的配置中配置了非法值或提供了非法值或在流程定义中使用了非法值的异常。 -
ActivitiTaskAlreadyClaimedException
:在已领取任务时,再调用taskService.claim(…)
时抛出。