介绍

在Oracle BPM中如何动态指定审批人,你可能觉得这问题很简单,在UserTask前面加上获取人员的Service就行了,这个也是一般做法,如图

在Service里可以调用第三方接口也可以调用存储过程,但如果这里想调用java代码该如何实现?有两个方案

  • 把代码发布成webservice或者rest接口,通过service进行调用
  • 借助script组件,script可以执行java代码,如图

把代码发布成webservice,增加了工作量,也增加了系统的复杂度,动态获取审批人问题变成了第三方系统集成问题,script组件的引入污染了流程图,试想如果每个节点都需要同样的计算逻辑,那么在每个节点前面都需要加上script组件,不仅不利于后期维护,而且也会影响最终给用户的流程图,影响流程图的美观。那有办法两者兼得吗,最近在看老外做的一个bpm项目,发现了一个解决方案。

HumanTask配置

  • 进入HumanTask->Assignment,点击右上角编辑按钮

  • 选择Use External Routing,点击编辑进行编辑

  • 输入Class Name,具体的Class我们后面创建,可以创建参数,这些参数在Class中可以获取到,可以是静态值也可以是XPath变量,Class必须实现oracle.bpel.services.workflow.task.IAssignmentService接口

  • 设置完,Assignment的界面是下面这样,并且一些操作也都不可用

代码

配置完HumanTask,就要实现我们的代码

  • 在项目右键选择Project Properties,进入Libraries and Classpath -> Add Library找到BPM Services

  • 点击Technology Scope,从左边列表中选择Java

  • 在项目上右键New创建Java Class,路径和名称保持HumanTask中配置的一致,必须实现oracle.bpel.services.workflow.task.IAssignmentService接口,以下是参考
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import oracle.bpel.services.workflow.IWorkflowConstants;
import oracle.bpel.services.workflow.metadata.routingslip.RoutingSlipUtil;
import oracle.bpel.services.workflow.metadata.routingslip.model.*;

import oracle.bpel.services.workflow.metadata.routingslip.model.Participants;
import oracle.bpel.services.workflow.metadata.routingslip.model.ParticipantsType.Participant;
import oracle.bpel.services.workflow.task.IAssignmentService;
import oracle.bpel.services.workflow.task.ITaskAssignee;
import oracle.bpel.services.workflow.task.model.Task;


public class CuxRouting implements IAssignmentService {

    @Override
    public Participants onInitiation(Task task, Map propertyBag) {
        
        System.out.println("platform===> " + propertyBag.get("platform"));
        String approvers=propertyBag.get("platform").toString();
        String expirationDays=null;
        
        ObjectFactory objFactory = new ObjectFactory();
        Participants participants = objFactory.createParticipants();
        Participant participant = objFactory.createParticipantsTypeParticipant();
        
        participant.setName("Participant");
        ResourceType resource = objFactory.createResourceType(approvers);
        resource.setIsGroup(false);
        
        resource.setIdentityType(IWorkflowConstants.IDENTITY_TYPE_USER);

        resource.setType("STATIC");
        participant.getResource().add(resource);
        participants.getParticipantOrSequentialParticipantOrAdhoc().add(participant);
        
        System.out.println("Routing task to participants\n" +
                        RoutingSlipUtil.getInstance().toString(participants));
        
        return participants;
    }

    @Override
    public Participants onReinitiation(Task task, Map propertyBag) {
        return null;
    }

    @Override
    public Participants onOutcomeUpdated(Task task, Map propertyBag,
                                         String updatedBy, String outcome) {
        return null;
    }

    @Override
    public Participants onAssignmentSkipped(Task task, Map propertyBag) {
        return null;
    }
    
    @Override
    public List getAssigneesToRequestForInformation(Task task,
                                                    Map propertyBag) {
        List rfiUsers = new ArrayList();
        return rfiUsers;
    }

    @Override
    public List getReapprovalAssignees(Task task, Map propertyBag,
                                       ITaskAssignee infoRequestedAssignee) {
        List reapprovalUsers = new ArrayList();
        return reapprovalUsers;
    }
    
}
  • 只需实现onInitiation即可,propertyBag可以获取参数,task是当前任务信息,函数需要返回一个Participants对象,该对象记录节点审批类型,审批人等信息,示例代码中将Participants信息打印出来,如下:
<participants xmlns="http://xmlns.oracle.com/bpel/workflow/routingSlip">
   <participant name="Participant">
      <resource isGroup="false" identityType="user" type="STATIC">DEFINESYS</resource>
   </participant>
</participants>

实际上,我们正常配置HumanTask的话,也会包含该信息

所以你可以在HumanTask中配置完,api参考正常配置的就行

部署

  • 代码写完正常打包部署即可

思考

这个小功能能用来干嘛呢?这个小功能太有用了,如果你想定制化Oracle BPM,这个特性可以赋予你非常灵活的能力,定制化流程主要是解决两个问题

  • 找人问题
  • 条件判断问题

该特性可以解决找人问题,注意到onInitiation也传入了Task对象,并且提供了多个接入点函数,这意味着你可以修改该task(这个我没测试过),如果可行的话,那么可以将条件判断的结果存储到Task对象中,在流程中引用解决第二个问题。

参考


DQuery
300 声望93 粉丝

幸福是奋斗出来的