当用JaWE创建流程时候,会将相关活动放到对应的角色中。而当启动流程时候需要将角色映射到具体的用户上面,才能将具体任务分配给具体用户。 Shark 可以将一个角色映射到一个单独的用户,也可以将角色映射到一个用户组。如果映射到单独的用户,则该角色的任务只会出现在该用户的任务列表里;如果映射到一组用户,则该角色的任务会出现在这个组的所有用户的任务列表里,如果其中一个用户接收了这个任务,则该任务会在该组其他成员的任务列表里删除。
但是根据代码分析,Shark将一个流程或一个包的角色映射存在数据库中,每当启动一个流程时候,Shark会到数据库中查找此流程的角色映射信息,如果找到就把相应的任务分配给相关用户;如果没有找到映射信息,则把所有任务都分配给启动流程的那个用户。这样就会出现一个问题,不便于在启动流程时候动态的映射角色和用户,因为角色和固定用户的映射信息是静态的存储在数据库中的,目前的方法只能每次启动之前重新映射角色,这样每次都会有数据库更改操作,增加了数据库读取操作,对性能造成影响,如果有大量并发时候,很有可能由于更改数据库造成问题。所以此处需要改进,合理的办法是允许将角色映射信息传入到流程启动参数中去,这样派发流程的人员就可以根据实际情况选择不同的处理人,即使派发的是同一个流程。
下面看一下映射角色的代码。由于JspClient示例中没有相关映射角色的操作,所以使用的是Shark Admin这个Swing客户端管理程序,此程序可以使用在Shark安装目录下的bin目录下的runSA.bat文件启动。具体使用方法可以参考安装目录下的doc/QuickStartExample/index.html文件。该程序有一个"User management"标签下有一个"Mapping"功能,就是进行角色映射的功能。其源代码为 org.enhydra.shark.swingclient.workflowadmin.user.UserMapping类。下面这个方法即是保存映射信息的操作:
protected void applyChanges() {
if (participants.isSelectionEmpty() || usernames.isSelectionEmpty())
return;
UserTransaction ut = null;
try {
ut = SharkInterfaceWrapper.getUserTransaction();
ut.begin();
ParticipantMap pm = SharkInterfaceWrapper.getParticipantMappingsAdmin().createParticipantMap();
pm.setPackageId(pkgId.getText());
pm.setProcessDefinitionId(procDefId.getText());
pm.setParticipantId(participantId.getText());
pm.setUsername(username.getText());
if (ResourceManager.getLanguageDependentString("IsGroupUserTRUEKey").equalsIgnoreCase(
isGroupUser.getText().trim()))
pm.setIsGroupUser(true);
else
pm.setIsGroupUser(false);
SharkInterfaceWrapper.getParticipantMappingsAdmin().saveParticipantMapping(pm);
umm.refresh(true);
ut.commit();
} catch (Exception ex) {
try {
ut.rollback();
} catch (Exception _) {
}
JOptionPane.showMessageDialog(umm.getWindow(),
ResourceManager.getLanguageDependentString("MessageMappingAlreadyExistsOrCannotBeAddedAtTheMoment"),
ResourceManager.getLanguageDependentString("WorkflowAdminTitle"), JOptionPane.INFORMATION_MESSAGE);
}
}
构造一个ParticipantMap,将映射信息放入ParticipantMap中,然后保存到数据库中。 SharkInterfaceWrapper.getParticipantMappingsAdmin().saveParticipantMapping(pm); 根据反射机制实际上是调用的类 org.enhydra.shark.partmappersistence.DODSParticipantMappingAdmin的 saveParticipantMapping(pm)方法:
/**
* Save new ParticipantMap to database.
*
* @param pm ParticipantMap to save
* @return boolean true if everything is ok, false otherwise
* @exception Exception Exception will be thrown if error occur.
*/
public boolean saveParticipantMapping(ParticipantMap pm) throws Exception {
boolean retVal = true;
if (!checkValidity(pm)) {
throw new Exception("Participant mapping [ " + pm + " ] is not valid");
}
if (doesParticipantMappingExist(pm)) {
throw new Exception("Participant mapping already exists");
}
DBTransaction dbt = getDBTransaction();
// if group user
if (pm.getIsGroupUser()) {
// FIXME
// GroupUserProcLevelParticipantDO mappDO =
// GroupUserProcLevelParticipantDO.createVirgin();
GroupUserDO groupDO = this.checkGroups(pm);
// process level participant
if (pm.getProcessDefinitionId() != null) {
ProcLevelParticipantDO procLevPartDO = this.checkProcLevelParticipant(pm);
GroupUserProcLevelParticipantDO gplPart = GroupUserProcLevelParticipantDO.createVirgin(dbt);
gplPart.setPARTICIPANTOID(procLevPartDO);
gplPart.setUSEROID(groupDO);
gplPart.save();
}
// package level participant
else {
PackLevelParticipantDO pckgLevPartDO = this.checkPackLevelParticipant(pm);
GroupUserPackLevelParticipantDO gplPart = GroupUserPackLevelParticipantDO.createVirgin(dbt);
gplPart.setPARTICIPANTOID(pckgLevPartDO);
gplPart.setUSEROID(groupDO);
gplPart.save();
}
}
// if single user
else {
// FIXME
// UserProcLevelParticipantDO mappDO =
// UserProcLevelParticipantDO.createVirgin(dbt);
NormalUserDO userDO = this.checkUsers(pm);
if (pm.getProcessDefinitionId() != null) {
ProcLevelParticipantDO procLevPartDO = this.checkProcLevelParticipant(pm);
UserProcLevelParticipantDO uplPart = UserProcLevelParticipantDO.createVirgin(dbt);
uplPart.setPARTICIPANTOID(procLevPartDO);
uplPart.setUSEROID(userDO);
uplPart.save();
} else {
PackLevelParticipantDO pckgLevPartDO = this.checkPackLevelParticipant(pm);
UserPackLevelParticipantDO uplPart = UserPackLevelParticipantDO.createVirgin(dbt);
uplPart.setPARTICIPANTOID(pckgLevPartDO);
uplPart.setUSEROID(userDO);
uplPart.save();
}
}
return retVal;
}
根据映射单个用户还是映射组用户分别处理,根据映射单个流程还是映射整个包分别把映射信息存储到SHKProcLevelParticipant表 (ProcLevelParticipantDO类为该表的实体类)和SHKPackLevelParticipant表 (PackLevelParticipantDO类为该表的实体类)。 DODSParticipantMappingAdmin类有一个getParticipantMappings(WMSessionHandle shandle, String packageId, String packageVer,String processDefinitionId, String participantId)查找映射信息,根据代码分析,其调用情况如下(省略了参数):
WfActivityImpl.startActivity()->WfActivityImpl.runNo()->WfActivityImpl.createAssignments()-> WfActivityImpl.findUsers()->StandardAssignmentManager.getAssignments()-> StandardAssignmentManager.findResources()->DODSParticipantMappingAdmin.getParticipantMappings()
当启动流程后,会启动流程的活动,这个时候该活动就根据角色映射信息把任务分配给相应的具体用户。目前已经清楚了Shark的角色映射机制,如果实际应用中每类流程的处理人员变动比较小的话,可以使用启动流程前重新映射的方式;如果变动比较频繁的话,为了效率和安全性,则需要添加动态映射的机制。目前想到的方法是可以根据具体的流程实例保存映射信息,即每个流程都有相应的映射信息保存,而不是所有同类流程使用同一个映射信息,这样就可以使同一流程的不同实例拥有不同的处理人了。
Shark 工作流研究2-用户角色映射
最新推荐文章于 2021-08-11 00:17:27 发布