这个异常可以在任何时候被API抛出,特定方法抛出的特定的异常
/** * 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时,就会抛出异常.taskId不能为null,如果传入null,就会抛出ActivitiIllegalArgumentException
应该避免过多的异常继承,子类只用于特定的场合
流程引擎和API调用的其他场合不使用子类异常,抛出一个普通的ActivitiExceptions
ActivitiWrongDbException: 当Activiti引擎发现数据库版本号和引擎版本号不一致时抛出 ActivitiOptimisticLockingException: 对同一数据进行并发方法并出现乐观锁时抛出 ActivitiClassLoadingException: 当无法找到需要加载的类或在加载类时出现了错误-JavaDelegate,TaskListener ActivitiObjectNotFoundException: 当请求或操作的对应不存在时抛出 ActivitiIllegalArgumentException: 这个异常表示调用Activiti API时传入了一个非法的参数,可能是引擎配置中的非法值,或提供了一个非法值,或流程定义中使用的非法值 ActivitiTaskAlreadyClaimedException: 当任务已经被认领了,再调用taskService.claim(...)就会抛出 查询 API在Activiti流程引擎中查询数据有两种方式:
查询API
原生查询
查询API: 查询API提供了完全类型安全的API,可以自定义添加查询条件和精确的排序条件,所有条件都以AND组合
List<Task> tasks = taskService.createTaskQuery() .taskAssignee("kermit") .processVariableValueEquals("orderId", "0815") .orderByDueDate().asc() .list();原生查询:
需要更强大的查询时:使用OR条件或者能使用查询API实现的条件.
可以编写自己的SQL查询. 返回类型由你使用的查询对象决定,数据会映射到正确的对象上:任务,流程实例,执行..
查询作用在数据库上,必须使用数据库中定义的表名和列名,要了解内部数据结构
使用原生查询时,表名可以通过API获得,可以尽量减少对数据库的依赖
List<Task> tasks = taskService.createNativeTaskQuery() .sql("SELECT count(*) FROM " + managementService.getTableName(Task.class) + " T WHERE T.NAME_ = #{taskName}") .parameter("taskName", "gonzoTask") .list(); long count = taskService.createNativeTaskQuery() .sql("SELECT count(*) FROM " + managementService.getTableName(Task.class) + " T1, " + managementService.getTableName(VariableInstanceEntity.class) + " V1 WHERE V1.TASK_ID_ = T1.ID_") .count(); 表达式Activiti使用UEL处理表达式.UEL即统一表达式语言, 是EE6规范的一部分.为了在所有运行环境都支持最新UEL的所有功能,使用JUEL的修改版本
表达式可以用在很多场景下:
Java服务任务
执行监听器
任务监听器
条件流
虽然有两重表达式:值表达式和方法表达式, Activiti进行了抽象,所以两者可以同样使用在需要表达式的场景中
Value expression: 解析为值,默认
${myVar} ${myBean.myProperty}所有流程变量都可以使用,所有spring bean(spring环境中)也可以使用在表达式中
Method expression: 调用一个方法,使用或不使用参数
${printer.print()} ${myBean.addNewOrder('orderName')} ${myBean.doSomething(myVar, execution)}当调用一个无参数的方法时,记得在方法名后添加空的括号,以区分值表达式
传递的参数可以是字符串也可以是表达式,它们会被自动解析
这些表达式支持解析原始类型:
bean
list
数组
map
包括比较
在流程实例中,表达式中可以使用一些默认对象:
execution: DelegateExecution,提供外出执行的额外信息
task: DelegateTask,提供当前任务的额外信息 ,只对任务监听器的表达式有效
authenticatedUserId: 当前登录的用户id.如果没有用户登录,这个变量就不可用
单元测试业务流程是软件项目的一部分,它也应该和普通的业务流程一样进行测试:使用单元测试
因为Activiti是一个嵌入式的java引擎,所以为业务流程编写单元测试和写普通单元测试完全一样
Activiti支持JUnit 3和4进行单元测试
使用JUnit 3时, 必须集成org.activiti.engine.test.ActivitiTestCase. 它通过保护的成员变量提供ProcessEngine和服务,
在测试的setup()中,默认会使用classpath下的activiti.cfg.xml初始化流程引擎
要使用不同的配置文件,可以重写getConfigurationResource() 方法
如果配置文件相同的话,对应的流程引擎会被静态缓存,就可以用于多个单元测试