天天看点

JBPM笔记-基础范例

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

JBPM笔记-基础范例

例图所示邮件服务器启动完毕,请不要关闭dos窗口。

pop3,smtp,等信息显示如上。

再打开新的dos窗口。

JBPM笔记-基础范例

输入telnet localhost 4555

JBPM笔记-基础范例

提示输入用户名密码:都是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。注意备份。

之后执行,则通过。

八、任务调度