org.activiti.engine
- 目录
- 概述
- 需求:
- 设计思路
- 实现思路分析
- 1.TaskService
- 2.RuntimeService
- 3.ProcessEngines
- 4.ProcessEngineLifecycleListener
- 5.ProcessEngines
- 参考资料和推荐阅读
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
欢迎阅读,各位老铁,如果对你有帮助,点个赞加个关注呗!~