bdf2-jbpm4模塊不再維護(hù)更新
2013年10月01日起,BDF2中集成的jBPM4模塊將不再做任何更新,今后將主推銳道自己的流程引擎UFLO,項(xiàng)目地址為bsdn.org/projects/uflo ,UFLO文檔教程地址為UFLO Home。
無(wú)論是通過(guò)哪種方式設(shè)計(jì)好流程模版并部署到BDF2系統(tǒng)當(dāng)中,一旦部署成功之后,接下來(lái)就可以對(duì)流程模版進(jìn)行配置了,這里需要注意的是,一般情況下,我們?cè)谠O(shè)計(jì)流程模版時(shí)(也就是在畫(huà)流程圖的時(shí)候)不需要對(duì)任務(wù)節(jié)點(diǎn)做太多配置(唯一要做的就是為其賦一個(gè)正確的名稱),所以關(guān)于任務(wù)節(jié)點(diǎn)的配置都是在BDF2當(dāng)中提供的配置與監(jiān)控當(dāng)中實(shí)現(xiàn)。
在BDF2當(dāng)中提供的配置與監(jiān)控當(dāng)中,選中要配置的流程模版,點(diǎn)擊工具欄上的“節(jié)點(diǎn)配置”按鈕,系統(tǒng)會(huì)彈出一個(gè)dialog,并在所有的任務(wù)節(jié)點(diǎn)上添加鏈接,點(diǎn)擊這個(gè)鏈接會(huì)彈出與這個(gè)任務(wù)節(jié)點(diǎn)相關(guān)的配置信息,如下圖所示:

從彈出的窗口當(dāng)中可以看出,對(duì)于任務(wù)節(jié)點(diǎn),我們可以在線配置的內(nèi)容有四塊:第一個(gè)就是當(dāng)前任務(wù)節(jié)點(diǎn)對(duì)應(yīng)處理表單頁(yè)面,它可以是一個(gè)標(biāo)準(zhǔn)的
doradoview(比如aa.bb.cc.Demo.d),也可是一個(gè)標(biāo)準(zhǔn)的JSP;第二個(gè)是配置任務(wù)的處理人,也就是任務(wù)分配,就是決定在這個(gè)節(jié)點(diǎn)上產(chǎn)生的任務(wù)由誰(shuí)來(lái)處理;第三個(gè)是定義任務(wù)在產(chǎn)生以后如何提醒任務(wù)處理人(發(fā)站內(nèi)消息、郵件或其它);第四個(gè)任務(wù)過(guò)期就是可以給任務(wù)一個(gè)處理時(shí)間,一旦超過(guò)個(gè)時(shí)間還沒(méi)有人處理,那么就通知任務(wù)處理人或做些其它動(dòng)作。
我們首先來(lái)看看“任務(wù)分配”頁(yè)中的配置內(nèi)容,如下圖所示:

點(diǎn)擊“添加”在彈出的窗口當(dāng)中選擇我們采用的任務(wù)分配器,但可以看到彈出窗口是空的,這是因?yàn)樵谶x擇任務(wù)分配器前,我們還需要將要采用的任務(wù)分配器加載到系統(tǒng)當(dāng)中,具體做法就是點(diǎn)擊菜單導(dǎo)航中的“任務(wù)分配管理”,在其中添加我們要采用的任務(wù)分配器,如下圖所示:

