也谈一下Activiti工作流节点的自由跳转
2016-06-06 17:11
465 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。
最近在搞openwebflow的工作流节点自由跳转功能,在网上看了一些资料,感觉不是很好,总结原因如下:
直接手动调用SqlSession的操作,感觉会漏掉一些重要的初始化操作(如:启动新节点之后加载其用户授权策略,等);
只有往前(往已执行过的节点)跳转的功能,没有往后节点(往还没有执行的节点)跳转的功能;
新任务不是追加到已有执行路径上,而是覆盖老任务;
那么就自己动手吧!操作流程其实也简单,大概如下:
按照目标节点(activity)定义创建一个新的任务(task),这个创建过程必须和正常流程到了某个节点的时候完全一样(如:不应该忽略用户授权策略的加载,任务名称表达式的计算,等);
删除掉当前任务(task);
注意:直接删除当前节点会报错,因为它还在流程之中,所以要先解除任务与当前执行execution的关联;
以上操作如何安全的实现呢?看了一下源码,经过多次痛苦的尝试,积累了不少教训:
直接SqlSession操作数据库是不行的,这种方法容易擦枪走火!
直接taskService.saveTask也是不行的,因为它实际上仅仅是针对DbSqlSession的操作!不commit一切操作都白搭!
那么怎么办呢?我想说的是,Activiti的封装做得很厚,想完全看懂是太难的。目前我还没想完全看懂,直接吐槽一下,与后人分享其中的痛苦:
太多的Command!一个saveTask()总会包装成SaveTask操作,关键代码总是藏得很深!
太多的事件!
太多的AtomicOperation!
太多的Listener!
太多的CommandInterceptor!隐隐约约感觉Activiti将各种CommandInterceptor组成一个chain,然后在执行核心代码的时候会一层一层的剥洋葱!
还有就是栈式Context!看看下面这段代码就明白有多坑爹了:
[java] view
plain copy
print?
public static void setCommandContext(CommandContext commandContext) {
getStack(commandContextThreadLocal).push(commandContext);
}
总之,代码看得那是相当郁闷!debug的时候,调用栈极其深,而且大部分都会落在如下两段代码中:
代码1:
[java] view
plain copy
print?
public <T> T execute(CommandConfig config, Command<T> command) {
if (!log.isDebugEnabled()) {
// do nothing here if we cannot log
return next.execute(config, command);
}
log.debug("\n");
log.debug("--- starting {} --------------------------------------------------------", command.getClass().getSimpleName());
try {
return next.execute(config, command);
} finally {
log.debug("--- {} finished --------------------------------------------------------", command.getClass().getSimpleName());
log.debug("\n");
}
}
代码2:
[java] view
plain copy
print?
try {
// Push on stack
Context.setCommandContext(context);
Context.setProcessEngineConfiguration(processEngineConfiguration);
return next.execute(config, command);
} catch (Exception e) {
context.exception(e);
} finally {
try {
if (!contextReused) {
context.close();
}
} finally {
// Pop from stack
Context.removeCommandContext();
Context.removeProcessEngineConfiguration();
}
}
看到那么多的next没?足够让人疯掉的*_*
由于时间关系,我没有细细的去理解每个类,但最终还是找出了一个极妙、极安全的方法,那就是:自己写Command!然后扔给CommandExecutor()了事!
最终形成的代码如下所示:
[java] view
plain copy
print?
package org.openwebflow.ctrl;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.RuntimeServiceImpl;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.openwebflow.util.ActivityUtils;
public class TaskFlowControlService
{
ProcessEngine _processEngine;
private String _processId;
public TaskFlowControlService(ProcessEngine processEngine, String processId)
{
_processEngine = processEngine;
_processId = processId;
}
/**
* 跳转至指定活动节点
*
* @param targetTaskDefinitionKey
* @throws Exception
*/
public void jump(String targetTaskDefinitionKey) throws Exception
{
TaskEntity currentTask = (TaskEntity) _processEngine.getTaskService().createTaskQuery()
.processInstanceId(_processId).singleResult();
jump(currentTask, targetTaskDefinitionKey);
}
/**
*
* @param currentTaskEntity
* 当前任务节点
* @param targetTaskDefinitionKey
* 目标任务节点(在模型定义里面的节点名称)
* @throws Exception
*/
private void jump(final TaskEntity currentTaskEntity, String targetTaskDefinitionKey) throws Exception
{
final ActivityImpl activity = ActivityUtils.getActivity(_processEngine,
currentTaskEntity.getProcessDefinitionId(), targetTaskDefinitionKey);
final ExecutionEntity execution = (ExecutionEntity) _processEngine.getRuntimeService().createExecutionQuery()
.executionId(currentTaskEntity.getExecutionId()).singleResult();
final TaskService taskService = _processEngine.getTaskService();
//包装一个Command对象
((RuntimeServiceImpl) _processEngine.getRuntimeService()).getCommandExecutor().execute(
new Command<java.lang.Void>()
{
@Override
public Void execute(CommandContext commandContext)
{
//创建新任务
execution.setActivity(activity);
execution.executeActivity(activity);
//删除当前的任务
//不能删除当前正在执行的任务,所以要先清除掉关联
currentTaskEntity.setExecutionId(null);
taskService.saveTask(currentTaskEntity);
taskService.deleteTask(currentTaskEntity.getId(), true);
return null;
}
});
}
}
最后写了一个测试类,代码如下:
[java] view
plain copy
print?
@Test
public void testTaskSequence() throws Exception
{
//_processDef对应于vacationRequest流程,参见https://github.com/bluejoe2008/openwebflow/blob/master/models/test.bpmn
ProcessInstance instance = _processEngine.getRuntimeService().startProcessInstanceByKey(_processDef.getKey());
String instanceId = instance.getId();
TaskService taskService = _processEngine.getTaskService();
Task task1 = taskService.createTaskQuery().singleResult();
Assert.assertEquals("step2", task1.getTaskDefinitionKey());
Map<String, Object> vars = new HashMap<String, Object>();
vars.put("vacationApproved", false);
vars.put("numberOfDays", 10);
vars.put("managerMotivation", "get sick");
String taskId = taskService.createTaskQuery().taskCandidateUser("kermit").singleResult().getId();
taskService.complete(taskId, vars);
Task task2 = taskService.createTaskQuery().singleResult();
Assert.assertEquals("adjustVacationRequestTask", task2.getTaskDefinitionKey());
TaskFlowControlService tfcs = new TaskFlowControlService(_processEngine, instanceId);
//跳回至 step2
tfcs.jump("step2");
Task task3 = taskService.createTaskQuery().singleResult();
Assert.assertEquals("step2", task3.getTaskDefinitionKey());
//确认权限都拷贝过来了
//management可以访问该task
Assert.assertEquals(1, taskService.createTaskQuery().taskCandidateGroup("management").count());
//engineering不可以访问该task
Assert.assertEquals(0, taskService.createTaskQuery().taskCandidateGroup("engineering").count());
//确认历史轨迹里已保存
List<HistoricActivityInstance> activities = _processEngine.getHistoryService()
.createHistoricActivityInstanceQuery().processInstanceId(instanceId).list();
Assert.assertEquals(5, activities.size());
Assert.assertEquals("step1", activities.get(0).getActivityId());
Assert.assertEquals("step2", activities.get(1).getActivityId());
Assert.assertEquals("requestApprovedDecision", activities.get(2).getActivityId());
Assert.assertEquals("adjustVacationRequestTask", activities.get(3).getActivityId());
Assert.assertEquals("step2", activities.get(4).getActivityId());
//测试一下往前跳
tfcs.jump("adjustVacationRequestTask");
Task task4 = taskService.createTaskQuery().singleResult();
Assert.assertEquals("adjustVacationRequestTask", task4.getTaskDefinitionKey());
activities = _processEngine.getHistoryService().createHistoricActivityInstanceQuery()
.processInstanceId(instanceId).list();
Assert.assertEquals(6, activities.size());
Assert.assertEquals("adjustVacationRequestTask", activities.get(5).getActivityId());
_processEngine.getRuntimeService().deleteProcessInstance(instanceId, "test");
}
顶2
踩0
上一篇activiti
源码笔记之startProcess
下一篇Activiti源码分析(框架、核心类。。。)
•Spring事务传播性与隔离级别2015-01-11阅读558
•关于activiti流程通过、驳回、会签、转办、中止、挂起等核心操作功能的封装2014-12-07阅读3049
•ibatis
到 MyBatis区别2014-11-19阅读605
•MyBatis入门学习2014-11-17阅读813
•分布式事务处理:原理、不足2014-11-16阅读533
•优雅的实现Activiti动态调整流程(自由跳转、前进、后退、分裂、前加签、后加签等),含范例代码!2014-12-29阅读7041
•Activti跳过中间节点的helloworld实例程序2014-12-05阅读806
•spring与mybatis三种整合方法2014-11-18阅读526
•MyBatis教程2014-11-17阅读15122
•Spring分布式事务实现(适用于spring-tx
2.5)2014-11-16阅读509
更多文章
Java
1230关注|581收录
Java
9485关注|454收录
Java
9784关注|1042收录
猜你在找
CCIE专家讲解思科认证网络认证CCNA v2.0网络工程师和网络安全课程
MySQL数据库管理
软件测试基础
《C语言/C++学习指南》加密解密篇(安全相关算法)
Java之路
SSH与工作流Activiti的集成开发
Activiti工作流2开发环境配置
Activiti5工作流 笔记1--环境
Activiti工作流简介
用activiti 工作流 实现简单的请假 附带源码
查看评论
8楼 zhongzhch6天前
17:11发表 [回复]
你写的这个测试过吗,能真正实现跳转吗?我们都测试了,根本行不通7楼 cloudfighter2016-04-11
14:11发表 [回复]
如果目标节点是一个多实例节点,该如何保证多实例 ?6楼 proger20122016-04-07
10:30发表 [回复]
hello,博主,代码里你给的这个地址的流程图已经不存在了,请问哪里还有啊?
https://github.com/bluejoe2008/openwebflow/blob/master/models/test.bpmn5楼 href="http://blog.csdn.net/itlangqun1" target=_blank>itlangqun2015-08-18
16:25发表 [回复]
博主,参照你提供的这个自由流程实现的方法我自行临摹了一个,这个方法现在作为发送、回收、退回等功能的底层实现基础。现在采用这个方法实现自由跳转,发现几个很严重的问题:
1. 流程监控图状态不对
2. 使用 List<String> activeActivityIds = runtimeService.getActiveActivityIds(processInstanceId);获取当前活动节点一直都是流程启动节点后的第一个走过节点
Re: itlangqun2015-08-18
16:33发表 [回复]
回复itlangqun1:这个是我的代码,能否指教一下
http://www.oschina.net/code/snippet_138859_503074楼 href="http://blog.csdn.net/dhysf" target=_blank>dhysf2015-05-29
16:19发表 [回复]
ActivityUtils 这个类能看下么 ?3楼 dongxh2002015-04-09
11:03发表 [回复]
您好,用了你的自由流 可以跳转,但是有个问题,跳转以后当前的节点 在act_hi_actinst历史节点表 没有结束时间。
不知道有什么解决办法吗
Re: 白乔2015-04-09
11:40发表 [回复]
回复dongxh200:您好!
你是从github上取得最新代码吗?
文中贴的代码不一定是最新版本。
Re: dongxh2002015-04-10
10:59发表 [回复]
回复bluejoe2000:谢谢你的回复,我是从github取的最新代码,我反复测试了在act_hi_actinst历史节点表 没有结束时间。
我不知道你注意到了那。
我还想问你一个问题,自由跳转可以直接跳转到多实例节点(会签)吗?
Re: tanyo5202015-09-18
15:12发表 [回复]
回复dongxh200:我好像也遇到这个问题了 就是多实例步骤 其中一个退回 删除了其他人的任务 流程结束后 流程实例没结束时间Re: dongxh2002015-04-10
10:57发表 [回复]
[java] view
plain copy
print?
executeCommand(new StartActivityCmd(currentTask.getExecutionId(), targetTaskDefinitionKey));
executeCommand(new DeleteRunningTaskCmd(currentTask));
Re: tanyo5202015-09-18
15:15发表 [回复]
回复dongxh200:好像是删除运行的任务导致 哥们你解决了么 求分享2楼 王明月2015-01-06
16:31发表 [回复]
你好。你这个跳转支持 并行网关外 跳转到 并行网关里面吗。1楼 mkcion20122014-12-26
16:00发表 [回复] [引用] [举报]
刚接触acitiviti 试了楼主的方法 的确可以做自由跳转,但是跳转之后,依然会回到原来的步骤 step1->step4之后 step4提交会跳转到step2 相当于step4 把step1顶替掉了,请问如何在step4提交之后跳转到step5
Re: 白乔2014-12-29
10:00发表 [回复] [引用] [举报]
回复mkcion2012:你的这种情况需要克隆一个新的节点(step4),并设置step4'的outgoingTransition
Re: liuyang19887162015-06-12
17:46发表 [回复] [引用] [举报]
回复bluejoe2000:我也遇到:步骤 step1->step4之后 step4提交会跳转到step2 ,不是跳转到step5,您说需要克隆一个新的节点(step4),并设置step4'的outgoingTransition,请问这种具体如何写呢,最近刚入手activiti,不是很明白,愿指教!谢谢
最近在搞openwebflow的工作流节点自由跳转功能,在网上看了一些资料,感觉不是很好,总结原因如下:
直接手动调用SqlSession的操作,感觉会漏掉一些重要的初始化操作(如:启动新节点之后加载其用户授权策略,等);
只有往前(往已执行过的节点)跳转的功能,没有往后节点(往还没有执行的节点)跳转的功能;
新任务不是追加到已有执行路径上,而是覆盖老任务;
那么就自己动手吧!操作流程其实也简单,大概如下:
按照目标节点(activity)定义创建一个新的任务(task),这个创建过程必须和正常流程到了某个节点的时候完全一样(如:不应该忽略用户授权策略的加载,任务名称表达式的计算,等);
删除掉当前任务(task);
注意:直接删除当前节点会报错,因为它还在流程之中,所以要先解除任务与当前执行execution的关联;
以上操作如何安全的实现呢?看了一下源码,经过多次痛苦的尝试,积累了不少教训:
直接SqlSession操作数据库是不行的,这种方法容易擦枪走火!
直接taskService.saveTask也是不行的,因为它实际上仅仅是针对DbSqlSession的操作!不commit一切操作都白搭!
那么怎么办呢?我想说的是,Activiti的封装做得很厚,想完全看懂是太难的。目前我还没想完全看懂,直接吐槽一下,与后人分享其中的痛苦:
太多的Command!一个saveTask()总会包装成SaveTask操作,关键代码总是藏得很深!
太多的事件!
太多的AtomicOperation!
太多的Listener!
太多的CommandInterceptor!隐隐约约感觉Activiti将各种CommandInterceptor组成一个chain,然后在执行核心代码的时候会一层一层的剥洋葱!
还有就是栈式Context!看看下面这段代码就明白有多坑爹了:
[java] view
plain copy
print?
public static void setCommandContext(CommandContext commandContext) {
getStack(commandContextThreadLocal).push(commandContext);
}
总之,代码看得那是相当郁闷!debug的时候,调用栈极其深,而且大部分都会落在如下两段代码中:
代码1:
[java] view
plain copy
print?
public <T> T execute(CommandConfig config, Command<T> command) {
if (!log.isDebugEnabled()) {
// do nothing here if we cannot log
return next.execute(config, command);
}
log.debug("\n");
log.debug("--- starting {} --------------------------------------------------------", command.getClass().getSimpleName());
try {
return next.execute(config, command);
} finally {
log.debug("--- {} finished --------------------------------------------------------", command.getClass().getSimpleName());
log.debug("\n");
}
}
代码2:
[java] view
plain copy
print?
try {
// Push on stack
Context.setCommandContext(context);
Context.setProcessEngineConfiguration(processEngineConfiguration);
return next.execute(config, command);
} catch (Exception e) {
context.exception(e);
} finally {
try {
if (!contextReused) {
context.close();
}
} finally {
// Pop from stack
Context.removeCommandContext();
Context.removeProcessEngineConfiguration();
}
}
看到那么多的next没?足够让人疯掉的*_*
由于时间关系,我没有细细的去理解每个类,但最终还是找出了一个极妙、极安全的方法,那就是:自己写Command!然后扔给CommandExecutor()了事!
最终形成的代码如下所示:
[java] view
plain copy
print?
package org.openwebflow.ctrl;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.RuntimeServiceImpl;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.openwebflow.util.ActivityUtils;
public class TaskFlowControlService
{
ProcessEngine _processEngine;
private String _processId;
public TaskFlowControlService(ProcessEngine processEngine, String processId)
{
_processEngine = processEngine;
_processId = processId;
}
/**
* 跳转至指定活动节点
*
* @param targetTaskDefinitionKey
* @throws Exception
*/
public void jump(String targetTaskDefinitionKey) throws Exception
{
TaskEntity currentTask = (TaskEntity) _processEngine.getTaskService().createTaskQuery()
.processInstanceId(_processId).singleResult();
jump(currentTask, targetTaskDefinitionKey);
}
/**
*
* @param currentTaskEntity
* 当前任务节点
* @param targetTaskDefinitionKey
* 目标任务节点(在模型定义里面的节点名称)
* @throws Exception
*/
private void jump(final TaskEntity currentTaskEntity, String targetTaskDefinitionKey) throws Exception
{
final ActivityImpl activity = ActivityUtils.getActivity(_processEngine,
currentTaskEntity.getProcessDefinitionId(), targetTaskDefinitionKey);
final ExecutionEntity execution = (ExecutionEntity) _processEngine.getRuntimeService().createExecutionQuery()
.executionId(currentTaskEntity.getExecutionId()).singleResult();
final TaskService taskService = _processEngine.getTaskService();
//包装一个Command对象
((RuntimeServiceImpl) _processEngine.getRuntimeService()).getCommandExecutor().execute(
new Command<java.lang.Void>()
{
@Override
public Void execute(CommandContext commandContext)
{
//创建新任务
execution.setActivity(activity);
execution.executeActivity(activity);
//删除当前的任务
//不能删除当前正在执行的任务,所以要先清除掉关联
currentTaskEntity.setExecutionId(null);
taskService.saveTask(currentTaskEntity);
taskService.deleteTask(currentTaskEntity.getId(), true);
return null;
}
});
}
}
最后写了一个测试类,代码如下:
[java] view
plain copy
print?
@Test
public void testTaskSequence() throws Exception
{
//_processDef对应于vacationRequest流程,参见https://github.com/bluejoe2008/openwebflow/blob/master/models/test.bpmn
ProcessInstance instance = _processEngine.getRuntimeService().startProcessInstanceByKey(_processDef.getKey());
String instanceId = instance.getId();
TaskService taskService = _processEngine.getTaskService();
Task task1 = taskService.createTaskQuery().singleResult();
Assert.assertEquals("step2", task1.getTaskDefinitionKey());
Map<String, Object> vars = new HashMap<String, Object>();
vars.put("vacationApproved", false);
vars.put("numberOfDays", 10);
vars.put("managerMotivation", "get sick");
String taskId = taskService.createTaskQuery().taskCandidateUser("kermit").singleResult().getId();
taskService.complete(taskId, vars);
Task task2 = taskService.createTaskQuery().singleResult();
Assert.assertEquals("adjustVacationRequestTask", task2.getTaskDefinitionKey());
TaskFlowControlService tfcs = new TaskFlowControlService(_processEngine, instanceId);
//跳回至 step2
tfcs.jump("step2");
Task task3 = taskService.createTaskQuery().singleResult();
Assert.assertEquals("step2", task3.getTaskDefinitionKey());
//确认权限都拷贝过来了
//management可以访问该task
Assert.assertEquals(1, taskService.createTaskQuery().taskCandidateGroup("management").count());
//engineering不可以访问该task
Assert.assertEquals(0, taskService.createTaskQuery().taskCandidateGroup("engineering").count());
//确认历史轨迹里已保存
List<HistoricActivityInstance> activities = _processEngine.getHistoryService()
.createHistoricActivityInstanceQuery().processInstanceId(instanceId).list();
Assert.assertEquals(5, activities.size());
Assert.assertEquals("step1", activities.get(0).getActivityId());
Assert.assertEquals("step2", activities.get(1).getActivityId());
Assert.assertEquals("requestApprovedDecision", activities.get(2).getActivityId());
Assert.assertEquals("adjustVacationRequestTask", activities.get(3).getActivityId());
Assert.assertEquals("step2", activities.get(4).getActivityId());
//测试一下往前跳
tfcs.jump("adjustVacationRequestTask");
Task task4 = taskService.createTaskQuery().singleResult();
Assert.assertEquals("adjustVacationRequestTask", task4.getTaskDefinitionKey());
activities = _processEngine.getHistoryService().createHistoricActivityInstanceQuery()
.processInstanceId(instanceId).list();
Assert.assertEquals(6, activities.size());
Assert.assertEquals("adjustVacationRequestTask", activities.get(5).getActivityId());
_processEngine.getRuntimeService().deleteProcessInstance(instanceId, "test");
}
顶2
踩0
上一篇activiti
源码笔记之startProcess
下一篇Activiti源码分析(框架、核心类。。。)
我的同类文章
Web应用(47)•Spring事务传播性与隔离级别2015-01-11阅读558
•关于activiti流程通过、驳回、会签、转办、中止、挂起等核心操作功能的封装2014-12-07阅读3049
•ibatis
到 MyBatis区别2014-11-19阅读605
•MyBatis入门学习2014-11-17阅读813
•分布式事务处理:原理、不足2014-11-16阅读533
•优雅的实现Activiti动态调整流程(自由跳转、前进、后退、分裂、前加签、后加签等),含范例代码!2014-12-29阅读7041
•Activti跳过中间节点的helloworld实例程序2014-12-05阅读806
•spring与mybatis三种整合方法2014-11-18阅读526
•MyBatis教程2014-11-17阅读15122
•Spring分布式事务实现(适用于spring-tx
2.5)2014-11-16阅读509
更多文章
参考知识库
Java
EE知识库
1230关注|581收录MySQL知识库
8483关注|1396收录Java
SE知识库
9485关注|454收录Java
Web知识库
9784关注|1042收录猜你在找
CCIE专家讲解思科认证网络认证CCNA v2.0网络工程师和网络安全课程
MySQL数据库管理
软件测试基础
《C语言/C++学习指南》加密解密篇(安全相关算法)
Java之路
SSH与工作流Activiti的集成开发
Activiti工作流2开发环境配置
Activiti5工作流 笔记1--环境
Activiti工作流简介
用activiti 工作流 实现简单的请假 附带源码
查看评论
8楼 zhongzhch6天前
17:11发表 [回复]
你写的这个测试过吗,能真正实现跳转吗?我们都测试了,根本行不通7楼 cloudfighter2016-04-11
14:11发表 [回复]
如果目标节点是一个多实例节点,该如何保证多实例 ?6楼 proger20122016-04-07
10:30发表 [回复]
hello,博主,代码里你给的这个地址的流程图已经不存在了,请问哪里还有啊?
https://github.com/bluejoe2008/openwebflow/blob/master/models/test.bpmn5楼 href="http://blog.csdn.net/itlangqun1" target=_blank>itlangqun2015-08-18
16:25发表 [回复]
博主,参照你提供的这个自由流程实现的方法我自行临摹了一个,这个方法现在作为发送、回收、退回等功能的底层实现基础。现在采用这个方法实现自由跳转,发现几个很严重的问题:
1. 流程监控图状态不对
2. 使用 List<String> activeActivityIds = runtimeService.getActiveActivityIds(processInstanceId);获取当前活动节点一直都是流程启动节点后的第一个走过节点
Re: itlangqun2015-08-18
16:33发表 [回复]
回复itlangqun1:这个是我的代码,能否指教一下
http://www.oschina.net/code/snippet_138859_503074楼 href="http://blog.csdn.net/dhysf" target=_blank>dhysf2015-05-29
16:19发表 [回复]
ActivityUtils 这个类能看下么 ?3楼 dongxh2002015-04-09
11:03发表 [回复]
您好,用了你的自由流 可以跳转,但是有个问题,跳转以后当前的节点 在act_hi_actinst历史节点表 没有结束时间。
不知道有什么解决办法吗
Re: 白乔2015-04-09
11:40发表 [回复]
回复dongxh200:您好!
你是从github上取得最新代码吗?
文中贴的代码不一定是最新版本。
Re: dongxh2002015-04-10
10:59发表 [回复]
回复bluejoe2000:谢谢你的回复,我是从github取的最新代码,我反复测试了在act_hi_actinst历史节点表 没有结束时间。
我不知道你注意到了那。
我还想问你一个问题,自由跳转可以直接跳转到多实例节点(会签)吗?
Re: tanyo5202015-09-18
15:12发表 [回复]
回复dongxh200:我好像也遇到这个问题了 就是多实例步骤 其中一个退回 删除了其他人的任务 流程结束后 流程实例没结束时间Re: dongxh2002015-04-10
10:57发表 [回复]
[java] view
plain copy
print?
executeCommand(new StartActivityCmd(currentTask.getExecutionId(), targetTaskDefinitionKey));
executeCommand(new DeleteRunningTaskCmd(currentTask));
Re: tanyo5202015-09-18
15:15发表 [回复]
回复dongxh200:好像是删除运行的任务导致 哥们你解决了么 求分享2楼 王明月2015-01-06
16:31发表 [回复]
你好。你这个跳转支持 并行网关外 跳转到 并行网关里面吗。1楼 mkcion20122014-12-26
16:00发表 [回复] [引用] [举报]
刚接触acitiviti 试了楼主的方法 的确可以做自由跳转,但是跳转之后,依然会回到原来的步骤 step1->step4之后 step4提交会跳转到step2 相当于step4 把step1顶替掉了,请问如何在step4提交之后跳转到step5
Re: 白乔2014-12-29
10:00发表 [回复] [引用] [举报]
回复mkcion2012:你的这种情况需要克隆一个新的节点(step4),并设置step4'的outgoingTransition
Re: liuyang19887162015-06-12
17:46发表 [回复] [引用] [举报]
回复bluejoe2000:我也遇到:步骤 step1->step4之后 step4提交会跳转到step2 ,不是跳转到step5,您说需要克隆一个新的节点(step4),并设置step4'的outgoingTransition,请问这种具体如何写呢,最近刚入手activiti,不是很明白,愿指教!谢谢
相关文章推荐
- 使用CoordinatorLayout实现折叠式ToolBar
- c++实验7——项目2——最大公约和和最小公倍数
- JavaScript判断数组重复内容的两种方法(推荐)
- 前端技术 -- 页面滚动条到一定高度后出现置顶按钮
- 关于Reveal Are you trying to load dynamic library with Reveal Framework already linked?
- Java 读写方案
- TCP 状态变迁图说明 【转】
- Transact-SQL 程序设计(一) --------变量和表达式
- ffmpeg大神博客
- 获取文件数字签名证书信息
- LVS集群
- AspnetIdentitySample
- 算法导论 分治法+归并排序的一种排序算法 C++实现
- 学习进度条十一(第12周)
- hdu 1023 Train Problem II
- 根据URL将文件下载本地
- more命令
- Android 获取手机总内存和可用内存等信息
- Cocos2d-x 多分辨率适配完全解析
- [疯狂Java]泛型:泛型方法、泛型方法VS类型通配符(?)