Activiti源码跟踪之Task表单操作GetTaskFormCmd

在Activiti中总共有三种表单,动态表单,普通表单和外置表单。本文介绍的是动态表单。

FormService.getTaskFormCmd:查询Task表单。通过源码跟踪,查看如何获取Task表单


一、FormProperty

Task可以配置属性值,比如有一个审核的任务,对应的流程定义XML代码如下:


<userTask id="audit" name="审核">
      <extensionElements>
        <activiti:formProperty id="vendorCode" name="供应商" type="string" expression="1" variable="1" readable="false" required="true"/>
        <activiti:formProperty id="date" name="时间" type="date" datePattern="MM-dd-yyyy hh:mm"/>
        <activiti:formProperty id="amount" name="总数" type="long" writable="false" required="true"/>
        <activiti:formProperty id="is_vip" name="是否会员" type="boolean" writable="false"/>
        <activiti:formProperty id="approved" name="是否通过" type="enum" required="true">
          <activiti:value id="1" name="通过"/>
          <activiti:value id="2" name="驳回"/>
        </activiti:formProperty>
      </extensionElements>
    </userTask>

其中activiti:formProperty用来定义Task的属性:

public interface FormProperty extends Serializable {
  
  /** The key used to submit the property in {@link FormService#submitStartFormData(String, java.util.Map)} 
   * or {@link FormService#submitTaskFormData(String, java.util.Map)} */
  String getId();
  
  /** The display label */
  String getName();
  
  /** Type of the property. */
  FormType getType();

  /** Optional value that should be used to display in this property */
  String getValue();
  
  /** Is this property read to be displayed in the form and made accessible with the methods 
   * {@link FormService#getStartFormData(String)} and {@link FormService#getTaskFormData(String)}. */
  boolean isReadable();

  /** Is this property expected when a user submits the form? */
  boolean isWritable();

  /** Is this property a required input field */
  boolean isRequired();
}

支持的表单属性有以下几种:

  • string (org.activiti.engine.impl.form.StringFormType)

  • long (org.activiti.engine.impl.form.LongFormType)

  • enum (org.activiti.engine.impl.form.EnumFormType)

  • date (org.activiti.engine.impl.form.DateFormType)

  • boolean (org.activiti.engine.impl.form.BooleanFormType)


二、如何去获取在流程定义中定义的表单内容?

TaskFormDataImpl taskFormData = (TaskFormDataImpl) formService.getTaskFormData(taskId);

GetTaskFormCmd的execute方法:

public TaskFormData execute(CommandContext commandContext) {
    TaskEntity task = commandContext
      .getTaskEntityManager()
      .findTaskById(taskId);
    if (task == null) {
      throw new ActivitiObjectNotFoundException("No task found for taskId '" + taskId +"'", Task.class);
    }
    
    if(task.getTaskDefinition() != null) {
      TaskFormHandler taskFormHandler = task.getTaskDefinition().getTaskFormHandler();
      if (taskFormHandler == null) {
        throw new ActivitiException("No taskFormHandler specified for task '" + taskId +"'");
      }
      
      return taskFormHandler.createTaskForm(task);
    } else {
      // Standalone task, no TaskFormData available
      return null;
    }
  }

核心代码再第9行task.getTaskDefinition()获取Task属性

public TaskDefinition getTaskDefinition() {
    if (taskDefinition==null && taskDefinitionKey!=null) {
      ProcessDefinitionEntity processDefinition = Context
        .getProcessEngineConfiguration()
        .getDeploymentManager()
        .findDeployedProcessDefinitionById(processDefinitionId);
      taskDefinition = processDefinition.getTaskDefinitions().get(taskDefinitionKey);
    }
    return taskDefinition;
  }

第6行代码findDeployedProcessDefinitionById,根据processDefinitionId查询流程定义:

