org.activiti.engine

本文详细介绍了Activiti流程引擎中的核心接口,包括TaskService、RuntimeService等,阐述了这些接口的功能及使用方法,为开发者提供了深入理解Activiti工作原理的基础。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Survive by day and develop by night.
talk for import biz , show your perfect code,full busy,skip hardness,make a better result,wait for change,challenge Survive.
happy for hardess to solve denpendies.

目录

在这里插入图片描述

概述

org.activiti.engine是一个非常常见的需求。

需求:

设计思路

实现思路分析

1.TaskService

public interface TaskService {

  /**
   * Creates a new task that is not related to any process instance.
   *
   * The returned task is transient and must be saved with {@link #saveTask(Task)} 'manually'.
   */
  Task newTask();

  /** create a new task with a user defined task id */
  Task newTask(String taskId);

  /**
   * Saves the given task to the persistent data store. If the task is already present in the persistent store, it is updated. After a new task has been saved, the task instance passed into this
   * method is updated with the id of the newly created task.
   *
   * @param task
   *          the task, cannot be null.
   */
  Task saveTask(Task task);

  /**
   * Deletes the given task, not deleting historic information that is related to this task.
   *
   * @param taskId
   *          The id of the task that will be deleted, cannot be null. If no task exists with the given taskId, the operation is ignored.
   * @throws ActivitiObjectNotFoundException
   *           when the task with given id does not exist.
   * @throws ActivitiException
   *           when an error occurs while deleting the task or in case the task is part of a running process.
   */
  void deleteTask(String taskId);

  /**
   * Deletes all tasks of the given collection, not deleting historic information that is related to these tasks.
   *
   * @param taskIds
   *          The id's of the tasks that will be deleted, cannot be null. All id's in the list that don't have an existing task will be ignored.
   * @throws ActivitiObjectNotFoundException
   *           when one of the task does not exist.
   * @throws ActivitiException
   *           when an error occurs while deleting the tasks or in case one of the tasks is part of a running process.
   */
  void deleteTasks(Collection<String> taskIds);

  /**
   * Deletes the given task.
   *
   * @param taskId
   *          The id of the task that will be deleted, cannot be null. If no task exists with the given taskId, the operation is ignored.
   * @param cascade
   *          If cascade is true, also the historic information related to this task is deleted.
   * @throws ActivitiObjectNotFoundException
   *           when the task with given id does not exist.
   * @throws ActivitiException
   *           when an error occurs while deleting the task or in case the task is part of a running process.
   */
  void deleteTask(String taskId, boolean cascade);

  /**
   * Deletes all tasks of the given collection.
   *
   * @param taskIds
   *          The id's of the tasks that will be deleted, cannot be null. All id's in the list that don't have an existing task will be ignored.
   * @param cascade
   *          If cascade is true, also the historic information related to this task is deleted.
   * @throws ActivitiObjectNotFoundException
   *           when one of the tasks does not exist.
   * @throws ActivitiException
   *           when an error occurs while deleting the tasks or in case one of the tasks is part of a running process.
   */
  void deleteTasks(Collection<String> taskIds, boolean cascade);

  /**
   * Deletes the given task, not deleting historic information that is related to this task..
   *
   * @param taskId
   *          The id of the task that will be deleted, cannot be null. If no task exists with the given taskId, the operation is ignored.
   * @param deleteReason
   *          reason the task is deleted. Is recorded in history, if enabled.
   * @throws ActivitiObjectNotFoundException
   *           when the task with given id does not exist.
   * @throws ActivitiException
   *           when an error occurs while deleting the task or in case the task is part of a running process
   */
  void deleteTask(String taskId, String deleteReason);

  /**
   * Deletes the given task, not deleting historic information that is related to this task..
   *
   * @param taskId
   *          The id of the task that will be deleted, cannot be null. If no task exists with the given taskId, the operation is ignored.
   * @param deleteReason
   *          reason the task is deleted. Is recorded in history, if enabled.
   * @param cancel
   *          mark the task as cancelled
   * @throws ActivitiObjectNotFoundException
   *           when the task with given id does not exist.
   * @throws ActivitiException
   *           when an error occurs while deleting the task or in case the task is part of a running process
   */
  void deleteTask(String taskId, String deleteReason, boolean cancel);

  /**
   * Deletes all tasks of the given collection, not deleting historic information that is related to these tasks.
   *
   * @param taskIds
   *          The id's of the tasks that will be deleted, cannot be null. All id's in the list that don't have an existing task will be ignored.
   * @param deleteReason
   *          reason the task is deleted. Is recorded in history, if enabled.
   * @throws ActivitiObjectNotFoundException
   *           when one of the tasks does not exist.
   * @throws ActivitiException
   *           when an error occurs while deleting the tasks or in case one of the tasks is part of a running process.
   */
  void deleteTasks(Collection<String> taskIds, String deleteReason);

