JBOSS工作流与JBPM开发实例

日期: 2010-12-01 来源:TechTarget中国 英文

  首先当你想学一个框架的时候一定是你要有项目来用他了,OK,那么你项目当中的流程是什么你应该清楚吧,那么当你清楚了这些的时候我们就开始我们这个最简单的例子吧。

    假如我们现在有这么一个例子,公司员工想报销点出差费,那么他要将他的申请提交给他的第一级领导——部门主管去审批。

    然后部门主管审批完了之后还要交给这个部门主管的上级公司老总进行审批。那么针对这个简单的流程,我们应该从哪里下手呢?

    首先第一件事情就是写流程定义文件,那么这个文件我们用什么来写呢,他就是一个符合某个语法的xml文件,幸运的是jbpm给我们提供了一个集成的开发环境让我们来用。

    首先去官网上下一个jbpm-jpdl-suite-3.2.GA包,解压后你会发现他里面有一个designer文件夹,那个里面就是我们写流程定义文件的开发环境,他是一个eclipse的插件。

    但是好像他给我们的那个eclipse版本有问题,建议大家从新下一个eclipse-SDK-3.2.1-win32.zip这个版本的eclipse,然后覆盖他给我们提供的那个。

    准备工作做完了,那么我们就开始吧,首先我们打开解压目录下的designer文件夹中的designer.bat文件,他弹出一个eclipse,然后我们就用这个东西来开发我们的流程定义文件了。

    打开之后你就会看见一个他的小例子,不过我们不去用他,我们自己新建一个工程。右键-new-other-jBoss jbpm-process project.这个时候你会看见他弹出一个对话框,输入你的工程名字,然后点击next,这个时候你会发现他已经把jbpm加载进去了,记住要选中 Generate simple ……。

    工程建立完了,我们开始建立我们的流程定义文件。在工程里面你会发现src/main/jpdl这个source folder,然后你会看见他里面已经有了一个流程定义文件了,但是我们不去用他的。

    我们自己建立一个,右键src/main/jpdl,然后new-other- jBoss jbpm-process definition.这个时候他就会弹出一个对话框,起一个你要写的流程定义文件的名字输入进去,OK,可以了。这个时候你打开你建立的那个文件夹,里 面就有processdefinition.xml文件,ok,打开他。

    在右面的图里面你就可以看到一张什么都没有的白纸,我们看看这部分左面的那些东西,什么start,end,tasknode,fork,join.

    那我们来解释一下这是个什么东西呢,我们看看我们的需求,员工要写一个报销单,然后交给部门主管来处理,那么部门主管就应该算是一个tasknode,他就是一个任务节点。

    start和end其实就是一个虚状态,当我们写完报销单的时候我们就提交了,这个时候他就到了第一个tasknode这个节点了。然后他审批完了还要交给总经理审批,那么他又是一个tasknode,然后总经理审批完了结束,ok,是一个end.

    start——》tasknode(部门主管审批)——》tasknode(总经理审批)——》end.

    如果觉得看的有点模糊可以看看我传上来的那个图。然后你在这个试图框的下面可以看到有个source,点击一下,就会发现他已经自动的给你生成xml代码了。

    但是这样还是有点不够,我们只是定义了一个tasknode节点,并没有定义tasknode节点的任务由谁来做。那么我们还要定义一个tasknode节点是由谁来做的:那么这段代码是这么写的:

以下是引用片段:
<?xml version=”1.0″ encoding=”UTF-8″?>
<process-definition
    name=”test1″>
   <start-state name=”start”>
      <transition name=”” to=”部门经理审批”></transition>
   </start-state>
   <task-node name=”部门经理审批”>
      <task>
       <assigment actorId=”部门经理”></assigment>
      </task>
      <transition name=”” to=”总经理审批”></transition>
   </task-node>
   <task-node name=”总经理审批”>
      <task>
       <assigment actorId=”总经理”></assigment>
      </task>
      <transition name=”” to=”end1″></transition>
   </task-node>
   <end-state name=”end1″></end-state>
</process-definition> 

    这样的话我们的流程定义文件就定义完了,但是这只是把文件定义完了,系统并不知道啊,所以我们还要把我们的文件部署到系统中去。

    首先我们在src/main/java里面新建立一个包,然后建立一个class,随便起个名字,就叫 TestJBPM_01吧,那么在这个类里面我们要做的是什么呢?我们要先导入表,因为jbpm要运行就要用到很多个表,ok,那么我们这个里面导入表和 hibernate导入表是差不多的,它的代码是这样的:

以下是引用片段:
package com.jbpm.test;
import junit.framework.TestCase;
import org.jbpm.JbpmConfiguration;
public class TestJbpm_01 extends TestCase {
 
 public void testJbpm(){
  
  //创建jbpm数据库表。他就像hibernate里面的哪个export一样。实际上他就是hibernate里面的哪个export。
  //应为他映射了很多个表,所以我们就能创建那么多个表。
  JbpmConfiguration.getInstance().createSchema();
  
 }

    然后呢我们就开始部署我们的流程定义文件,我们将这个文件当中的内容呢放到数据库当中去,当我们以后再用的时候呢我们就随时的将它加载出来。

以下是引用片段:
package com.jbpm.test;
import junit.framework.TestCase;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.ProcessDefinition;
public class TestJbpm_02 extends TestCase {
 
 //jbpmConfiguration对象的创建
 static JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
 
 public void testJbpm(){
  
  //然后我们把processDefinition里面相关的对象持久化到数据库里面去。
  //流程定义文件里面有很多个概念,他有node,有transition,还有processDefinition,那么我们不需要一个
  //一个保存,jbpm把保存这么多对象的方法封装成一个接口,叫做deployProcessDefinition。我们只要调用这个
  //方法,传一个processDefinition对象,我们就能将他们存入到数据库里面去。
  
  //这个首先第一步我们要得到一个processDefinition对象,然后我们把他部署到流程中去。
  ProcessDefinition processDefinition = ProcessDefinition.parseXmlResource(“testJBPM/testJbpm.xml”);
  //我们要存就必须获得一个session对象,而jbpm已经把session对象封装到一个JbpmContext对象里面了。
  //那么这个jbpmContext对象是怎么得到的呢,我们要先有一个jbpmConfiguration对象,我们要对数据库进行
  //操作的时候一定要有jbpmConfiguration这个对象,用他来创建一个类似于hibernate当中的session一样的
  //对象——jbpmContext。他是我们对数据库所有的操作的一个接口。
  JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
  try{
   //然后部署的操作已经由jbpmContext给我们创建好了,我们只需要调一下他的一个方法就可以了。
   jbpmContext.deployProcessDefinition(processDefinition);
  }finally{
   //最后我们还要对他close一下,就像我们用hibernate的时候要close session一样。
   jbpmContext.close();
  }
 }

   第二步我们也做完了,那么现在我们开始做第三步,也就是说,我们流程定义文件写好了,现在我们的系统当中有了这样一个报销流程。

    那么就开始实际的去用她吧,一个人小报销了,那么她就要写一个报销的申请,但是这个 报销的申请写完了存到数据库当中了还不能算完了,应该和我们的这个流程关联起来啊,那么她应该怎么去关联呢,我们在建立这个申请单这个类的时候应该定义一 个processInstanceId属性,她是一个long型的。

    记录这我们的这个流程实例的id,那么什么是流程实例 (processInstance)呢,她是我们工作流当中第二重要的概念,他和流程定义的关系就相当于对象和类之间的关系,类是一个抽象的东西,她定义 完了是什么也干不了的,要想用她内部定义的东西我们就要new出一个实例来,当然这个里面也是这样的。

    那么也就是说,当我们创建这个报销申请的时候我们就要先根据这个流程‘new’出一个流程实例来存到数据库当中,然后在把她的id传给报销申请对象然后再将这个报销申请对象存到数据库当中。那么这个代码是这样的:

以下是引用片段:
package com.jbpm.test;
import junit.framework.TestCase;
import org.hibernate.Session;
public class TestJbpm_03 extends TestCase {
 
 public void testJbpm(){
  Session session = null;
  try{
   session = HibernateUtil.getSession();
   session.beginTransaction();
   
   Document doc = new Document();
   doc.setTitle(“title3”);
   doc.setContent(“this is content3”);
   session.save(doc);      
   session.getTransaction().commit();
  }catch(Exception e){
   e.printStackTrace();
   session.getTransaction().rollback();
  }finally{
   HibernateUtil.closeSession(session);
  }
 }

package com.jbpm.test;
import junit.framework.TestCase;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
/**
/*
/*将申请单和流程实例绑定
**/
public class TestJbpm_04 extends TestCase {
 
 static JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
 
 public void testJbpm(){
  
  JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
  jbpmContext.setSessionFactory(HibernateUtil.getSessionFactory());
  try {
   ProcessDefinition processDefinition = jbpmContext.getGraphSession().findLatestProcessDefinition(“testJbpm”);
   ProcessInstance processInstance = new ProcessInstance(processDefinition);
   jbpmContext.save(processInstance);  
   
   
   //将我们的document和instance绑定。
   long processInstanceId = processInstance.getId();
   Document document = (Document)jbpmContext.getSession().load(Document.class,1);
   document.setProcessInstanceId(processInstanceId);
   jbpmContext.getSession().update(document);
   processInstance.getContextInstance().setVariable(“document”, document.getId());
  }catch(Exception e){
   e.printStackTrace();
  }finally{
   jbpmContext.close();
  }
  
 }

    现在我们的申请已经和实例关联起来了,那么接下来的下一步就开始用啦,就是让 这个申请流转起来吧,那么她应该怎么去流转呢,嘿嘿,jbpm给我们提供一个signal方法,每当执行一次这个方法的时候她就流转一下到下一个节点,你 可以打印出当前节点试一下,看看是不是执行一次你的当前节点就换一下。这段代码是这样的:

以下是引用片段:
package com.jbpm.test;
import junit.framework.TestCase;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.exe.ProcessInstance;
public class TestJbpm_05 extends TestCase {
 
 static JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
 
 public void testJbpm(){
  JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
  jbpmContext.setSessionFactory(HibernateUtil.getSessionFactory());
  try{
   
   Document document = (Document)jbpmContext.getSession().load(Document.class, 3);
   long processInstanceId = document.getProcessInstanceId();
   ProcessInstance processInstance = jbpmContext.getProcessInstance(processInstanceId);
   processInstance.signal();
  }finally{
   jbpmContext.close();
  }
 }

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐

  • API创建影响生产的六个方面

    在API创建方面,简单性至关重要。AnyPresence的Vivek Gupta讨论了开发者可以从6个方面处理好API的创建问题,从而加速API生产。

  • 微服务:是谁看上了这块小鲜肉

    微服务——IT领域的又一个新名词。但它是否能如同OpenStack,如同Docker那样成为众人疯抢的“肥肉”呢?从目前来看,可能还没有到达疯抢的地步,但也不乏支持者。

  • 应用开发工具帮助报社与时俱进

    新闻媒体业务要一直向顶尖技术看齐,如果他们想要打败竞争对手,成为社会的脉搏的话。心态一直是最重要的,无论是在收集和报道新闻方面,还是在内部运营方法。

  • 为移动工作者赋权构建API及工作流的步骤

    主管不能简单地把移动工作者认为是不坐在一起的人。相反,赋权要从评估员工需求开始,因为接下来关键的速度爆发当然就必须来自于移动设备和宽带服务的利用。