1. 程式人生 > >利用JBPM4.4的AssignmentHandler實現使用者角色整合另一種構思

利用JBPM4.4的AssignmentHandler實現使用者角色整合另一種構思

Jbpm4提供的IdentitySession介面並不是一種很好的處理方式,鑑於我們每個業務系統都有一套自己的使用者及許可權認證管理機制,需要與jbpm4.4整合的話,就比較周折了,我們經常需要查詢的就是使用者自己的任務。jbpm4的任務裡有一個比較好的任務人員指派定義方式,就是使用AssignmentHandler介面,其定義如下所示:

Java程式碼 複製程式碼
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <process name="TaskAssignmentHandler" xmlns="http://jbpm.org/4.4/jpdl"
    >   
  3.   <start g="20,20,48,48">   
  4.     <transition to="review" />   
  5.   </start>   
  6.   <task name="review" g="96,16,127,52">   
  7.     <assignment-handler class="org.jbpm.examples.task.assignmenthandler.AssignTask">   
  8.       <field name="assignee">   
  9.         <string value=
    "johndoe" />   
  10.       </field>   
  11.     </assignment-handler>   
  12.     <transition to="wait" />   
  13.   </task>   
  14.   <state name="wait" g="255,16,88,52" />   
  15. </process>  
<?xml version="1.0" encoding="UTF-8"?>

<process name="TaskAssignmentHandler" xmlns="http://jbpm.org/4.4/jpdl">

  <start g="20,20,48,48">
    <transition to="review" />
  </start>

  <task name="review" g="96,16,127,52">
    <assignment-handler class="org.jbpm.examples.task.assignmenthandler.AssignTask">
      <field name="assignee">
        <string value="johndoe" />
      </field>
    </assignment-handler>
    <transition to="wait" />
  </task>

  <state name="wait" g="255,16,88,52" />

</process>
Java程式碼 複製程式碼
  1. package org.jbpm.examples.task.assignmenthandler;   
  2. import org.jbpm.api.model.OpenExecution;   
  3. import org.jbpm.api.task.Assignable;   
  4. import org.jbpm.api.task.AssignmentHandler;   
  5. /**  
  6.  * @author Tom Baeyens  
  7.  */
  8. publicclass AssignTask implements AssignmentHandler {   
  9. privatestaticfinallong serialVersionUID = 1L;   
  10.   String assignee;   
  11. publicvoid assign(Assignable assignable, OpenExecution execution) {   
  12.     assignable.setAssignee(assignee);   
  13.   }   
  14. }  
package org.jbpm.examples.task.assignmenthandler;

import org.jbpm.api.model.OpenExecution;
import org.jbpm.api.task.Assignable;
import org.jbpm.api.task.AssignmentHandler;


/**
 * @author Tom Baeyens
 */
public class AssignTask implements AssignmentHandler {
  
  private static final long serialVersionUID = 1L;

  String assignee;

  public void assign(Assignable assignable, OpenExecution execution) {
    assignable.setAssignee(assignee);
  }
}

 這要求我們在設計流程定義後,任務的處理人已經必須定下來了,但若我們在流程釋出後,還需要手工改這裡的任務執行人員(並且人員是我們系統的使用者),甚至人員可能在流程執行過程中,由使用者在任務表單或計算過程中動態指定,以上的方式並不能滿足我們的要求。

基於這種想法,應該設計另一種允許使用者修改流程定義中的人員,並且跟我們的系統使用者角色結合起來。

jbpm4之後的版本,啟動流程及執行流程時,都會去讀取流程定義,因此,我們可以動態修改以上配置檔案,讓其生成類似如下的配置格式即可以滿足我們的要求:

Java程式碼 複製程式碼
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <process name="TaskAssignmentHandler" xmlns="http://jbpm.org/4.4/jpdl">   
  3.   <start g="20,20,48,48">   
  4.     <transition to="review" />   
  5.   </start>   
  6.   <task name="review" g="96,16,127,52">   
  7.     <assignment-handler class="com.htsoft.core.jbpm.AssignmentHandler">   
  8.       <field name="userIds">   
  9.         <string value="1" />   
  10.       </field>   
  11.      <field name="roleIds">   
  12.         <string value="1,2" />   
  13.       </field>   
  14.     </assignment-handler>   
  15.     <transition to="wait" />   
  16.   </task>   
  17.   <state name="wait" g="255,16,88,52" />   
  18. </process>  
<?xml version="1.0" encoding="UTF-8"?>

<process name="TaskAssignmentHandler" xmlns="http://jbpm.org/4.4/jpdl">

  <start g="20,20,48,48">
    <transition to="review" />
  </start>

  <task name="review" g="96,16,127,52">
    <assignment-handler class="com.htsoft.core.jbpm.AssignmentHandler">
      <field name="userIds">
        <string value="1" />
      </field>
     <field name="roleIds">
        <string value="1,2" />
      </field>
    </assignment-handler>
    <transition to="wait" />
  </task>

  <state name="wait" g="255,16,88,52" />

</process>

 以上的userIds的1,以及roleIds的1,2則代表我們系統中的使用者id與角色的id,其值由後臺使用者在後面通過介面來設定。

其設定後,就生成以上的程式碼寫至jbpm4_lob表中的blobvalue欄位中去則可,這是持久化的處理。

也可以臨時呼叫類似以下的程式碼動態實現以上效果:

Java程式碼 複製程式碼
  1. /**  
  2.      * 為流程定義加上任務的指派人員介面  
  3.      * @param deployId  
  4.      */
  5. publicvoid addAssignHandler(ProUserAssign proUserAssign){   
  6.         ProcessDefinitionImpl pd=(ProcessDefinitionImpl)repositoryService.createProcessDefinitionQuery().deploymentId(proUserAssign.getDeployId()).uniqueResult();   
  7.          EnvironmentFactory environmentFactory = (EnvironmentFactory) processEngine;   
  8.          EnvironmentImpl env=null;   
  9. try {   
  10.              env = environmentFactory.openEnvironment();   
  11. //找到任務的定義
  12.              TaskDefinitionImpl taskDef=pd.getTaskDefinition(proUserAssign.getActivityName());   
  13.              UserCodeReference userCodeReference = new UserCodeReference();   
  14.              ObjectDescriptor descriptor = new ObjectDescriptor();   
  15. //加上任務的人員動態指派
  16.              descriptor.setClassName("com.htsoft.core.jbpm.UserAssignHandler");   
  17. //動態加引數
  18.              FieldOperation userIdsFo = new FieldOperation();   
  19.              userIdsFo.setFieldName("userIds");    
  20.              userIdsFo.setDescriptor(new StringDescriptor(proUserAssign.getUserId()));   
  21.              FieldOperation groupIdsFo=new FieldOperation();   
  22.              groupIdsFo.setFieldName("groupIds");   
  23.              groupIdsFo.setDescriptor(new StringDescriptor(proUserAssign.getRoleId()));   
  24.              List<Operation> listOp=new ArrayList<Operation>();   
  25.              listOp.add(userIdsFo);   
  26.              listOp.add(groupIdsFo);   
  27.              descriptor.setOperations(listOp);   
  28.              userCodeReference.setCached(false);   
  29.              userCodeReference.setDescriptor(descriptor);   
  30.              taskDef.setAssignmentHandlerReference(userCodeReference);   
  31.          }catch(Exception ex){   
  32.              logger.error("ADD AssignHandler Error:" + ex.getMessage());   
  33.          }finally{   
  34. if(env!=null){   
  35.                  env.close();   
  36.              }   
  37.          }   
  38.     }  
