1、节点含义
<?xml version="1.0" encoding="UTF-8"?>
<process-definition
xmlns="urn:jbpm.org:jpdl-3.2" name="example001">
<start-state name="start">
<transition name="" to="state1"></transition>
</start-state>
<state name="state1">
<transition name="" to="node1"></transition>
</state>
<node name="node1">
<transition name="" to="state2"></transition>
</node>
<state name="state2">
<transition name="" to="task1"></transition>
</state>
<task-node name="task1">
<transition name="tobf" to="end1"></transition>
</task-node>
<end-state name="end1"></end-state>
</process-definition>
JbpmContext jbpmContext = getJbpmContext();
GraphSession graphSession=jbpmContext.getGraphSession();
ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition(processName);
ProcessInstance processInstance = new ProcessInstance(processDefinition);
Token token = processInstance.getRootToken();
token.signal();
logger.info("NodeName:"+token.getNode().getName());
token.signal();
logger.info("NodeName:"+token.getNode().getName());
token.signal();
logger.info("NodeName:"+token.getNode().getName());
显示结果如下:
NodeName:state1
NodeName:state2
NodeName:end1
总结:
node、state、task节点分别为node、等待节点、任务节点。
进过node、task-node不需要singal就往下走,所以没有显示他们的名称,state节点必须singal才往下走。
二、ActionHandler、设置工作参与者以及获取工作路由
<?xml version="1.0" encoding="UTF-8"?>
<process-definition
xmlns="urn:jbpm.org:jpdl-3.2" name="example002">
<start-state name="start">
<transition name="" to="state1"></transition>
</start-state>
<state name="state1">
<transition name="" to="node1"></transition>
</state>
<node name="node1">
<action class="jbpm.java.handler.example.TestAction"></action>
<transition name="" to="state2"></transition>
</node>
<state name="state2">
<transition name="" to="task1"></transition>
</state>
<task-node name="task1">
<task>
<assignment actor-id="#{user}"></assignment>
</task>
<transition name="tobf" to="end1"></transition>
</task-node>
<end-state name="end1"></end-state>
</process-definition>
TestAction.java
public class TestAction implements ActionHandler {
private static final long serialVersionUID = 1196655833977006482L;
@Override
public void execute(ExecutionContext executionContext) throws Exception {
System.out.println("通过Action类来解决问题!!!");
}
}
JbpmContext jbpmContext = getJbpmContext();
GraphSession graphSession=jbpmContext.getGraphSession();
ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition(processName);
ProcessInstance processInstance = new ProcessInstance(processDefinition);
processInstance.getContextInstance().setVariable("user", "用户");
Token token = processInstance.getRootToken();
token.signal();
logger.info("NodeName:"+token.getNode().getName());
token.signal();
logger.info("NodeName:"+token.getNode().getName());
token.signal();
logger.info("NodeName:"+token.getNode().getName());
token.signal();
logger.info("NodeName:"+token.getNode().getName());
TaskInstance ti = (TaskInstance)processInstance.getTaskMgmtInstance().getTaskInstances().iterator().next();
System.out.println("现在工作的参与者是"+ti.getActorId());
//获取该工作的路由
List<Transition> tns = ti.getTask().getTaskNode().getLeavingTransitions();
for(Transition tn : tns) {
System.out.println("该工作的所有路由"+tn.getName());
}
输出结果:
NodeName:state1
通过Action类来解决问题!!!
NodeName:node1
NodeName:state2
NodeName:task1
现在工作的参与者是用户
该工作的所有路由tobf
三、beanShell脚本、Assignment应用
<?xml version="1.0" encoding="UTF-8"?>
<process-definition
xmlns="urn:jbpm.org:jpdl-3.2" name="example003">
<start-state name="start">
<transition name="" to="task1"></transition>
</start-state>
<task-node name="task1">
<task>
<assignment class="jbpm.java.handler.example.TestAssignment"></assignment>
<assignment actor-id="用户001"/>
</task>
<event type="node-enter">
<script>
print("当前节点对象的ID:"+token.getId());
contextInstance = executionContext.getContextInstance();
print("流程变量param的值:"+contextInstance.getVariable("param"));
print("直接获取变量值:"+param);
</script>
</event>
<transition name="" to="end1"></transition>
</task-node>
<end-state name="end1"></end-state>
</process-definition>
TestAssignment.java
public class TestAssignment implements AssignmentHandler{
private static final long serialVersionUID = 1443420479356838909L;
@Override
public void assign(Assignable assignable, ExecutionContext executionContext) throws Exception {
assignable.setActorId("用户001");
}
}
JbpmContext jbpmContext = getJbpmContext();
GraphSession graphSession=jbpmContext.getGraphSession();
ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition(processName);
ProcessInstance processInstance = new ProcessInstance(processDefinition);
ContextInstance contextInstance = processInstance.getContextInstance();
contextInstance.setVariable("param", "参数param值");
Token token = processInstance.getRootToken();
token.signal();
logger.info("NodeName:"+token.getNode().getName());
token.signal();
logger.info("NodeName:"+token.getNode().getName());
结果如下:
当前节点对象的ID:23
流程变量param的值:param的值
直接获取变量值:param的值
NodeName:task1
NodeName:end1
现在工作的参与者是用户001
四、fork join 节点
discriminator = true 经过一个节点,则结束。 一般开发不使用。
默认情况下join会等到所有从fork上生成的子token都到达join节点时,才会继续向下。
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="example004">
<start-state name="start">
<transition name="" to="fork1"></transition>
</start-state>
<fork name="fork1">
<script>
<variable name="transNames" access="write"></variable>
<expression>
transNames = new ArrayList();
if(param>100){
transNames.add("tr1");
transNames.add("tr2");
}else{
transNames.add("tr3");
transNames.add("tr4");
}
</expression>
</script>
<transition name="tr1" to="node1"></transition>
<transition name="tr2" to="node2"></transition>
<transition name="tr3" to="node3"></transition>
<transition name="tr4" to="node4"></transition>
</fork>
<node name="node1">
<event type="node-enter">
<script>
print("进入第一个节点");
</script>
</event>
<transition name="" to="join1"></transition>
</node>
<node name="node2">
<event type="node-enter">
<script>
print("进入第二个节点");
</script>
</event>
<transition name="" to="join1"></transition>
</node>
<node name="node3">
<event type="node-enter">
<script>
print("进入第三个节点");
</script>
</event>
<transition name="" to="join1"></transition>
</node>
<node name="node4">
<event type="node-enter">
<script>
print("进入第四个节点");
</script>
</event>
<transition name="" to="join1"></transition>
</node>
<join name="join1">
<transition name="" to="end1"></transition>
</join>
<end-state name="end1">
<event type="node-enter">
<script>
print("结束操作");
</script>
</event>
</end-state>
</process-definition>
JbpmContext jbpmContext = getJbpmContext();
GraphSession graphSession=jbpmContext.getGraphSession();
ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition(processName);
ProcessInstance processInstance = new ProcessInstance(processDefinition);
processInstance.getContextInstance().setVariable("param", new Integer(11));
Token token = processInstance.getRootToken();
token.signal();
logger.info("NodeName:"+token.getNode().getName());
结果如下:
进入第三个节点
进入第四个节点
结束操作
NodeName:end1
四、Decision节点
定义流程走向节点,在本节点上添加多个Transtion,和Fork相反,只能在多个Transition内选择一个。
A:未指定decision线路。
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="example005">
<start-state name="start">
<transition name="" to="decision1"></transition>
</start-state>
<decision name="decision1">
<transition name="tr1" to="node1"></transition>
<transition name="tr2" to="node2"></transition>
<transition name="tr3" to="node3"></transition>
</decision>
<node name="node1">
<event type="node-enter">
<script>
print("进入第一个节点");
</script>
</event>
<transition name="" to="end1"></transition>
</node>
<node name="node2">
<event type="node-enter">
<script>
print("进入第二个节点");
</script>
</event>
<transition name="" to="end1"></transition>
</node>
<node name="node3">
<event type="node-enter">
<script>
print("进入第三个节点");
</script>
</event>
<transition name="" to="end1"></transition>
</node>
<end-state name="end1">
<event type="node-enter">
<script>
print("结束操作");
</script>
</event>
</end-state>
</process-definition>
String processName = (String)Persistence.getVariable("processName");
logger.info("processName:"+processName);
JbpmContext jbpmContext = getJbpmContext();
GraphSession graphSession=jbpmContext.getGraphSession();
ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition(processName);
ProcessInstance processInstance = new ProcessInstance(processDefinition);
Token token = processInstance.getRootToken();
token.signal();
logger.info("NodeName:"+token.getNode().getName());
只要经过一个节点,就可以继续向下流转。没指定默认进入第一个。
结果如下:
进入第一个节点
结束操作
NodeName:end1
end
B:通过表达式变量程序内指定方式指定decision线路
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="example005">
<start-state name="start">
<transition name="" to="decision1"></transition>
</start-state>
<decision name="decision1" expression="#{tname}">
<transition name="tr1" to="node1"></transition>
<transition name="tr2" to="node2"></transition>
<transition name="tr3" to="node3"></transition>
</decision>
<node name="node1">
<event type="node-enter">
<script>
print("进入第一个节点");
</script>
</event>
<transition name="" to="end1"></transition>
</node>
<node name="node2">
<event type="node-enter">
<script>
print("进入第二个节点");
</script>
</event>
<transition name="" to="end1"></transition>
</node>
<node name="node3">
<event type="node-enter">
<script>
print("进入第三个节点");
</script>
</event>
<transition name="" to="end1"></transition>
</node>
<end-state name="end1">
<event type="node-enter">
<script>
print("结束操作");
</script>
</event>
</end-state>
</process-definition>
JbpmContext jbpmContext = getJbpmContext();
GraphSession graphSession=jbpmContext.getGraphSession();
ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition(processName);
ProcessInstance processInstance = new ProcessInstance(processDefinition);
processInstance.getContextInstance().setVariable("tname", "tr2");
Token token = processInstance.getRootToken();
token.signal();
logger.info("NodeName:"+token.getNode().getName());
结果:
进入第二个节点
结束操作
NodeName:end1
end
C:通过DecisionHandler方式指定decision线路
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="example005">
<start-state name="start">
<transition name="" to="decision1"></transition>
</start-state>
<decision name="decision1">
<handler class="jbpm.java.handler.example.TestDecision"/>
<transition name="tr1" to="node1"></transition>
<transition name="tr2" to="node2"></transition>
<transition name="tr3" to="node3"></transition>
</decision>
<node name="node1">
<event type="node-enter">
<script>
print("进入第一个节点");
</script>
</event>
<transition name="" to="end1"></transition>
</node>
<node name="node2">
<event type="node-enter">
<script>
print("进入第二个节点");
</script>
</event>
<transition name="" to="end1"></transition>
</node>
<node name="node3">
<event type="node-enter">
<script>
print("进入第三个节点");
</script>
</event>
<transition name="" to="end1"></transition>
</node>
<end-state name="end1">
<event type="node-enter">
<script>
print("结束操作");
</script>
</event>
</end-state>
</process-definition>
TestDecision.java
public class TestDecision implements DecisionHandler {
private static final long serialVersionUID = -9083605280987838663L;
@Override
public String decide(ExecutionContext executionContext) throws Exception {
return "tr3";
}
}
JbpmContext jbpmContext = getJbpmContext();
GraphSession graphSession=jbpmContext.getGraphSession();
ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition(processName);
ProcessInstance processInstance = new ProcessInstance(processDefinition);
Token token = processInstance.getRootToken();
token.signal();
logger.info("NodeName:"+token.getNode().getName());
结果:
进入第三个节点
结束操作
NodeName:end1
end
五、根据参与者actor-id取到对应任务、根据任务ID取得实例
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="example008">
<start-state name="start">
<transition name="" to="task1"></transition>
</start-state>
<task-node name="task1">
<event type="task-create">
<script>
print("触发了task-create事件");
</script>
</event>
<event type="task-start">
<script>
print("触发了task-start事件");
</script>
</event>
<event type="task-assign">
<script>
print("触发了task-assign事件");
</script>
</event>
<event type="task-end">
<script>
print("触发了task-end事件");
</script>
</event>
<task>
<assignment actor-id="admin001"></assignment>
</task>
<transition name="" to="end1"></transition>
</task-node>
<end-state name="end1"></end-state>
</process-definition>
JbpmContext jbpmContext = getJbpmContext();
GraphSession graphSession=jbpmContext.getGraphSession();
ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition(processName);
ProcessInstance processInstance = new ProcessInstance(processDefinition);
Token token = processInstance.getRootToken();
token.signal();
logger.info("NodeName:"+token.getNode().getName());
//根据参与者actor-id取到对应任务
List<TaskInstance> taskInstance = jbpmContext.getTaskMgmtSession().findTaskInstances("admin001");
for(TaskInstance ti : taskInstance){
logger.info("actor-id:"+ti.getName());
}
输出结果:
触发了task-create事件
触发了task-assign事件
NodeName:task1
actor-id:task1
JbpmContext jbpmContext = getJbpmContext();
GraphSession graphSession=jbpmContext.getGraphSession();
ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition(processName);
ProcessInstance processInstance = new ProcessInstance(processDefinition);
Token token = processInstance.getRootToken();
token.signal();
logger.info("NodeName:"+token.getNode().getName());
//根据任务ID取得实例
TaskInstance taskInstance = jbpmContext.loadTaskInstance(taskInstanceId);
logger.info("actor-id:"+taskInstance.getName());/
输出结果如下:
触发了task-create事件
触发了task-assign事件
NodeName:task1
actor-id:task1
六、Swimlane方式
用于处理一个流程中多个任务节点由同一个人或者角色来完成。
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="example009">
<swimlane name="user">
<assignment actor-id="#{userId}"></assignment>
</swimlane>
<start-state name="start">
<transition name="" to="task1"></transition>
</start-state>
<task-node name="task1">
<event type="task-create">
<script>
print("触发了task-create事件");
</script>
</event>
<event type="task-start">
<script>
print("触发了task-start事件");
</script>
</event>
<event type="task-assign">
<script>
print("触发了task-assign事件");
</script>
</event>
<event type="task-end">
<script>
print("触发了task-end事件");
</script>
</event>
<task swimlane="user"/>
<transition name="" to="end1"></transition>
</task-node>
<end-state name="end1"></end-state>
</process-definition>
JbpmContext jbpmContext = getJbpmContext();
GraphSession graphSession=jbpmContext.getGraphSession();
ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition(processName);
ProcessInstance processInstance = new ProcessInstance(processDefinition);
processInstance.getContextInstance().setVariable("userId", "admin002");
Token token = processInstance.getRootToken();
token.signal();
logger.info("NodeName:"+token.getNode().getName());
List<TaskInstance> taskInstance = jbpmContext.getTaskMgmtSession().findTaskInstances("admin002");
for(TaskInstance ti : taskInstance){
logger.info("actor-id:"+ti.getName());
}
输出结果:
触发了task-create事件
触发了task-assign事件
NodeName:task1
actor-id:task1
七、pooled-actors方式
一个任务直接分配给多个参与者,多个参与者用逗号隔开。
例如:提交给一个部门,该部门的人都能看到,其中一个人处理就可以了。
这种方式只能静态分配,不能动态分配。所以适用范围有限。
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="example010">
<start-state name="start">
<transition name="" to="task1"></transition>
</start-state>
<task-node name="task1">
<event type="task-create">
<script>
print("触发了task-create事件");
</script>
</event>
<event type="task-start">
<script>
print("触发了task-start事件");
</script>
</event>
<event type="task-assign">
<script>
print("触发了task-assign事件");
</script>
</event>
<event type="task-end">
<script>
print("触发了task-end事件");
</script>
</event>
<task>
<assignment pooled-actors="admin001,admin002,admin003"></assignment>
</task>
<transition name="" to="end1"></transition>
</task-node>
<end-state name="end1"></end-state>
</process-definition>
JbpmContext jbpmContext = getJbpmContext();
GraphSession graphSession=jbpmContext.getGraphSession();
ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition(processName);
ProcessInstance processInstance = new ProcessInstance(processDefinition);
Token token = processInstance.getRootToken();
token.signal();
logger.info("NodeName:"+token.getNode().getName());
List<TaskInstance> taskInstance = jbpmContext.getTaskMgmtSession().findPooledTaskInstances("admin001");
for(TaskInstance ti : taskInstance){
logger.info("pooled-actors:"+ti.getName());
}
输出结果如下:
触发了task-create事件
NodeName:task1
pooled-actors:task1
七、发送mail提醒
A、建立邮件服务。
下载james-2.3.2,解压。进入dos命令行模式,进入C:\james-2.3.2\bin,执行run.bat
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZwpmLzUzNy8VO1kTMzgDO1MTMvwlMy8CXxAzMxAjMvw1ckF2bsBXdvwFdl5mLuR2cj5Set1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
例图所示邮件服务器启动完毕,请不要关闭dos窗口。
pop3,smtp,等信息显示如上。
再打开新的dos窗口。
输入telnet localhost 4555
提示输入用户名密码:都是root
之后输入help,可以看到命令帮助。
输入 adduser adminsender 123456
新增一个用户以及密码。新增完毕之后即可关闭此窗口,或者输入quit退出。
B、程序配置。
把jbpm-jpdl-3.2.3中的两个jar文件activation.jar、mail.jar放置工程中。
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="" name="example011">
<start-state name="start-state1">
<transition to="task-node1"></transition>
</start-state>
<task-node name="task-node1">
<task name="notifyTask" notify="true">
<assignment actor-id="adminsender"></assignment>
</task>
<transition to="end-state1"></transition>
</task-node>
<end-state name="end-state1"></end-state>
</process-definition>
或者使用下面流程文件:
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="" name="example012">
<start-state name="start-state1">
<transition to="task-node1"></transition>
</start-state>
<task-node name="task-node1">
<task name="notifyTask">
<assignment actor-id="adminsender"/>
<event type="task-assign">
<mail template="task-assign"/>
</event>
</task>
<transition to="end-state1"></transition>
</task-node>
<end-state name="end-state1"></end-state>
</process-definition>
注意 xmlns="" ,里面暂时为空。不能放入urn:jbpm.org:jpdl-3.2,否则会在部署的时候提示org.jbpm.jpdl.JpdlException: [[ERROR] line 12: cvc-complex-type.3.2.2: Attribute 'notify' is not allowed to appear in element 'task'.]
原因暂时不清数,不过去掉,即可正常部署。
建立MailResolver.java文件
package jbpm.java.mail;
import org.jbpm.mail.AddressResolver;
public class MailResolver implements AddressResolver{
private static final long serialVersionUID = 3634448991562190346L;
@Override
public Object resolveAddress(String actorId) {
if(actorId.equals("adminsender")){
return "[email protected]";
}else{
return "[email protected]";
}
}
}
修改jbpm.cfg.xml,加入如下内容:
<string name="resource.mail.templates" value="jbpm.mail.templates.xml"/>
<string name="jbpm.mail.smtp.host" value="localhost"/>
<string name="jbpm.mail.smtp.port" value="25"/>
<bean name="jbpm.mail.address.resolver" class="jbpm.java.mail.MailResolver" singleton="true"/>
<string name="jbpm.mail.from.address" value="[email protected]"/>
<string name="jbpm.mail.smtp.auth" value="true"/>
部署xml文件。执行
JbpmContext jbpmContext = getJbpmContext();
GraphSession graphSession=jbpmContext.getGraphSession();
ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition(processName);
ProcessInstance processInstance = new ProcessInstance(processDefinition);
Token token = processInstance.getRootToken();
token.signal();
logger.info("NodeName:"+token.getNode().getName());
提示
java.lang.NoClassDefFoundError: com/sun/mail/util/LineInputStream错误。
主要原因是javax.mail和javax.activation这两个包已经在javaEE5当中属于基础包了,但是里面的方法与现在jbpm提供的的mail.jar和activation.jar有一些出入
X:/Program Files/MyEclipse 6.5/myeclipse/eclipse/plugins/com.genuitec.eclipse.j2eedt.core_6.5.0.zmyeclipse650200806/data/libraryset/EE_5
这个路径里,可以看到javaee.jar,用rar把这个文件打开,然后进到javax文件夹里,删除mail.jar和activation.jar。注意备份。
之后执行,则通过。
八、任务调度