`
jeffen2006
  • 浏览: 255090 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

重新看待jbpm的流程定义

阅读更多

jbpm的流程定义从发布上看有2种方式,一种是发布持久化到关系型数据库中,另一种则是由java代码实时生成。

之前一直关注持久化的方式,每次都是生成好固定的xml文件,然后发布到数据中,然后再从数据库中检索出来使用。

不过通过2天的学习,第二种代码生成的方式有着第一种持久化方式所不能替代的优点。下面通过一个简单但是非常实用的例子来说明。

网上有很多人在问,fork分出去的多条路线,为什么一定要全部到达join后才能延续流程,能不能其中部分路线到达后流程就继续呢。很多人通过了很复杂的方法实现了这个功能。下面我就介绍一个简单的办法,在fork下增加script元素:

  1. package com.jeffentest;   
  2. import org.jbpm.*;   
  3. import org.jbpm.graph.def.ProcessDefinition;   
  4. import org.jbpm.graph.exe.*;   
  5. import org.jbpm.context.exe.ContextInstance;   
  6.   
  7.   
  8. public class Jeffentest {   
  9.     static JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();   
  10.     static ProcessDefinition processDefinition = null;   
  11.     static ProcessInstance processInstance = null;   
  12.     //static SchedulerSession schedulerSession =null;   
  13.     private static void run(){   
  14.         //JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();   
  15.         try {   
  16.             processDefinitionProcessDefinition.parseXmlString(   
  17.                       "<process-definition>" +   
  18.                       "  <start-state name='start'>" +   
  19.                       "    <transition to='a' />" +   
  20.                       "  start-state>" +   
  21.                       "  <state name='a'>" +   
  22.                       "    <transition to='multichoice' />" +   
  23.                       "  state>" +   
  24.                       "  <fork name='multichoice'>" +   
  25.                       "    <script>" +   
  26.                       "      <variable name='transitionNames' access='write' />" +   
  27.                       "      <expression>" +   
  28.                       "        transitionNames = new ArrayList();" +   
  29.                       "        if ( scenario == 1 ) {" +   
  30.                       "          transitionNames.add( \"to b\" );" +   
  31.                       "        } else if ( scenario == 2 ) {" +   
  32.                       "          transitionNames.add( \"to c\" );" +   
  33.                       "        } else if ( scenario >= 3 ) {" +   
  34.                       "          transitionNames.add( \"to b\" );" +   
  35.                       "          transitionNames.add( \"to c\" );" +   
  36.                       "        }" +   
  37.                       "      expression>" +   
  38.                       "    script>" +   
  39.                       "    <transition name='to b' to='b' />" +   
  40.                       "    <transition name='to c' to='c' />" +   
  41.                       "  fork>" +   
  42.                       "  <state name='b'>" +   
  43.                       "    <transition to='syncmerge' />" +   
  44.                       "  state>" +   
  45.                       "  <state name='c'>" +   
  46.                       "    <transition to='syncmerge' />" +   
  47.                       "  state>" +   
  48.                       "  <join name='syncmerge'>" +   
  49.                       "    <transition to='end' />" +   
  50.                       "  join>" +   
  51.                       "  <end-state name='end'>end-state>" +   
  52.                       "process-definition>"   
  53.                     );   
  54.             processInstancenew ProcessInstance(processDefinition);   
  55.             ContextInstance ci = (ContextInstance) processInstance.getInstance( ContextInstance.class );   
  56.             Token root = processInstance.getRootToken();   
  57.             System.out.println(root.getNode());//StartState(start)   
  58.             root.signal();   
  59.             System.out.println(root.getNode());//State(a)   
  60.             ci.setVariable( "scenario", new Integer(2) );   
  61.             root.signal();   
  62.             Token tokenB = root.getChild("to b");    
  63.             Token tokenC = root.getChild("to c");   
  64.             System.out.println(root.getNode());//Fork(multichoice)   
  65.             System.out.println("tokenC:"+tokenC.getNode());//tokenC:State(c)   
  66.             tokenC.signal();   
  67.             System.out.println("tokenC:"+tokenC.getNode());//tokenC:Join(syncmerge)   
  68.             System.out.println(root.getNode());//EndState(end)   
  69.                
  70.         }catch(Exception e){   
  71.             e.printStackTrace();   
  72.         }finally {   
  73.               //jbpmContext.close();   
  74.         }   
  75.     }      
  76.     public static void main(String[] args) {   
  77.         run();   
  78.     }   
  79. }   

运行结果如下:

StartState(start)
State(a)
Fork(multichoice)
tokenC:State(c)
tokenC:Join(syncmerge)
EndState(end)

大家看到了,fork出去2条路线b/c,c完成了而b没有完成,但是整个流程已经结束了。

这里有一点需要注意,这种方式仅仅适合代码生成流程定义,如果你想通过持久化流程定义到数据库的方式,那么结果就仍然要等待路线b的完成了。为什么呢?因为这是jbpm3.1.2的限制:the script in a fork is not persisted.  script in fork might be removed in later versions of jPDL.

有兴趣的朋友可以验证一下。

还有一个节点类型Merge也是同样的情况,它有一个Synchronized属性。对于这个节点jbpm的开发者有这么一段话,大家见仁见智吧。
/**
 * TODO is the merge node usefull ?
 * i don't think the merge node is usefull because every node has an
 * implicit merge in front of it (= multiple transitions can arrive in
 * the same node).  maybe we should just leave this in for the sake
 * of workflow patterns ?
 */
附:merge的使用语句
Merge merge = (Merge) processDefinition.getNode("xor");
merge.setSynchronized( false );

 

分享到:
评论
4 楼 LeanderSaka 2007-03-15  
最近正好在做JBPM的东西,由java代码实时生成的是真的没有试过,感谢LG了。
3 楼 jevy30 2007-03-09  
写join即可实现,如下:
<join name="join" >
      <event type="node-enter">
         <script>org.jbpm.graph.node.Join join = (org.jbpm.graph.node.Join)node;join.setDiscriminator(true);</script>
      </event>
    <transition to="end" />
  </join> 
2 楼 skllb 2007-01-15  
标题正是我正在研究的, 呵、内容有点不符、
1 楼 jeffen2006 2006-12-01  
java代码中的xml不能正确显示,csdn就可以。

相关推荐

Global site tag (gtag.js) - Google Analytics