/**
     * 為流程定義加上任務的指派人員介面
     * @param deployId
     */
    public void addAssignHandler(ProUserAssign proUserAssign){
    	ProcessDefinitionImpl pd=(ProcessDefinitionImpl)repositoryService.createProcessDefinitionQuery().deploymentId(proUserAssign.getDeployId()).uniqueResult();
    	 EnvironmentFactory environmentFactory = (EnvironmentFactory) processEngine;
		 EnvironmentImpl env=null;
		 try {
			 env = environmentFactory.openEnvironment();
			 //找到任務的定義
			 TaskDefinitionImpl taskDef=pd.getTaskDefinition(proUserAssign.getActivityName());
			 UserCodeReference userCodeReference = new UserCodeReference();
			 ObjectDescriptor descriptor = new ObjectDescriptor();
			 //加上任務的人員動態指派
			 descriptor.setClassName("com.htsoft.core.jbpm.UserAssignHandler");
			 //動態加引數
			 FieldOperation userIdsFo = new FieldOperation();
			 userIdsFo.setFieldName("userIds");	
			 userIdsFo.setDescriptor(new StringDescriptor(proUserAssign.getUserId()));
			 
			 FieldOperation groupIdsFo=new FieldOperation();
			 groupIdsFo.setFieldName("groupIds");
			 groupIdsFo.setDescriptor(new StringDescriptor(proUserAssign.getRoleId()));
			 
			 List<Operation> listOp=new ArrayList<Operation>();
			 listOp.add(userIdsFo);
			 listOp.add(groupIdsFo);
			 descriptor.setOperations(listOp);
			 
			 userCodeReference.setCached(false);
			 userCodeReference.setDescriptor(descriptor);
			 taskDef.setAssignmentHandlerReference(userCodeReference);
			 
		 }catch(Exception ex){
			 logger.error("ADD AssignHandler Error:" + ex.getMessage());
		 }finally{
			 if(env!=null){
				 env.close();
			 }
		 }
    }

不過該方式沒有持久久,重啟系統後,儲存的使用者及角色設定並不會生效。

UserAssignHandler類程式碼如下:

Java程式碼 複製程式碼
  1. package com.htsoft.core.jbpm;   
  2. import org.apache.commons.lang.StringUtils;   
  3. import org.apache.commons.logging.Log;   
  4. import org.apache.commons.logging.LogFactory;   
  5. import org.jbpm.api.model.OpenExecution;   
  6. import org.jbpm.api.task.Assignable;   
  7. import org.jbpm.api.task.AssignmentHandler;   
  8. import com.htsoft.core.Constants;   
  9. /**  
  10.  * 尚未開始使用  
  11.  * <B><P>Joffice -- http://www.jee-soft.cn</P></B>  
  12.  * <B><P>Copyright (C) 2008-2010 GuangZhou HongTian Software Company (廣州巨集天軟體有限公司)</P></B>   
  13.  * <B><P>description:</P></B>  
  14.  * <P></P>  
  15.  * <P>product:joffice</P>  
  16.  * <P></P>   
  17.  * @see com.htsoft.core.jbpm.UserAssignHandler  
  18.  * <P></P>  
  19.  * @author   
  20.  * @version V1  
  21.  * @create: 2010-11-23下午02:58:01  
  22.  */
  23. publicclass UserAssignHandler implements AssignmentHandler{   
  24. private Log logger=LogFactory.getLog(UserAssignHandler.class);   
  25. //授予使用者ID
  26.     String userIds;   
  27. //授權角色ID
  28.     String groupIds;   
  29. @Override
  30. publicvoid assign(Assignable assignable, OpenExecution execution) throws Exception {   
  31.         String assignId=(String)execution.getVariable(Constants.FLOW_ASSIGN_ID);   
  32.         logger.info("assignId:===========>" + assignId);   
  33. //在表單提交中指定了固定的執行人員
  34. if(StringUtils.isNotEmpty(assignId)){   
  35.             assignable.setAssignee(assignId);   
  36. return;   
  37.         }   
  38. //在表單中指定了執行的角色TODO
  39. //在表單中指定了會籤人員
  40.         String signUserIds=(String)execution.getVariable(Constants.FLOW_SIGN_USERIDS);   
  41. if(signUserIds!=null){   
  42. //TODO 取到該任務,進行會籤設定
  43.         }   
  44.         logger.debug("Enter UserAssignHandler assign method~~~~");   
  45. if(userIds!=null){//若使用者不為空
  46.             String[]uIds=userIds.split("[,]");   
  47. if(uIds!=null && uIds.length>1){//多於一個人的
  48. for(String uId:uIds){   
  49.                     assignable.addCandidateUser(uId);   
  50.                 }   
  51.             }else{   
  52.                 assignable.setAssignee(userIds);   
  53.             }   
  54.         }   
  55. if(groupIds!=null){//若角色組不為空
  56.             String[]gIds=userIds.split("[,]");   
  57. if(gIds!=null&& gIds.length>1){//多於一個角色的
  58. for(String gId:gIds){   
  59.                     assignable.addCandidateGroup(gId);   
  60.                 }   
  61.             }else{   
  62.                 assignable.addCandidateGroup(groupIds);   
  63.             }   
  64.         }   
  65.     }   
  66. }