- pppppp
- 等级: 初级会员
- 文章: 49
- 积分: 87
- 来自: ...
|
发表时间:2007-09-19
最后修改:2008-11-27
目前有很多实现动态会签的文章,但是给人感觉不是很优雅,下面介绍一种实现方式。
1、流程定义文件:
xml 代码
- <
process-definition
- xmlns
=
"urn:jbpm.org:jpdl-3.1"
name
=
"foreach"
>
- <
start-state
name
=
"start"
>
- <
task
name
=
"one"
>
- </
task
>
- <
transition
name
=
"a"
to
=
"foreachf"
>
</
transition
>
- </
start-state
>
- <
node
name
=
"foreachf"
>
- <
action
class
=
"com.framework.workflow.jbpm.ForEachFork"
>
- <
foreach
>
#{bpm_assignees}
</
foreach
>
- <
var
>
reviewer
</
var
>
- </
action
>
- <
transition
name
=
"review"
to
=
"review"
>
</
transition
>
- </
node
>
- <
task-node
name
=
"review"
>
- <
task
name
=
"reviewTask"
>
- <
assignment
class
=
"com.framework.workflow.jbpm.DefaultAssignment"
>
- <
actor
>
#{reviewer}
</
actor
>
- </
assignment
>
- </
task
>
- <
transition
name
=
"reject"
to
=
"endreview"
>
- <
action
class
=
"com.framework.workflow.jbpm.JoinEndForkedTokens"
/>
- </
transition
>
- <
transition
name
=
"approve"
to
=
"endreview"
>
</
transition
>
- </
task-node
>
- <
join
name
=
"endreview"
>
- <
transition
name
=
"toend"
to
=
"end1"
>
</
transition
>
- </
join
>
- <
end-state
name
=
"end1"
>
</
end-state
>
- </
process-definition
>
在这里我们从node节点动态生成任务节点,会签时当有一个是reject时便结束所有节点。
2、动态派生ForEachFork代码:
java 代码
- public
class
ForEachFork
implements
ActionHandler
- {
- private
Element foreach;
- private
String var;
-
- private
static
Map map =
new
HashMap();
- static
{
- List list = new
ArrayList();
- list.add("1234"
);
- list.add("2345"
);
- list.add("3456"
);
- map.put("bpm_assignees"
, list);
- }
-
-
-
-
-
-
-
-
-
-
- @SuppressWarnings
(
"unchecked"
)
- public
void
execute(
final
ExecutionContext executionContext)
- throws
Exception
- {
-
-
- if
(foreach ==
null
)
- {
- throw
new
WorkflowException(
"forEach has not been provided"
);
- }
-
- List forEachColl = null
;
- String forEachCollStr = foreach.getTextTrim();
-
- if
(forEachCollStr !=
null
)
- {
- if
(forEachCollStr.startsWith(
"#{"
))
- {
- String expression = forEachCollStr.substring(2
, forEachCollStr.length() -
1
);
- forEachColl = (List)map.get(expression);
-
- }
-
- }
-
- if
(var ==
null
|| var.length() ==
0
)
- {
- throw
new
WorkflowException(
"forEach variable name has not been provided"
);
- }
-
-
-
-
-
- Token rootToken = executionContext.getToken();
- Node node = executionContext.getNode();
- List forkTransitions = new
ArrayList();
-
- for
(
int
i =
0
; i < node.getLeavingTransitions().size(); i++)
- {
- Transition transition = (Transition) node.getLeavingTransitions().get(i);
- for
(
int
iVar =
0
; iVar < forEachColl.size(); iVar++)
- {
-
- String tokenName = getTokenName(rootToken, transition.getName(), iVar);
- Token loopToken = new
Token(rootToken, tokenName);
- loopToken.setTerminationImplicit(true
);
- executionContext.getJbpmContext().getSession().save(loopToken);
-
-
- final
ExecutionContext newExecutionContext =
new
ExecutionContext(loopToken);
- newExecutionContext.getContextInstance().createVariable(var, forEachColl.get(iVar), loopToken);
-
-
- ForkedTransition forkTransition = new
ForkedTransition();
- forkTransition.executionContext = newExecutionContext;
- forkTransition.transition = transition;
- forkTransitions.add(forkTransition);
- }
- }
-
-
-
- for
(ForkedTransition forkTransition : forkTransitions)
- {
- node.leave(forkTransition.executionContext, forkTransition.transition);
- }
- }
-
-
-
-
-
-
-
-
-
-
- protected
String getTokenName(Token parent, String transitionName,
int
loopIndex)
- {
- String tokenName = null
;
- if
(transitionName !=
null
)
- {
- if
(!parent.hasChild(transitionName))
- {
- tokenName = transitionName;
- }
- else
- {
- int
i =
2
;
- tokenName = transitionName + Integer.toString(i);
- while
(parent.hasChild(tokenName))
- {
- i++;
- tokenName = transitionName + Integer.toString(i);
- }
- }
- }
- else
- {
-
- int
size = ( parent.getChildren()!=
null
? parent.getChildren().size()+
1
:
1
);
- tokenName = Integer.toString(size);
- }
- return
tokenName +
"."
+ loopIndex;
- }
-
-
-
-
-
-
- private
class
ForkedTransition
- {
- private
ExecutionContext executionContext;
- private
Transition transition;
- }
- }
在具体应用中需要灵活的根据业务逻辑需要派生所需要的分支。
3、DefaultAssignment
进行简单的权限操作,这里面主要是将#{reviewer}值作为actorId进行设置
4、JoinEndForkedTokens结束所有节点
java 代码
- public
class
JoinEndForkedTokens
implements
ActionHandler
- {
-
- public
JoinEndForkedTokens()
- {
- }
-
-
-
- public
void
execute(ExecutionContext executionContext)
- {
- Token token = executionContext.getToken().getParent();
- Map childTokens = token.getActiveChildren();
- for
(Object childToken : childTokens.values())
- {
- cancelToken(executionContext, (Token)childToken);
- }
-
- }
-
-
-
-
-
-
-
-
-
- protected
void
cancelToken(ExecutionContext executionContext, Token token)
- {
-
- Map childTokens = token.getActiveChildren();
- for
(Object childToken : childTokens.values())
- {
- cancelToken(executionContext, (Token)childToken);
- }
-
- if
(!token.hasEnded())
- {
- token.end(true
);
- }
-
-
- cancelTokenTasks(executionContext, token);
- }
-
-
-
-
-
-
-
-
-
- protected
void
cancelTokenTasks(ExecutionContext executionContext, Token token)
- {
- TaskMgmtInstance tms = executionContext.getTaskMgmtInstance();
- Collection tasks = tms.getUnfinishedTasks(token);
- for
(Object task : tasks)
- {
- TaskInstance taskInstance = (TaskInstance)task;
- if
(taskInstance.isBlocking())
- {
- taskInstance.setBlocking(false
);
- }
- if
(taskInstance.isSignalling())
- {
- taskInstance.setSignalling(false
);
- }
- if
(!taskInstance.hasEnded())
- {
- taskInstance.end();
- }
- }
- }
- }
结束所有分支节点任务,流向结束节点。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
返回顶楼 |
|
|
- llandyl
- 等级:
- 性别:
- 文章: 25
- 积分: 277
|
如果将流程定义文件修改,变成两次调用生成<node name="foreachf">就会有错误,而不是直接结束。
错误出现在 executionContext.getJbpmContext().getSession().save(loopToken);
。通过跟踪发现,是executionContext.getJbpmContext()为空。即报Caused by: java.lang.NullPointerException的错误。
这个问题困扰我几天了。一致没有解决。
不知那位有过此情况下的情况,望告知。谢谢!
|
返回顶楼 |
|
|
- llandyl
- 等级:
- 性别:
- 文章: 25
- 积分: 277
|
问题已经解决。是测试程序测试方法不对造成的。
|
返回顶楼 |
|
|
- rebellan
- 等级: 初级会员
- 性别:
- 文章: 2
- 积分: 32
- 来自: 北京
|
太感谢楼主的分享精神了,搞了好久的会签 被楼主点通了,谢谢
|
返回顶楼 |
|
|