JBPM引擎设计(1)

来源:互联网 发布:远程的端口号 编辑:程序博客网 时间:2024/05/18 02:24

1、命令模式在Jbpm的使用,有助于管理各命令的执行,也方便方便接口处理,如下:

protected int getJobCount() {    return processEngine.execute(new Command<Integer>() {      private static final long serialVersionUID = 1L;      public Integer execute(Environment environment) {        org.hibernate.Session session = environment.get(org.hibernate.Session.class);        return (Integer) session.createCriteria("org.jbpm.pvm.internal.job.JobImpl")          .add(Restrictions.gt("retries", 0))          .setProjection(Projections.rowCount())          .uniqueResult();      }    });  }


2、JBPM中类的调用关系,(主要在命令模式处理业务dao的过程)如下:

以上类图只在Task处理做解释,实际上包含业务处理的所有操作(DAO)都为一个Command,如上面的getTaskCmd,其实现如下:

package org.jbpm.pvm.internal.cmd;import org.jbpm.api.JbpmException;import org.jbpm.api.cmd.Environment;import org.jbpm.api.task.Task;import org.jbpm.pvm.internal.session.DbSession;import org.jbpm.pvm.internal.task.TaskImpl;/** * @author Alejandro Guizar */public class GetTaskCmd extends AbstractCommand<Task> {  private static final long serialVersionUID = 1L;    protected String taskId;    public GetTaskCmd(String taskId) {    if (taskId==null) {      throw new JbpmException("taskId is null");    }    this.taskId = taskId;  }  public Task execute(Environment environment) throws Exception {    DbSession dbSession = environment.get(DbSession.class);    return dbSession.get(TaskImpl.class, Long.parseLong(taskId));  }}

而以上处理中的DbSession就是hibernate的Session接口,这是在enviroment中注入的:

package org.jbpm.pvm.internal.hibernate;import java.io.Serializable;import java.util.Collection;import java.util.List;import org.hibernate.LockMode;import org.hibernate.Session;import org.hibernate.criterion.Order;import org.hibernate.criterion.Restrictions;import org.hibernate.metadata.ClassMetadata;import org.jbpm.api.Execution;import org.jbpm.api.JbpmException;import org.jbpm.api.history.HistoryComment;import org.jbpm.api.task.Task;import org.jbpm.internal.log.Log;import org.jbpm.pvm.internal.client.ClientExecution;import org.jbpm.pvm.internal.env.EnvironmentImpl;import org.jbpm.pvm.internal.history.model.HistoryCommentImpl;import org.jbpm.pvm.internal.history.model.HistoryProcessInstanceImpl;import org.jbpm.pvm.internal.id.DbidGenerator;import org.jbpm.pvm.internal.job.JobImpl;import org.jbpm.pvm.internal.job.StartProcessTimer;import org.jbpm.pvm.internal.model.ExecutionImpl;import org.jbpm.pvm.internal.query.DeploymentQueryImpl;import org.jbpm.pvm.internal.query.HistoryActivityInstanceQueryImpl;import org.jbpm.pvm.internal.query.HistoryDetailQueryImpl;import org.jbpm.pvm.internal.query.HistoryProcessInstanceQueryImpl;import org.jbpm.pvm.internal.query.JobQueryImpl;import org.jbpm.pvm.internal.query.ProcessInstanceQueryImpl;import org.jbpm.pvm.internal.query.TaskQueryImpl;import org.jbpm.pvm.internal.session.DbSession;import org.jbpm.pvm.internal.task.TaskImpl;import org.jbpm.pvm.internal.util.Clock;import org.jbpm.pvm.internal.util.CollectionUtil;/** * @author Tom Baeyens */public class DbSessionImpl implements DbSession {  private static Log log = Log.getLog(DbSessionImpl.class.getName());  protected Session session;  public void close() {    session.close();  }  public <T> T get(Class<T> entityClass, Object primaryKey) {    return entityClass.cast(session.get(entityClass, (Serializable) primaryKey));  }  public void flush() {    session.flush();  }  public void forceVersionUpdate(Object entity) {    session.lock(entity, LockMode.FORCE);  }  public void lockPessimistically(Object entity) {    session.lock(entity, LockMode.UPGRADE);  }  public void save(Object entity) {    session.save(entity);  }  public void update(Object entity) {    session.update(entity);  }  public void merge(Object entity) {    session.merge(entity);  }  public void delete(Object entity) {    session.delete(entity);  }  public Session getSession() {    return session;  }  public void setSession(Session session) {    this.session = session;  }  public void deleteProcessDefinitionHistory(String processDefinitionId) {    List<?> historyProcessInstances = session.createCriteria(HistoryProcessInstanceImpl.class)      .add(Restrictions.eq("processDefinitionId", processDefinitionId))      .list();    for (Object hpi : historyProcessInstances) {      session.delete(hpi);    }  }  public boolean isHistoryEnabled() {    ClassMetadata historyHibernateMetadata = session.getSessionFactory()      .getClassMetadata(HistoryProcessInstanceImpl.class);    return historyHibernateMetadata != null;  }  // process execution queries ////////////////////////////////////////////////  public ClientExecution findExecutionById(String executionId) {    // query definition can be found at the bottom of resource jbpm.execution.hbm.xml    return (ClientExecution) session.getNamedQuery("findExecutionById")      .setString("id", executionId)      .setMaxResults(1)      .uniqueResult();  }  public ClientExecution findProcessInstanceById(String processInstanceId) {    // query definition can be found at the bottom of resource jbpm.execution.hbm.xml    return (ClientExecution) session.getNamedQuery("findProcessInstanceById")      .setString("processInstanceId", processInstanceId)      .setMaxResults(1)      .uniqueResult();  }  public ClientExecution findProcessInstanceByIdIgnoreSuspended(String processInstanceId) {    // query definition can be found at the bottom of resource jbpm.execution.hbm.xml    return (ClientExecution) session.getNamedQuery("findProcessInstanceByIdIgnoreSuspended")      .setString("processInstanceId", processInstanceId)      .setMaxResults(1)      .uniqueResult();  }  public List<String> findProcessInstanceIds(String processDefinitionId) {    // query definition can be found at the bottom of resource jbpm.execution.hbm.xml    List<?> processInstanceIds = session.getNamedQuery("findProcessInstanceIds")      .setString("processDefinitionId", processDefinitionId)      .list();    return CollectionUtil.checkList(processInstanceIds, String.class);  }  public void deleteProcessInstance(String processInstanceId) {    deleteProcessInstance(processInstanceId, true);  }  public void deleteProcessInstance(String processInstanceId, boolean deleteHistory) {    if (processInstanceId == null) {      throw new JbpmException("processInstanceId is null");    }    // if history should be deleted    if (deleteHistory && (isHistoryEnabled())) {      // try to get the history      HistoryProcessInstanceImpl historyProcessInstance = findHistoryProcessInstanceById(processInstanceId);      // if there is a history process instance in the db      if (historyProcessInstance != null) {        if (log.isDebugEnabled()) {          log.debug("deleting history process instance " + processInstanceId);        }        session.delete(historyProcessInstance);      }    }    ExecutionImpl processInstance = (ExecutionImpl) findProcessInstanceByIdIgnoreSuspended(processInstanceId);    if (processInstance != null) {      deleteSubProcesses(processInstance, deleteHistory);      // delete remaining tasks for this process instance      List<TaskImpl> tasks = findTasks(processInstanceId);      for (TaskImpl task : tasks) {        session.delete(task);      }      // delete remaining jobs for this process instance      JobImpl currentJob = EnvironmentImpl.getFromCurrent(JobImpl.class, false);      List<JobImpl> jobs = findJobs(processInstanceId);      for (JobImpl job : jobs) {        if (job != currentJob) {          session.delete(job);        }      }      if (log.isDebugEnabled()) {        log.debug("Deleting process instance " + processInstanceId);      }      session.delete(processInstance);    }    else {      throw new JbpmException("Can't delete processInstance " + processInstanceId        + ": no processInstance found for the given id");    }  }  private void deleteSubProcesses(ExecutionImpl execution, boolean deleteHistory) {    ExecutionImpl subProcessInstance = execution.getSubProcessInstance();    if (subProcessInstance != null) {      subProcessInstance.setSuperProcessExecution(null);      execution.setSubProcessInstance(null);      deleteProcessInstance(subProcessInstance.getId(), deleteHistory);    }    Collection<ExecutionImpl> childExecutions = execution.getExecutions();    if (childExecutions != null) {      for (ExecutionImpl childExecution : childExecutions) {        deleteSubProcesses(childExecution, deleteHistory);      }    }  }  public HistoryProcessInstanceImpl findHistoryProcessInstanceById(String processInstanceId) {    return (HistoryProcessInstanceImpl) session.createCriteria(HistoryProcessInstanceImpl.class)      .add(Restrictions.eq("processInstanceId", processInstanceId))      .uniqueResult();  }  List<TaskImpl> findTasks(String processInstanceId) {    List<?> tasks = session.createCriteria(TaskImpl.class)      .createAlias("processInstance", "pi")      .add(Restrictions.eq("pi.id", processInstanceId))      .list();    return CollectionUtil.checkList(tasks, TaskImpl.class);  }  List<JobImpl> findJobs(String processInstanceId) {    List<?> jobs = session.createCriteria(JobImpl.class)      .createAlias("processInstance", "pi")      .add(Restrictions.eq("pi.id", processInstanceId))      .list();    return CollectionUtil.checkList(jobs, JobImpl.class);  }  public void cascadeExecutionSuspend(ExecutionImpl execution) {    // cascade suspend to jobs    List<?> jobs = session.createCriteria(JobImpl.class)      .add(Restrictions.eq("execution", execution))      .add(Restrictions.ne("state", JobImpl.STATE_SUSPENDED))      .list();    for (JobImpl job : CollectionUtil.checkList(jobs, JobImpl.class)) {      job.suspend();    }    // cascade suspend to tasks    List<?> tasks = session.createCriteria(TaskImpl.class)      .add(Restrictions.eq("execution", execution))      .add(Restrictions.ne("state", Task.STATE_SUSPENDED))      .list();    for (TaskImpl task : CollectionUtil.checkList(tasks, TaskImpl.class)) {      task.suspend();    }  }  public void cascadeExecutionResume(ExecutionImpl execution) {    // cascade resume to jobs    List<?> jobs = session.createCriteria(JobImpl.class)      .add(Restrictions.eq("execution", execution))      .add(Restrictions.eq("state", JobImpl.STATE_SUSPENDED))      .list();    for (JobImpl job : CollectionUtil.checkList(jobs, JobImpl.class)) {      job.resume();    }    // cascade resume to tasks    List<?> tasks = session.createCriteria(TaskImpl.class)      .add(Restrictions.eq("execution", execution))      .add(Restrictions.eq("state", Task.STATE_SUSPENDED))      .list();    for (TaskImpl task : CollectionUtil.checkList(tasks, TaskImpl.class)) {      task.resume();    }  }  public TaskImpl createTask() {    TaskImpl task = newTask();    task.setCreateTime(Clock.getTime());    return task;  }  protected TaskImpl newTask() {    TaskImpl task = new TaskImpl();    long dbid = EnvironmentImpl.getFromCurrent(DbidGenerator.class).getNextId();    task.setDbid(dbid);    task.setNew(true);    return task;  }  public TaskImpl findTaskByDbid(long taskDbid) {    return (TaskImpl) session.get(TaskImpl.class, taskDbid);  }  public TaskImpl findTaskByExecution(Execution execution) {    return (TaskImpl) session.createCriteria(TaskImpl.class)      .add(Restrictions.eq("execution", execution))      .uniqueResult();  }  public JobImpl findFirstAcquirableJob() {    return (JobImpl) session.getNamedQuery("findFirstAcquirableJob")      .setTimestamp("now", Clock.getTime())      .setMaxResults(1)      .uniqueResult();  }  public List<JobImpl> findExclusiveJobs(Execution processInstance) {    List<?> exclusiveJobs = session.getNamedQuery("findExclusiveJobs")      .setTimestamp("now", Clock.getTime())      .setEntity("processInstance", processInstance)      .list();    return CollectionUtil.checkList(exclusiveJobs, JobImpl.class);  }  public JobImpl findFirstDueJob() {    return (JobImpl) session.getNamedQuery("findFirstDueJob")      .setMaxResults(1)      .uniqueResult();  }  public List<StartProcessTimer> findStartProcessTimers(String processDefinitionName) {    List<?> timers = session.createCriteria(StartProcessTimer.class)      .add(Restrictions.eq("signalName", processDefinitionName))      .list();    return CollectionUtil.checkList(timers, StartProcessTimer.class);  }  public ProcessInstanceQueryImpl createProcessInstanceQuery() {    return new ProcessInstanceQueryImpl();  }  public TaskQueryImpl createTaskQuery() {    return new TaskQueryImpl();  }  public HistoryProcessInstanceQueryImpl createHistoryProcessInstanceQuery() {    return new HistoryProcessInstanceQueryImpl();  }  public HistoryActivityInstanceQueryImpl createHistoryActivityInstanceQuery() {    return new HistoryActivityInstanceQueryImpl();  }  public HistoryDetailQueryImpl createHistoryDetailQuery() {    return new HistoryDetailQueryImpl();  }  public JobQueryImpl createJobQuery() {    return new JobQueryImpl();  }  public DeploymentQueryImpl createDeploymentQuery() {    return new DeploymentQueryImpl();  }  public List<HistoryComment> findCommentsByTaskId(String taskId) {    List<?> comments = session.createCriteria(HistoryCommentImpl.class)      .createAlias("historyTask", "task")      .add(Restrictions.eq("task.dbid", Long.parseLong(taskId)))      .addOrder(Order.asc("historyTaskIndex"))      .list();    return CollectionUtil.checkList(comments, HistoryComment.class);  }}
也就是说,底层还是通过session操作数据库的。


3、关于上图中的CommandService是一个接口:

public interface CommandService {    String NAME_TX_REQUIRED_COMMAND_SERVICE = "txRequiredCommandService";  String NAME_NEW_TX_REQUIRED_COMMAND_SERVICE = "newTxRequiredCommandService";  /**   * @throws JbpmException if command throws an exception.   */  <T> T execute(Command<T> command);}

实际调用的类是AbstractServiceImpl依赖这个CommandService,如下:

public class AbstractServiceImpl {    protected CommandService commandService;  public CommandService getCommandService() {    return commandService;  }  public void setCommandService(CommandService commandService) {    this.commandService = commandService;  }}

AbstractServiceImpl几个子类对于实际操作的几个接口:


4、我们在使用JBPM流程引擎时,先获取单例的ProcessEnginee对象,用这个可以

 RepositoryService getRepositoryService();  /** the {@link ExecutionService execution service} that provides access   * to the runtime executions repository. */   ExecutionService getExecutionService();  /** the {@link HistoryService history service} that provides access   * to the history executions repository. */   HistoryService getHistoryService();  /** the {@link TaskService task service} that exposes the    * runtime human task lists. */   TaskService getTaskService();  /** the {@link IdentityService identity service} that exposes the    * user and group operations management operations. */   IdentityService getIdentityService();  /** the {@link ManagementService management service} that exposes the    * management operations to operators that have to keep the jBPM system    * up and running. */   ManagementService getManagementService();

也就是几个服务接口,我们应用层就是操作者几个接口进行流程控制。


6、以上关键部分就是CommandService是具体对象:

比如TaskServiceImp中依赖的CommandService就是:

processEngineWireContext.get()在上层获取

比如ProcessEniginee中还有一个execute(Command<T>)接口中的Command就是这里获取

userCommandService = (CommandService) processEngineWireContext.get(CommandService.NAME_TX_REQUIRED_COMMAND_SERVICE);



0 0