  /**
   * Deletes all tasks of the given collection, not deleting historic information that is related to these tasks.
   *
   * @param taskIds
   *          The id's of the tasks that will be deleted, cannot be null. All id's in the list that don't have an existing task will be ignored.
   * @param deleteReason
   *          reason the task is deleted. Is recorded in history, if enabled.
   * @oaramn cancel
   *           mark the task as cancelled
   * @throws ActivitiObjectNotFoundException
   *           when one of the tasks does not exist.
   * @throws ActivitiException
   *           when an error occurs while deleting the tasks or in case one of the tasks is part of a running process.
   */
  void deleteTasks(Collection<String> taskIds, String deleteReason, boolean cancel);

  /**
   * Claim responsibility for a task: the given user is made assignee for the task. The difference with {@link #setAssignee(String, String)} is that here a check is done if the task already has a user
   * assigned to it. No check is done whether the user is known by the identity component.
   *
   * @param taskId
   *          task to claim, cannot be null.
   * @param userId
   *          user that claims the task. When userId is null the task is unclaimed, assigned to no one.
   * @throws ActivitiObjectNotFoundException
   *           when the task doesn't exist.
   * @throws ActivitiTaskAlreadyClaimedException
   *           when the task is already claimed by another user.
   */
  void claim(String taskId, String userId);

  /**
   * A shortcut to {@link #claim} with null user in order to unclaim the task
   *
   * @param taskId
   *          task to unclaim, cannot be null.
   * @throws ActivitiObjectNotFoundException
   *           when the task doesn't exist.
   */
  void unclaim(String taskId);

  /**
   * Called when the task is successfully executed.
   *
   * @param taskId
   *          the id of the task to complete, cannot be null.
   * @throws ActivitiObjectNotFoundException
   *           when no task exists with the given id.
   * @throws ActivitiException
   *           when this task is {@link DelegationState#PENDING} delegation.
   */
  void complete(String taskId);

  /**
   * Delegates the task to another user. This means that the assignee is set and the delegation state is set to {@link DelegationState#PENDING}. If no owner is set on the task, the owner is set to the
   * current assignee of the task.
   *
   * @param taskId
   *          The id of the task that will be delegated.
   * @param userId
   *          The id of the user that will be set as assignee.
   * @throws ActivitiObjectNotF

2.RuntimeService

public interface RuntimeService {

  /**
   * Create a {@link ProcessInstanceBuilder}, that allows to set various options for starting a process instance,
   * as an alternative to the various startProcessInstanceByXX methods.
   */
  ProcessInstanceBuilder createProcessInstanceBuilder();

  /**
   * Starts a process instance previously created.
   *
   * @param createdProcessInstance
   *          The already created process instance.
   * @throws ActivitiObjectNotFoundException
   *          when user does not have permission to start the process instance
   * @throws NotFoundException
   *          when no process instance with the given id is found
   */
  ProcessInstance startCreatedProcessInstance(ProcessInstance createdProcessInstance, Map<String, Object> variables);

  /**
   * Starts a new process instance in the latest version of the process definition with the given key.
   *
   * @param processDefinitionKey
   *          key of process definition, cannot be null.
   * @throws ActivitiObjectNotFoundException
   *           when no process definition is deployed with the given key.
   */
  ProcessInstance startProcessInstanceByKey(String processDefinitionKey);

  /**
   * Starts a new process instance in the latest version of the process definition with the given key.
   *
   * A business key can be provided to associate the process instance with a certain identifier that has a clear business meaning. For example in an order process, the business key could be an order
   * id. This business key can then be used to easily look up that process instance , see {@link ProcessInstanceQuery#processInstanceBusinessKey(String)}. Providing such a business key is definitely a
   * best practice.
   *
   * @param processDefinitionKey
   *          key of process definition, cannot be null.
   * @param businessKey
   *          a key that uniquely identifies the process instance in the context or the given process definition.
   * @throws ActivitiObjectNotFoundException
   *           when no process definition is deployed with the given key.
   */
  ProcessInstance startProcessInstanceByKey(String processDefinitionKey, String businessKey);

  /**
   * Starts a new process instance in the latest version of the process definition with the given key
   *
   * @param processDefinitionKey
   *          key of process definition, cannot be null.
   * @param variables
   *          the variables to pass, can be null.
   * @throws ActivitiObjectNotFoundException
   *           when no process definition is deployed with the given key.
   */
  ProcessInstance startProcessInstanceByKey(String processDefinitionKey, Map<String, Object> variables);

  /**
   * Starts a new process instance in the latest version of the process definition with the given key.
   *
   * A business key can be provided to associate the process instance with a certain identifier that has a clear business meaning. For example in an order process, the business key could be an order
   * id. This business key can then be used to easily look up that process instance , see {@link ProcessInstanceQuery#processInstanceBusinessKey(String)}. Providing such a business key is definitely a
   * best practice.
   *
   * The combination of processdefinitionKey-businessKey must be unique.
   *
   * @param processDefinitionKey
   *          key of process definition, cannot be null.
   * @param variables
   *          the variables to pass, can be null.
   * @param businessKey
   *          a key that uniquely identifies the process instance in the context or the given process definition.
   * @throws ActivitiObjectNotFoundException
   *           when no process definition is deployed with the given key.
   */
  ProcessInstance startProcessInstanceByKey(String processDefinitionKey, String businessKey, Map<String, Object> variables);

  /**
   * Similar to {@link #startProcessInstanceByKey(String)}, but using a specific tenant identifier.
   */
  ProcessInstance startProcessInstanceByKeyAndTenantId(String processDefinitionKey, String tenantId);

  /**
   * Similar to {@link #startProcessInstanceByKey(String, String)}, but using a specific tenant identifier.
   */
  ProcessInstance startProcessInstanceByKeyAndTenantId(String processDefinitionKey, String businessKey, String tenantId);

  /**
   * Similar to {@link #startProcessInstanceByKey(String, Map)}, but using a specific tenant identifier.
   */
  ProcessInstance startProcessInstanceByKeyAndTenantId(String processDefinitionKey, Map<String, Object> variables, String tenantId);

  /**
   * Similar to {@link #startProcessInstanceByKey(String, String, Map)}, but using a specific tenant identifier.
   */
  ProcessInstance startProcessInstanceByKeyAndTenantId(String processDefinitionKey, String businessKey, Map<String, Object> variables, String tenantId);

  /**
   * Starts a new process instance in the exactly specified version of the process definition with the given id.
   *
   * @param processDefinitionId
   *          the id of the process definition, cannot be null.
   * @throws ActivitiObjectNotFoundException
   *           when no process definition is deployed with the given key.
   */
  ProcessInstance startProcessInstanceById(String processDefinitionId);

  /**
   * Starts a new process instance in the exactly specified version of the process definition with the given id.
   *
   * A business key can be provided to associate the process instance with a certain identifier that has a clear business meaning. For example in an order process, the business key could be an order
   * id. This business key can then be used to easily look up that process instance , see {@link ProcessInstanceQuery#processInstanceBusinessKey(String)}. Providing such a business key is definitely a
   * best practice.
   *
   * @param processDefinitionId
   *          the id of the process definition, cannot be null.
   * @param businessKey
   *          a key that uniquely identifies the process instance in the context or the given process definition.
   * @throws ActivitiObjectNotFoundException
   *           when no process definition is deployed with the given key.
   */
  ProcessInstance startProcessInstanceById(String processDefinitionId, String businessKey);

  /**
   * Starts a new process instance in the exactly specified version of the process definition with the given id.
   *
   * @param processDefinitionId
   *          the id of the process definition, cannot be null.
   * @param variables
   *          variables to be passed, can be null
   * @throws ActivitiObjectNotFoundException
   *           when no process definition is deployed with the given key.
   */
  ProcessInstance startProcessInstanceById(String processDefinitionId, Map<String, Object> variables);

  /**
   * Starts a new process instance in the exactly specified version of the process definition with the given id.
   *
   * A business key can be provided to associate the process instance with a certain identifier that has a clear business meaning. For example in an order process, the business key could be an order
   * id. This business key can then be used to easily look up that process instance , see {@link ProcessInstanceQuery#processInstanceBusinessKey(String)}. Providing such a business key is definitely a
   * best practice.
   *
   * @param processDefinitionId
   *          the id of the process definition, cannot be null.
   * @param variables
   *          variables to be passed, can be null
   * @throws ActivitiObjectNotFoundException
   *           when no process definition is deployed with the given key.
   */
  ProcessInstance startProcessInstanceById(String processDefinitionId, String businessKey, Map<String, Object> variables);

  /**
   * <p>
   * Signals the process engine that a message is received and starts a new {@link ProcessInstance}.
   * </p>
   *
   * <p>
   * Calling this method can have two different outcomes:
   * <ul>
   * <li>If the message name is associated with a message start event, a new process instance is started.</li>
   * <li>If no subscription to a message with the given name exists, {@link ActivitiException} is thrown</li>
   * </ul>
   * </p>
   *
   * @param messageName
   *          the 'name' of the message as specified as an attribute on the bpmn20 {@code <message name="messageName" />} element.
   *
   * @return the {@link ProcessInstance} object representing the started process instance
   *
   * @throws ActivitiException
   *           if no subscription to a message with the given name exists
   *
   * @since 5.9
   */
  ProcessInstance startProcessInstanceByMessage(String messageName);

  /**
   * Similar to {@link RuntimeService#startProcessInstanceByMessage(String)}, but with tenant context.
   */
  ProcessInstance startProcessInstanceByMessageAndTenantId(String messageName, String tenantId);

  /**
   * <p>
   * Signals the process engine that a message is received and starts a new {@link ProcessInstance}.
   * </p>
   *
   * See {@link #startProcessInstanceByMessage(String, Map)}. This method allows specifying a business key.
   *
   * @param messageName
   *          the 'name' of the message as specified as an attribute on the bpmn20 {@code <message name="messageName" />} element.
   * @param businessKey
   *          the business key which is added to the started process instance
   *
   * @throws ActivitiException
   *           if no subscription to a message with the given name exists
   *
   * @since 5.10
   */
  ProcessInstance startProcessInstanceByMessage(String messageName, String businessKey);

  /**
   * Similar to {@link RuntimeService#startProcessInstanceByMessage(String, String)}, but with tenant context.
   */
  ProcessInstance startProcessInstanceByMessageAndTenantId(String messageName, String businessKey, String tenantId);

  /**
   * <p>
   * Signals the process engine that a message is received and starts a new {@link ProcessInstance}.
   * </p>
   *
   * See {@link #startProcessInstanceByMessage(String)}. In addition, this method allows specifying a the payload of the message as a map of process variables.
   *
   * @param messageName
   *          the 'name' of the message as specified as an attribute on the bpmn20 {@code <message name="messageName" />} element.
   * @param processVariables
   *          the 'payload' of the message. The variables are added as processes variables to the started process instance.
   * @return the {@link ProcessInstance} object representing the started process instance
   *
   * @throws ActivitiException
   *           if no subscription to a message with the given name exists
   *
   * @since 5.9
   */
  ProcessInstance startProcessInstanceByMessage(String messageName, Map<String, Object> processVariables);

  /**
   * Similar to {@link RuntimeService#startProcessInstanceByMessage(String, Map<String, Object>)}, but with tenant context.
   */
  ProcessInstance startProcessInstanceByMessageAndTenantId(String messageName, Map<String, Object> processVariables, String tenantId);

  /**
   * <p>
   * Signals the process engine that a message is received and starts a new {@link ProcessInstance}.
   * </p>
   *
   * See {@link #startProcessInstanceByMessage(String, Map)}. In addition, this method allows specifying a business key.
   *
   * @param messageName
   *          the 'name' of the message as specified as an attribute on the bpmn20 {@code <message name="messageName" />} element.
   * @param businessKey
   *          the business key which is added to the started process instance
   * @param processVariables
   *          the 'payload' of the message. The variables are added as processes variables to the started process instance.
   * @return the {@link ProcessInstance} object representing the started process instance
   *
   * @throws ActivitiException
   *           if no subscription to a message with the given name exists
   *
   * @since 5.9
   */
  ProcessInstance startProcessInstanceByMessage(String messageName, String businessKey, Map<String, Object> processVariables);

  /**
   * Similar to {@link RuntimeService#startProcessInstanceByMessage(String, String, Map<String, Object>)}, but with tenant context.
   */
  ProcessInstance startProcessInstanceByMessageAndTenantId(String messageName, String businessKey, Map<String, Object> processVariables, String tenantId);

  /**
   * Delete an existing runtime process instance.
   *
   * @param processInstanceId
   *          id of process instance to delete, cannot be null.
   * @param deleteReason
   *          reason for deleting, can be null.
   * @throws ActivitiObjectNotFoundException
   *           when no process instance is found with the given id.
   */
  void deleteProcessInstance(String processInstanceId, String deleteReason);

  /**
   * Finds the activity ids for all executions that are waiting in activities. This is a list because a single activity can be active multiple times.
   *
   * @param executionId
   *          id of the execution, cannot be null.
   * @throws ActivitiObjectNotFoundException
   *           when no execution exists with the given executionId.
   */
  List<String> getActiveActivityIds(String executionId);

  /**
   * Sends an external trigger to an activity instance that is waiting inside the given execution.
   *
   * @param executionId
   *          id of execution to signal, cannot be null.
   * @throws ActivitiObjectNotFoundException
   *           when no execution is found for the given executionId.
   */
  void trigger(String executionId);

  /**
   * Sends an external trigger to an activity instance that is waiting inside the given execution.
   *
   * @param executionId
   *          id of execution to signal, cannot be null.
   * @param processVariables
   *          a map of process variables
   * @throws ActivitiObjectNotFoundException
   *           when no execution is found for the given executionId.
   */
  void trigger(String executionId, Map<String, Object> processVariables);


  /**
   * Similar to {@link #trigger(String, Map)}, but with an extra parameter that allows to pass
   * transient variables.
   */
  void trigger(String executionId, Map<String, Object> processVariables, Map<String, Object> transientVariables);

  /**
   * Updates the business key for the provided process instance
   *
   * @param processInstanceId
   *          id of the process instance to set the business key, cannot be null
   * @param businessKey
   *          new businessKey value
   */
  void updateBusinessKey(String processInstanceId, String businessKey);

  // Identity Links
  // ///////////////////////////////////////////////////////////////

  /**
   * Involves a user with a process instance. The type of identity link is defined by the given identityLinkType.
   *
   * @param processInstanceId
   *          id of the process instance, cannot be null.
   * @param userId
   *          id of the user involve, cannot be null.
   * @param identityLinkType
   *          type of identityLink, cannot be null (@see {@link IdentityLinkType}).
   * @throws ActivitiObjectNotFoundException
   *           when the process instance doesn't exist.
   */
  void addUserIdentityLink(String processInstanceId, String userId, String identityLinkType);

  /**
   * Involves a group with a process instance. The type of identityLink is defined by the given identityLink.
   *
   * @param processInstanceId
   *          id of the process instance, cannot be null.
   * @param groupId
   *          id of the group to involve, cannot be null.
   * @param identityLinkType
   *          type of identity, cannot be null (@see {@link IdentityLinkType}).
   * @throws ActivitiObjectNotFoundException
   *           when the process instance or group doesn't exist.
   */
  void addGroupIdentityLink(String processInstanceId, String groupId, String identityLinkType);

  /**
   * Convenience shorthand for {@link #addUserIdentityLink(String, String, String)}; with type {@link IdentityLinkType#CANDIDATE}
   *
   * @param processInstanceId
   *          id of the process instance, cannot be null.
   * @param userId
   *          id of the user to use as candidate, cannot be null.
   * @throws ActivitiObjectNotFoundException
   *           when the task or user doesn't exist.
   */
  void addParticipantUser(String processInstanceId, String userId);

  /**
   * Convenience shorthand for {@link #addGroupIdentityLink(String, String, String)}; with type {@link IdentityLinkType#CANDIDATE}
   *
   * @param processInstanceId
   *          id of the process instance, cannot be null.
   * @param groupId
   *          id of the group to use as candidate, cannot be null.
   * @throws ActivitiObjectNotFoundException
   *           when the task or group doesn't exist.
   */
  void addParticipantGroup(String processInstanceId, String groupId);

  /**
   * Convenience shorthand for {@link #deleteUserIdentityLink(String, String, String)}; with type {@link IdentityLinkType#CANDIDATE}
   *
   * @param processInstanceId
   *          id of the process instance, cannot be null.
   * @param userId
   *          id of the user to use as candidate, cannot be null.
   * @throws ActivitiObjectNotFoundException
   *           when the task or user doesn't exist.
   */
  void deleteParticipantUser(String processInstanceId, String userId);

  /**
   * Convenience shorthand for {@link #deleteGroupIdentityLink(String, String, String)}; with type {@link IdentityLinkType#CANDIDATE}
   *
   * @param processInstanceId
   *          id of the process instance, cannot be null.
   * @param groupId
   *          id of the group to use as candidate, cannot be null.
   * @throws ActivitiObjectNotFoundException
   *           when the task or group doesn't exist.
   */
  void deleteParticipantGroup(String processInstanceId, String groupId);

  /**
   * Removes the association between a user and a process instance for the given identityLinkType.
   *
   * @param processInstanceId
   *          id of the process instance, cannot be null.
   * @param userId
   *          id of the user involve, cannot be null.
   * @param identityLinkType
   *          type of identityLink, cannot be null (@see {@link IdentityLinkType}).
   * @throws ActivitiObjectNotFoundException
   *           when the task or user doesn't exist.
   */
  void deleteUserIdentityLink(String processInstanceId, String userId, String identityLinkType);

  /**
   * Removes the association between a group and a process instance for the given identityLinkType.
   *
   * @param processInstanceId
   *          id of the process instance, cannot be null.
   * @param groupId
   *          id of the group to involve, cannot be null.
   * @param identityLinkType
   *          type of identity, cannot be null (@see {@link IdentityLinkType}).
   * @throws ActivitiObjectNotFoundException
   *           when the task or group doesn't exist.
   */
  void deleteGroupIdentityLink(String processInstanceId, String groupId, String identityLinkType);

  /**
   * Retrieves the {@link IdentityLink}s associated with the given process instance. Such an {@link IdentityLink} informs how a certain user is involved with a process instance.
   */
  List<IdentityLink> getIdentityLinksForProcessInstance(String instanceId);

  // Variables
  // ////////////////////////////////////////////////////////////////////

在这里插入图片描述

3.ProcessEngines

在这里插入图片描述

public abstract class ProcessEngines {

  private static Logger log = LoggerFactory.getLogger(ProcessEngines.class);

  public static final String NAME_DEFAULT = "default";

  protected static boolean isInitialized;
  protected static Map<String, ProcessEngine> processEngines = new HashMap<String, ProcessEngine>();
  protected static Map<String, ProcessEngineInfo> processEngineInfosByName = new HashMap<String, ProcessEngineInfo>();
  protected static Map<String, ProcessEngineInfo> processEngineInfosByResourceUrl = new HashMap<String, ProcessEngineInfo>();
  protected static List<ProcessEngineInfo> processEngineInfos = new ArrayList<ProcessEngineInfo>();

  /**
   * Initializes all process engines that can be found on the classpath for resources <code>activiti.cfg.xml</code> (plain Activiti style configuration) and for resources
   * <code>activiti-context.xml</code> (Spring style configuration).
   */
  public synchronized static void init() {
    if (!isInitialized()) {
      if (processEngines == null) {
        // Create new map to store process-engines if current map is
        // null
        processEngines = new HashMap<String, ProcessEngine>();
      }
      ClassLoader classLoader = ReflectUtil.getClassLoader();
      Enumeration<URL> resources = null;
      try {
        resources = classLoader.getResources("activiti.cfg.xml");
      } catch (IOException e) {
        throw new ActivitiIllegalArgumentException("problem retrieving activiti.cfg.xml resources on the classpath: " + System.getProperty("java.class.path"), e);
      }

      // Remove duplicated configuration URL's using set. Some
      // classloaders may return identical URL's twice, causing duplicate
      // startups
      Set<URL> configUrls = new HashSet<URL>();
      while (resources.hasMoreElements()) {
        configUrls.add(resources.nextElement());
      }
      for (Iterator<URL> iterator = configUrls.iterator(); iterator.hasNext();) {
        URL resource = iterator.next();
        log.info("Initializing process engine using configuration '{}'", resource.toString());
        initProcessEngineFromResource(resource);
      }

      try {
        resources = classLoader.getResources("activiti-context.xml");
      } catch (IOException e) {
        throw new ActivitiIllegalArgumentException("problem retrieving activiti-context.xml resources on the classpath: " + System.getProperty("java.class.path"), e);
      }
      while (resources.hasMoreElements()) {
        URL resource = resources.nextElement();
        log.info("Initializing process engine using Spring configuration '{}'", resource.toString());
        initProcessEngineFromSpringResource(resource);
      }

      setInitialized(true);
    } else {
      log.info("Process engines already initialized");
    }
  }

  protected static void initProcessEngineFromSpringResource(URL resource) {
    try {
      Class<?> springConfigurationHelperClass = ReflectUtil.loadClass("org.activiti.spring.SpringConfigurationHelper");
      Method method = springConfigurationHelperClass.getDeclaredMethod("buildProcessEngine", new Class<?>[] { URL.class });
      ProcessEngine processEngine = (ProcessEngine) method.invoke(null, new Object[] { resource });

      String processEngineName = processEngine.getName();
      ProcessEngineInfo processEngineInfo = new ProcessEngineInfoImpl(processEngineName, resource.toString(), null);
      processEngineInfosByName.put(processEngineName, processEngineInfo);
      processEngineInfosByResourceUrl.put(resource.toString(), processEngineInfo);

    } catch (Exception e) {
      throw new ActivitiException("couldn't initialize process engine from spring configuration resource " + resource.toString() + ": " + e.getMessage(), e);
    }
  }

  /**
   * Registers the given process engine. No {@link ProcessEngineInfo} will be available for this process engine. An engine that is registered will be closed when the {@link ProcessEngines#destroy()}
   * is called.
   */
  public static void registerProcessEngine(ProcessEngine processEngine) {
    processEngines.put(processEngine.getName(), processEngine);
  }

  /**
   * Unregisters the given process engine.
   */
  public static void unregister(ProcessEngine processEngine) {
    processEngines.remove(processEngine.getName());
  }

  private static ProcessEngineInfo initProcessEngineFromResource(URL resourceUrl) {
    ProcessEngineInfo processEngineInfo = processEngineInfosByResourceUrl.get(resourceUrl.toString());
    // if there is an existing process engine info
    if (processEngineInfo != null) {
      // remove that process engine from the member fields
      processEngineInfos.remove(processEngineInfo);
      if (processEngineInfo.getException() == null) {
        String processEngineName = processEngineInfo.getName();
        processEngines.remove(processEngineName);
        processEngineInfosByName.remove(processEngineName);
      }
      processEngineInfosByResourceUrl.remove(processEngineInfo.getResourceUrl());
    }

    String resourceUrlString = resourceUrl.toString();
    try {
      log.info("initializing process engine for resource {}", resourceUrl);
      ProcessEngine processEngine = buildProcessEngine(resourceUrl);
      String processEngineName = processEngine.getName();
      log.info("initialised process engine {}", processEngineName);
      processEngineInfo = new ProcessEngineInfoImpl(processEngineName, resourceUrlString, null);
      processEngines.put(processEngineName, processEngine);
      processEngineInfosByName.put(processEngineName, processEngineInfo);
    } catch (Throwable e) {
      log.error("Exception while initializing process engine: {}", e.getMessage(), e);
      processEngineInfo = new ProcessEngineInfoImpl(null, resourceUrlString, getExceptionString(e));
    }
    processEngineInfosByResourceUrl.put(resourceUrlString, processEngineInfo);
    processEngineInfos.add(processEngineInfo);
    return processEngineInfo;
  }

  private static String getExceptionString(Throwable e) {
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    e.printStackTrace(pw);
    return sw.toString();
  }

  private static ProcessEngine buildProcessEngine(URL resource) {
    InputStream inputStream = null;
    try {
      inputStream = resource.openStream();
      ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(inputStream);
      return processEngineConfiguration.buildProcessEngine();

    } catch (IOException e) {
      throw new ActivitiIllegalArgumentException("couldn't open resource stream: " + e.getMessage(), e);
    } finally {
      IoUtil.closeSilently(inputStream);
    }
  }

  /** Get initialization results. */
  public static List<ProcessEngineInfo> getProcessEngineInfos() {
    return processEngineInfos;
  }

  /**
   * Get initialization results. Only info will we available for process engines which were added in the {@link ProcessEngines#init()}. No {@link ProcessEngineInfo} is available for engines which were
   * registered programatically.
   */
  public static ProcessEngineInfo getProcessEngineInfo(String processEngineName) {
    return processEngineInfosByName.get(processEngineName);
  }

  public static ProcessEngine getDefaultProcessEngine() {
    return getProcessEngine(NAME_DEFAULT);
  }

  /**
   * obtain a process engine by name.
   *
   * @param processEngineName
   *          is the name of the process engine or null for the default process engine.
   */
  public static ProcessEngine getProcessEngine(String processEngineName) {
    if (!isInitialized()) {
      init();
    }
    return processEngines.get(processEngineName);
  }

  /**
   * retries to initialize a process engine that previously failed.
   */
  public static ProcessEngineInfo retry(String resourceUrl) {
    log.debug("retying initializing of resource {}", resourceUrl);
    try {
      return initProcessEngineFromResource(new URL(resourceUrl));
    } catch (MalformedURLException e) {
      throw new ActivitiIllegalArgumentException("invalid url: " + resourceUrl, e);
    }
  }

  /**
   * provides access to process engine to application clients in a managed server environment.
   */
  public static Map<String, ProcessEngine> getProcessEngines() {
    return processEngines;
  }

  /**
   * closes all process engines. This method should be called when the server shuts down.
   */
  public synchronized static void destroy() {
    if (isInitialized()) {
      Map<String, ProcessEngine> engines = new HashMap<String, ProcessEngine>(processEngines);
      processEngines = new HashMap<String, ProcessEngine>();

      for (String processEngineName : engines.keySet()) {
        ProcessEngine processEngine = engines.get(processEngineName);
        try {
          processEngine.close();
        } catch (Exception e) {
          log.error("exception while closing {}", (processEngineName == null ? "the default process engine" : "process engine " + processEngineName), e);
        }
      }

      processEngineInfosByName.clear();
      processEngineInfosByResourceUrl.clear();
      processEngineInfos.clear();

      setInitialized(false);
    }
  }

  public static boolean isInitialized() {
    return isInitialized;
  }

  public static void setInitialized(boolean isInitialized) {
    ProcessEngines.isInitialized = isInitialized;
  }
}

4.ProcessEngineLifecycleListener

public interface ProcessEngineLifecycleListener {

  /**
   * Called right after the process-engine has been built.
   *
   * @param processEngine
   *          engine that was built
   */
  void onProcessEngineBuilt(ProcessEngine processEngine);

  /**
   * Called right after the process-engine has been closed.
   *
   * @param processEngine
   *          engine that was closed
   */
  void onProcessEngineClosed(ProcessEngine processEngine);
}

5.ProcessEngines

public abstract class ProcessEngines {

  private static Logger log = LoggerFactory.getLogger(ProcessEngines.class);

  public static final String NAME_DEFAULT = "default";

  protected static boolean isInitialized;
  protected static Map<String, ProcessEngine> processEngines = new HashMap<String, ProcessEngine>();
  protected static Map<String, ProcessEngineInfo> processEngineInfosByName = new HashMap<String, ProcessEngineInfo>();
  protected static Map<String, ProcessEngineInfo> processEngineInfosByResourceUrl = new HashMap<String, ProcessEngineInfo>();
  protected static List<ProcessEngineInfo> processEngineInfos = new ArrayList<ProcessEngineInfo>();

  /**
   * Initializes all process engines that can be found on the classpath for resources <code>activiti.cfg.xml</code> (plain Activiti style configuration) and for resources
   * <code>activiti-context.xml</code> (Spring style configuration).
   */
  public synchronized static void init() {
    if (!isInitialized()) {
      if (processEngines == null) {
        // Create new map to store process-engines if current map is
        // null
        processEngines = new HashMap<String, ProcessEngine>();
      }
      ClassLoader classLoader = ReflectUtil.getClassLoader();
      Enumeration<URL> resources = null;
      try {
        resources = classLoader.getResources("activiti.cfg.xml");
      } catch (IOException e) {
        throw new ActivitiIllegalArgumentException("problem retrieving activiti.cfg.xml resources on the classpath: " + System.getProperty("java.class.path"), e);
      }

      // Remove duplicated configuration URL's using set. Some
      // classloaders may return identical URL's twice, causing duplicate
      // startups
      Set<URL> configUrls = new HashSet<URL>();
      while (resources.hasMoreElements()) {
        configUrls.add(resources.nextElement());
      }
      for (Iterator<URL> iterator = configUrls.iterator(); iterator.hasNext();) {
        URL resource = iterator.next();
        log.info("Initializing process engine using configuration '{}'", resource.toString());
        initProcessEngineFromResource(resource);
      }

      try {
        resources = classLoader.getResources("activiti-context.xml");
      } catch (IOException e) {
        throw new ActivitiIllegalArgumentException("problem retrieving activiti-context.xml resources on the classpath: " + System.getProperty("java.class.path"), e);
      }
      while (resources.hasMoreElements()) {
        URL resource = resources.nextElement();
        log.info("Initializing process engine using Spring configuration '{}'", resource.toString());
        initProcessEngineFromSpringResource(resource);
      }

      setInitialized(true);
    } else {
      log.info("Process engines already initialized");
    }
  }

  protected static void initProcessEngineFromSpringResource(URL resource) {
    try {
      Class<?> springConfigurationHelperClass = ReflectUtil.loadClass("org.activiti.spring.SpringConfigurationHelper");
      Method method = springConfigurationHelperClass.getDeclaredMethod("buildProcessEngine", new Class<?>[] { URL.class });
      ProcessEngine processEngine = (ProcessEngine) method.invoke(null, new Object[] { resource });

      String processEngineName = processEngine.getName();
      ProcessEngineInfo processEngineInfo = new ProcessEngineInfoImpl(processEngineName, resource.toString(), null);
      processEngineInfosByName.put(processEngineName, processEngineInfo);
      processEngineInfosByResourceUrl.put(resource.toString(), processEngineInfo);

    } catch (Exception e) {
      throw new ActivitiException("couldn't initialize process engine from spring configuration resource " + resource.toString() + ": " + e.getMessage(), e);
    }
  }

  /**
   * Registers the given process engine. No {@link ProcessEngineInfo} will be available for this process engine. An engine that is registered will be closed when the {@link ProcessEngines#destroy()}
   * is called.
   */
  public static void registerProcessEngine(ProcessEngine processEngine) {
    processEngines.put(processEngine.getName(), processEngine);
  }

  /**
   * Unregisters the given process engine.
   */
  public static void unregister(ProcessEngine processEngine) {
    processEngines.remove(processEngine.getName());
  }

  private static ProcessEngineInfo initProcessEngineFromResource(URL resourceUrl) {
    ProcessEngineInfo processEngineInfo = processEngineInfosByResourceUrl.get(resourceUrl.toString());
    // if there is an existing process engine info
    if (processEngineInfo != null) {
      // remove that process engine from the member fields
      processEngineInfos.remove(processEngineInfo);
      if (processEngineInfo.getException() == null) {
        String processEngineName = processEngineInfo.getName();
        processEngines.remove(processEngineName);
        processEngineInfosByName.remove(processEngineName);
      }
      processEngineInfosByResourceUrl.remove(processEngineInfo.getResourceUrl());
    }

    String resourceUrlString = resourceUrl.toString();
    try {
      log.info("initializing process engine for resource {}", resourceUrl);
      ProcessEngine processEngine = buildProcessEngine(resourceUrl);
      String processEngineName = processEngine.getName();
      log.info("initialised process engine {}", processEngineName);
      processEngineInfo = new ProcessEngineInfoImpl(processEngineName, resourceUrlString, null);
      processEngines.put(processEngineName, processEngine);
      processEngineInfosByName.put(processEngineName, processEngineInfo);
    } catch (Throwable e) {
      log.error("Exception while initializing process engine: {}", e.getMessage(), e);
      processEngineInfo = new ProcessEngineInfoImpl(null, resourceUrlString, getExceptionString(e));
    }
    processEngineInfosByResourceUrl.put(resourceUrlString, processEngineInfo);
    processEngineInfos.add(processEngineInfo);
    return processEngineInfo;
  }

  private static String getExceptionString(Throwable e) {
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    e.printStackTrace(pw);
    return sw.toString();
  }

  private static ProcessEngine buildProcessEngine(URL resource) {
    InputStream inputStream = null;
    try {
      inputStream = resource.openStream();
      ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(inputStream);
      return processEngineConfiguration.buildProcessEngine();

    } catch (IOException e) {
      throw new ActivitiIllegalArgumentException("couldn't open resource stream: " + e.getMessage(), e);
    } finally {
      IoUtil.closeSilently(inputStream);
    }
  }

  /** Get initialization results. */
  public static List<ProcessEngineInfo> getProcessEngineInfos() {
    return processEngineInfos;
  }

  /**
   * Get initialization results. Only info will we available for process engines which were added in the {@link ProcessEngines#init()}. No {@link ProcessEngineInfo} is available for engines which were
   * registered programatically.
   */
  public static ProcessEngineInfo getProcessEngineInfo(String processEngineName) {
    return processEngineInfosByName.get(processEngineName);
  }

  public static ProcessEngine getDefaultProcessEngine() {
    return getProcessEngine(NAME_DEFAULT);
  }

  /**
   * obtain a process engine by name.
   *
   * @param processEngineName
   *          is the name of the process engine or null for the default process engine.
   */
  public static ProcessEngine getProcessEngine(String processEngineName) {
    if (!isInitialized()) {
      init();
    }
    return processEngines.get(processEngineName);
  }

  /**
   * retries to initialize a process engine that previously failed.
   */
  public static ProcessEngineInfo retry(String resourceUrl) {
    log.debug("retying initializing of resource {}", resourceUrl);
    try {
      return initProcessEngineFromResource(new URL(resourceUrl));
    } catch (MalformedURLException e) {
      throw new ActivitiIllegalArgumentException("invalid url: " + resourceUrl, e);
    }
  }

在这里插入图片描述

参考资料和推荐阅读

[1].www.activite.org

欢迎阅读,各位老铁,如果对你有帮助,点个赞加个关注呗!~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迅捷的软件产品制作专家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值