public ProcessDefinitionEntity findDeployedProcessDefinitionById(String processDefinitionId) {
    if (processDefinitionId == null) {
      throw new ActivitiIllegalArgumentException("Invalid process definition id : null");
    }
    
    // first try the cache
    ProcessDefinitionEntity processDefinition = processDefinitionCache.get(processDefinitionId);
    
    if (processDefinition == null) {
      processDefinition = Context.getCommandContext()
        .getProcessDefinitionEntityManager()
        .findProcessDefinitionById(processDefinitionId);
      if (processDefinition == null) {
        throw new ActivitiObjectNotFoundException("no deployed process definition found with id '" + processDefinitionId + "'", ProcessDefinition.class);
      }
      processDefinition = resolveProcessDefinition(processDefinition);
    }
    return processDefinition;
  }

第7行代码变量processDefinitionCache是一个DeploymentCache实例对象,在这里引申一下。

当初始化流程引擎的时候,会执行下面的方法

org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl


buildProcessEngine()--->init()--->initDeployers(),这时候processDefinitionCache会被初始化。那么processDefinitionCache什么时候赋值的呢?processDefinitionCache属于DeploymentCache对象,可以看出应该是在流程部署的时候进行赋值的。可以参考:Activiti源码跟踪之流程部署


接着往下看--》resolveProcessDefinition方法

public ProcessDefinitionEntity resolveProcessDefinition(ProcessDefinitionEntity processDefinition) {
    String processDefinitionId = processDefinition.getId();
    String deploymentId = processDefinition.getDeploymentId();
    processDefinition = processDefinitionCache.get(processDefinitionId);
    if (processDefinition==null) {
      DeploymentEntity deployment = Context
        .getCommandContext()
        .getDeploymentEntityManager()
        .findDeploymentById(deploymentId);
      deployment.setNew(false);
      deploy(deployment, null);
      processDefinition = processDefinitionCache.get(processDefinitionId);
      
      if (processDefinition==null) {
        throw new ActivitiException("deployment '"+deploymentId+"' didn't put process definition '"+processDefinitionId+"' in the cache");
      }
    }
    return processDefinition;
  }

如果processDefinitionCache没有流程定义的话,重新部署流程:

      deployment.setNew(false);
      deploy(deployment, null);

因为部署会把流程定义放在缓存中,所以这个时候再去processDefinitionCache查询流程定义。

根据taskDefinitionKey就可以获取到TaskDefinition


三、如何解析TaskDefinition()

再看下GetTaskFormCmd的execute方法

TaskFormHandler taskFormHandler = task.getTaskDefinition().getTaskFormHandler();
taskFormHandler.createTaskForm(task);

DefaultTaskFormHandler.createTaskForm--->DefaultFormHandler.initializeFormProperties(taskFormData, task.getExecution())。循环DefaultFormHandler的formPropertyHandlers获取到FormProperty。


四:扩展:如何根据ProcessDefinitionId和TaskDefinitionKey获取到表单属性

1、根据processDefinitionId查询流程定义

ProcessDefinitionEntity processDefinition = Context.getProcessEngineConfiguration().getDeploymentManager()
                .findDeployedProcessDefinitionById(processDefinitionId);

2、根据TaskDefinitionKey获取Task定义

TaskDefinition taskDefinition = processDefinition.getTaskDefinitions().get(taskDefinitionKey);

3、获取Task表单属性

因为DefaultTaskFormHandler有FormPropertyHandlers属性,所以可以直接从DefaultTaskFormHandler获取FormPropertyHandlers

DefaultTaskFormHandler taskFormHandler = (DefaultTaskFormHandler) taskDefinition.getTaskFormHandler();

public class FormPropertyHandler implements Serializable {

  private static final long serialVersionUID = 1L;
  
  protected String id;
  protected String name;
  protected AbstractFormType type;
  protected boolean isReadable;
  protected boolean isWritable;
  protected boolean isRequired;
  protected String variableName;
  protected Expression variableExpression;
  protected Expression defaultExpression;

    ......

}

然后获取表单属性:

formPropertyHandler.getId();

formPropertyHandler.getName();

formPropertyHandler.getType().getName()



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值