從上圖當(dāng)中可以看出,任務(wù)分配方式列表中,默認(rèn)系統(tǒng)只提供了兩種,對(duì)于用戶來(lái)說(shuō),一般情況下,我都都需要定義自己的任務(wù)分配方式,如果需要定義,那么我們可以實(shí)現(xiàn)一個(gè)IAssignmentProvider接口的實(shí)現(xiàn)類(lèi),這個(gè)接口源碼如下:
IAssignmentProvider接口源碼
package com.bstek.bdf2.jbpm4.view.assignment.provider;
import java.util.Collection;
import org.jbpm.api.model.OpenExecution;
import com.bstek.bdf2.jbpm4.model.AssignmentInfo;
import com.bstek.bdf2.jbpm4.model.PrincipalDef;
/**
* @author Jacky.gao
* @since 2013-3-23
*/
public interface IAssignmentProvider {
/**
* @return 返回配置頁(yè)面所在的URL
*/
String getUrl();
/**
* @return 返回配置類(lèi)型的ID
*/
String getTypeId();
/**
* @return 返回與配置類(lèi)型ID對(duì)象的Name描述
*/
String getTypeName();
/**
* @param assignmentDefId 任務(wù)分配定義的ID
* @return 根據(jù)任務(wù)分配定義的ID返回與之對(duì)應(yīng)的任務(wù)分配信息
*/
Collection<AssignmentInfo> getAssignmentInfos(String assignmentDefId);
/**
* 刪除指定分配定義下的分配定義信息
* @param assignmentDefId 分配定義信息的ID
*/
void deleteAssignmentInfos(String assignmentDefId);
/**
* @param assignmentDefId 任務(wù)分配定義的ID
* @param execution 當(dāng)前流程實(shí)例執(zhí)行上下文對(duì)象
* @return 根據(jù)任務(wù)分配定義的ID返回所有與之對(duì)應(yīng)的任務(wù)處理人的PrincipalDef集合
*/
Collection<PrincipalDef> getTaskPrincipals(String assignmentDefId,OpenExecution execution);
/**
* @return 是否禁用
*/
boolean isDisabled();
}
實(shí)際上,我們看到的系統(tǒng)當(dāng)中默認(rèn)提供的兩種任務(wù)分配方式:流程實(shí)例發(fā)起人與指定一個(gè)用戶,它們都是通過(guò)實(shí)現(xiàn)IAssignmentProvider接口,然后配置到Spring當(dāng)中才出現(xiàn)在上圖中的下接列表當(dāng)中的。所以如果我們要定義自己的,同樣要實(shí)現(xiàn)IAssignmentProvider接口。
如果不想系統(tǒng)默認(rèn)提供的流程實(shí)例發(fā)起人出現(xiàn)在列表中,那么可以將bdf2.jbpm4.disablePromoterAssignment屬性設(shè)置成true,同樣對(duì)于指定一個(gè)用戶的任務(wù)分配方式,如果不需要那么就將bdf2.jbpm4.disableSpecifyUserAssignment屬性設(shè)置成true即可。
實(shí)際上,BDF2默認(rèn)提供的兩種任務(wù)分配方式:流程實(shí)例發(fā)起人與指定一個(gè)用戶,就是給我們對(duì)如何編寫(xiě)IAssignmentProvider接口實(shí)現(xiàn)類(lèi)提供了兩種不同類(lèi)型的示例。對(duì)于流程實(shí)例發(fā)起人這種任務(wù)分配方式,在使用不需要界面配置,所以它的實(shí)現(xiàn)類(lèi)相對(duì)簡(jiǎn)單,其源碼如下:
PromoterAssignmentProvider類(lèi)源碼
package com.bstek.bdf2.jbpm4.view.assignment.provider.impl.promoter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.jbpm.api.model.OpenExecution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.bstek.bdf2.jbpm4.model.AssignmentInfo;
import com.bstek.bdf2.jbpm4.model.PrincipalDef;
import com.bstek.bdf2.jbpm4.service.IBpmService;
import com.bstek.bdf2.jbpm4.view.assignment.provider.IAssignmentProvider;
/**
* 流程發(fā)起人任務(wù)分配方式
* @author Jacky.gao
* @since 2013-3-23
*/
@Component
public class PromoterAssignmentProvider implements IAssignmentProvider {
@Value("${bdf2.jbpm4.disablePromoterAssignment}")
private boolean disabled;
@Autowired
@Qualifier(IBpmService.BEAN_ID)
private IBpmService bmpService;
public String getUrl() {
return null;
}
public String getTypeId() {
return "promoter";
}
public String getTypeName() {
return "流程實(shí)例發(fā)起人";
}
public Collection<AssignmentInfo> getAssignmentInfos(String assignmentDefId) {
List<AssignmentInfo> info=new ArrayList<AssignmentInfo>();
AssignmentInfo a=new AssignmentInfo();
a.setName("流程實(shí)例發(fā)起人");
a.setValue("從流程實(shí)例中取名為["+IBpmService.PROCESS_INSTANCE_PROMOTER+"]的變量值,這個(gè)變量值表
示流程實(shí)例發(fā)起人用戶名");
info.add(a);
return info;
}
public Collection<PrincipalDef> getTaskPrincipals(String assignmentDefId,OpenExecution execution) {
List<PrincipalDef> usernames=new ArrayList<PrincipalDef>();
String username=(String)execution.getVariable(IBpmService.PROCESS_INSTANCE_PROMOTER);
if(StringUtils.isEmpty(username)){
throw new RuntimeException("Variable not found ["+IBpmService.PROCESS_INSTANCE_PROMOTER+"]
in current process instance");
}
PrincipalDef p=new PrincipalDef();
p.setId(username);
usernames.add(p);
return usernames;
}
public void deleteAssignmentInfos(String assignmentDefId){
//do nothing
}
public boolean isDisabled(){
return disabled;
}
}
但對(duì)于指定一個(gè)用戶這種任務(wù)分配方式,因?yàn)樯婕暗巾?yè)面,相比之下就復(fù)雜一些,我們來(lái)看看它的源碼:
SpecifyUserAssignmentProvider類(lèi)源碼
package com.bstek.bdf2.jbpm4.view.assignment.provider.impl.specifyuser;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.Session;
import org.jbpm.api.model.OpenExecution;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.bstek.bdf2.jbpm4.Jbpm4HibernateDao;
import com.bstek.bdf2.jbpm4.model.AssignmentInfo;
import com.bstek.bdf2.jbpm4.model.InternalAssignment;
import com.bstek.bdf2.jbpm4.model.PrincipalDef;
import com.bstek.bdf2.jbpm4.view.assignment.provider.IAssignmentProvider;
/**
* 指定一個(gè)用戶作為任務(wù)處理人
* @author Jacky.gao
* @since 2013-3-23
*/
@Component
public class SpecifyUserAssignmentProvider extends Jbpm4HibernateDao implements
IAssignmentProvider {
@Value("${bdf2.jbpm4.disableSpecifyUserAssignment}")
private boolean disabled;
public String getUrl() {
return "bdf2.jbpm4.view.assignment.provider.impl.specifyuser.SpecifyUserProvider";
}
public String getTypeId() {
return "specify_user";
}
public String getTypeName() {
return "指定一個(gè)用戶";
}
public Collection<AssignmentInfo> getAssignmentInfos(String assignmentDefId) {
String hql="from "+InternalAssignment.class.getName()+" where assignmentDefId=:assignmentDefId";
Map<String,Object> map=new HashMap<String,Object>();
map.put("assignmentDefId", assignmentDefId);
List<InternalAssignment> internals=this.query(hql, map);
List<AssignmentInfo> infos=new ArrayList<AssignmentInfo>();
for(InternalAssignment internal:internals){
AssignmentInfo info=new AssignmentInfo();
info.setName("一個(gè)用戶");
info.setValue(internal.getName());
infos.add(info);
}
return infos;
}
public Collection<PrincipalDef> getTaskPrincipals(String assignmentDefId,OpenExecution execution) {
String hql="from "+InternalAssignment.class.getName()+" where assignmentDefId=:assignmentDefId";
Map<String,Object> map=new HashMap<String,Object>();
map.put("assignmentDefId", assignmentDefId);
List<InternalAssignment> internals=this.query(hql, map);
List<PrincipalDef> result=new ArrayList<PrincipalDef>();
for(InternalAssignment internal:internals){
PrincipalDef def=new PrincipalDef();
def.setId(internal.getValue());
result.add(def);
}
return result;
}
public void deleteAssignmentInfos(String assignmentDefId){
String hql="delete "+InternalAssignment.class.getName()+" where assignmentDefId=:assignmentDefId";
Map<String,Object> map=new HashMap<String,Object>();
map.put("assignmentDefId", assignmentDefId);
Session session=this.getSessionFactory().openSession();
try{
session.createQuery(hql).setString("assignmentDefId", assignmentDefId).executeUpdate();
}finally{
session.flush();
session.close();
}
}
public boolean isDisabled() {
return disabled;
}
}
可以看到,指定一個(gè)用戶這種任務(wù)分配方式當(dāng)中用到的頁(yè)面是通過(guò)實(shí)現(xiàn)類(lèi)當(dāng)中的getUrl方法返回的,這個(gè)返回的頁(yè)面是bdf2.jbpm4.view.assignment.provider.impl.specifyuser.SpecifyUserProvider,實(shí)際上這是一個(gè)標(biāo)準(zhǔn)的dorado7view文件,我們可以在BDF2-JBPM4源碼包中找到bdf2.jbpm4.view.assignment.provider.impl.specifyuser包下的名為SpecifyUserProvider.view.xml文件,具體頁(yè)面中的實(shí)現(xiàn)大家可以參考這個(gè)view文件,值得注意的是,這里的getUrl方法返回的頁(yè)面只能是一個(gè)標(biāo)準(zhǔn)的dorado7view,而不能是JSP或其它,因?yàn)榉祷氐腢RL會(huì)被系統(tǒng)采用dorado7中的subviewholder引入到父頁(yè)面當(dāng)中,而subviewholder中的頁(yè)面只能是標(biāo)準(zhǔn)的dorado7 view。
定義一個(gè)任務(wù)分配方式,確認(rèn)后,再次打開(kāi)任務(wù)節(jié)點(diǎn)配置界面,就可以看到定義的任務(wù)分配方式,如下圖所示:

任務(wù)處理人配置好之后,就可以利用這個(gè)配置與監(jiān)控對(duì)流程模版進(jìn)行測(cè)試了,通過(guò)點(diǎn)擊工具欄上的“創(chuàng)建實(shí)例”按鈕就可以創(chuàng)建一個(gè)新的流程實(shí)例,以這個(gè)流程模版為例,新的流程實(shí)例產(chǎn)生后,流程將會(huì)流轉(zhuǎn)到初審節(jié)點(diǎn),右上邊的任務(wù)列表中也會(huì)出現(xiàn)這個(gè)初審節(jié)點(diǎn)上產(chǎn)生的任務(wù),點(diǎn)擊其上的“查看流程圖按鈕”,可以看到當(dāng)前流程實(shí)例所處位置,如下圖所示:

更多建議: