提交 6b49dd42 编写于 作者: T Tijs Rademakers

Add dynamic bpmn to Activiti 5 compatibility engine

上级 0e3bde19
......@@ -34,6 +34,8 @@ import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Attachment;
import org.activiti.engine.task.Comment;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Joram Barrez
* @author Tijs Rademakers
......@@ -50,6 +52,10 @@ public interface Activiti5CompatibilityHandler {
BpmnModel getProcessDefinitionBpmnModel(String processDefinitionId);
ObjectNode getProcessDefinitionInfo(String processDefinitionId);
void saveProcessDefinitionInfo(String processDefinitionId, ObjectNode infoNode);
void addCandidateStarter(String processDefinitionId, String userId, String groupId);
void deleteCandidateStarter(String processDefinitionId, String userId, String groupId);
......
......@@ -15,10 +15,13 @@ package org.activiti.engine.impl.cmd;
import java.io.Serializable;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.compatibility.Activiti5CompatibilityHandler;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.deploy.DeploymentManager;
import org.activiti.engine.impl.persistence.deploy.ProcessDefinitionInfoCacheObject;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.util.Activiti5Util;
import com.fasterxml.jackson.databind.node.ObjectNode;
......@@ -44,7 +47,12 @@ public class GetProcessDefinitionInfoCmd implements Command<ObjectNode>, Seriali
ObjectNode resultNode = null;
DeploymentManager deploymentManager = commandContext.getProcessEngineConfiguration().getDeploymentManager();
// make sure the process definition is in the cache
deploymentManager.findDeployedProcessDefinitionById(processDefinitionId);
ProcessDefinitionEntity processDefinition = deploymentManager.findDeployedProcessDefinitionById(processDefinitionId);
if (Activiti5Util.isActiviti5ProcessDefinition(commandContext, processDefinition)) {
Activiti5CompatibilityHandler activiti5CompatibilityHandler = Activiti5Util.getActiviti5CompatibilityHandler();
return activiti5CompatibilityHandler.getProcessDefinitionInfo(processDefinitionId);
}
ProcessDefinitionInfoCacheObject definitionInfoCacheObject = deploymentManager.getProcessDefinitionInfoCache().get(processDefinitionId);
if (definitionInfoCacheObject != null) {
resultNode = definitionInfoCacheObject.getInfoNode();
......
......@@ -16,10 +16,12 @@ import java.io.Serializable;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.compatibility.Activiti5CompatibilityHandler;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionInfoEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionInfoEntityManager;
import org.activiti.engine.impl.util.Activiti5Util;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.node.ObjectNode;
......@@ -49,6 +51,12 @@ public class SaveProcessDefinitionInfoCmd implements Command<Void>, Serializable
throw new ActivitiIllegalArgumentException("process definition info node is null");
}
if (Activiti5Util.isActiviti5ProcessDefinitionId(commandContext, processDefinitionId)) {
Activiti5CompatibilityHandler activiti5CompatibilityHandler = Activiti5Util.getActiviti5CompatibilityHandler();
activiti5CompatibilityHandler.saveProcessDefinitionInfo(processDefinitionId, infoNode);
return null;
}
ProcessDefinitionInfoEntityManager definitionInfoEntityManager = commandContext.getProcessDefinitionInfoEntityManager();
ProcessDefinitionInfoEntity definitionInfoEntity = definitionInfoEntityManager.findProcessDefinitionInfoByProcessDefinitionId(processDefinitionId);
if (definitionInfoEntity == null) {
......
......@@ -74,6 +74,8 @@ import org.activiti5.engine.impl.pvm.delegate.ActivityExecution;
import org.activiti5.engine.impl.scripting.ScriptingEngines;
import org.activiti5.engine.repository.DeploymentBuilder;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Joram Barrez
* @author Tijs Rademakers
......@@ -156,6 +158,25 @@ public class DefaultActiviti5CompatibilityHandler implements Activiti5Compatibil
}
}
public ObjectNode getProcessDefinitionInfo(String processDefinitionId) {
try {
return getProcessEngine().getDynamicBpmnService().getProcessDefinitionInfo(processDefinitionId);
} catch (org.activiti5.engine.ActivitiException e) {
handleActivitiException(e);
return null;
}
}
public void saveProcessDefinitionInfo(String processDefinitionId, ObjectNode infoNode) {
try {
getProcessEngine().getDynamicBpmnService().saveProcessDefinitionInfo(processDefinitionId, infoNode);
} catch (org.activiti5.engine.ActivitiException e) {
handleActivitiException(e);
}
}
public void deleteCandidateStarter(String processDefinitionId, String userId, String groupId) {
try {
if (userId != null) {
......
......@@ -102,6 +102,7 @@ public class DefaultProcessEngineFactory {
activiti5Configuration.setCreateDiagramOnDeploy(activiti6Configuration.isCreateDiagramOnDeploy());
activiti5Configuration.setProcessDefinitionCacheLimit(activiti6Configuration.getProcessDefinitionCacheLimit());
activiti5Configuration.setEnableProcessDefinitionInfoCache(activiti6Configuration.isEnableProcessDefinitionInfoCache());
if (activiti6Configuration.isAsyncExecutorEnabled()) {
activiti5Configuration.setAsyncExecutorEnabled(true);
......
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti5.engine;
import com.fasterxml.jackson.databind.node.ObjectNode;
/** Service providing access to the repository of process definitions and deployments.
*
* @author Tijs Rademakers
*/
public interface DynamicBpmnService {
ObjectNode getProcessDefinitionInfo(String processDefinitionId);
void saveProcessDefinitionInfo(String processDefinitionId, ObjectNode infoNode);
ObjectNode changeServiceTaskClassName(String id, String className);
void changeServiceTaskClassName(String id, String className, ObjectNode infoNode);
ObjectNode changeServiceTaskExpression(String id, String expression);
void changeServiceTaskExpression(String id, String expression, ObjectNode infoNode);
ObjectNode changeServiceTaskDelegateExpression(String id, String expression);
void changeServiceTaskDelegateExpression(String id, String expression, ObjectNode infoNode);
ObjectNode changeUserTaskName(String id, String name);
void changeUserTaskName(String id, String name, ObjectNode infoNode);
ObjectNode changeUserTaskDescription(String id, String description);
void changeUserTaskDescription(String id, String description, ObjectNode infoNode);
ObjectNode changeUserTaskDueDate(String id, String dueDate);
void changeUserTaskDueDate(String id, String dueDate, ObjectNode infoNode);
ObjectNode changeUserTaskPriority(String id, String priority);
void changeUserTaskPriority(String id, String priority, ObjectNode infoNode);
ObjectNode changeUserTaskCategory(String id, String category);
void changeUserTaskCategory(String id, String category, ObjectNode infoNode);
ObjectNode changeUserTaskFormKey(String id, String formKey);
void changeUserTaskFormKey(String id, String formKey, ObjectNode infoNode);
ObjectNode changeUserTaskAssignee(String id, String assignee);
void changeUserTaskAssignee(String id, String assignee, ObjectNode infoNode);
ObjectNode changeUserTaskOwner(String id, String owner);
void changeUserTaskOwner(String id, String owner, ObjectNode infoNode);
ObjectNode changeUserTaskCandidateUser(String id, String candidateUser, boolean overwriteOtherChangedEntries);
void changeUserTaskCandidateUser(String id, String candidateUser, boolean overwriteOtherChangedEntries, ObjectNode infoNode);
ObjectNode changeUserTaskCandidateGroup(String id, String candidateGroup, boolean overwriteOtherChangedEntries);
void changeUserTaskCandidateGroup(String id, String candidateGroup, boolean overwriteOtherChangedEntries, ObjectNode infoNode);
ObjectNode getBpmnElementProperties(String id, ObjectNode infoNode);
ObjectNode changeLocalizationName(String language, String id, String value);
void changeLocalizationName(String language, String id, String value, ObjectNode infoNode);
ObjectNode changeLocalizationDescription(String language, String id, String value);
void changeLocalizationDescription(String language, String id, String value, ObjectNode infoNode);
ObjectNode getLocalizationElementProperties(String language, String id, ObjectNode infoNode);
}
\ No newline at end of file
......@@ -73,5 +73,7 @@ public interface ProcessEngine {
ManagementService getManagementService();
DynamicBpmnService getDynamicBpmnService();
ProcessEngineConfiguration getProcessEngineConfiguration();
}
......@@ -214,6 +214,8 @@ public abstract class ProcessEngineConfiguration {
protected boolean useClassForNameClassLoading = true;
protected ProcessEngineLifecycleListener processEngineLifecycleListener;
protected boolean enableProcessDefinitionInfoCache = false;
/** use one of the static createXxxx methods instead */
protected ProcessEngineConfiguration() {
}
......@@ -809,4 +811,13 @@ public abstract class ProcessEngineConfiguration {
this.asyncFailedJobWaitTime = asyncFailedJobWaitTime;
return this;
}
public boolean isEnableProcessDefinitionInfoCache() {
return enableProcessDefinitionInfoCache;
}
public ProcessEngineConfiguration setEnableProcessDefinitionInfoCache(boolean enableProcessDefinitionInfoCache) {
this.enableProcessDefinitionInfoCache = enableProcessDefinitionInfoCache;
return this;
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti5.engine.impl;
import org.activiti.engine.DynamicBpmnConstants;
import org.activiti5.engine.DynamicBpmnService;
import org.activiti5.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti5.engine.impl.cmd.GetProcessDefinitionInfoCmd;
import org.activiti5.engine.impl.cmd.SaveProcessDefinitionInfoCmd;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Tijs Rademakers
*/
public class DynamicBpmnServiceImpl extends ServiceImpl implements DynamicBpmnService, DynamicBpmnConstants {
public DynamicBpmnServiceImpl(ProcessEngineConfigurationImpl processEngineConfiguration) {
super(processEngineConfiguration);
}
public ObjectNode getProcessDefinitionInfo(String processDefinitionId) {
return commandExecutor.execute(new GetProcessDefinitionInfoCmd(processDefinitionId));
}
public void saveProcessDefinitionInfo(String processDefinitionId, ObjectNode infoNode) {
commandExecutor.execute(new SaveProcessDefinitionInfoCmd(processDefinitionId, infoNode));
}
public ObjectNode changeServiceTaskClassName(String id, String className) {
ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
changeServiceTaskClassName(id, className, infoNode);
return infoNode;
}
public void changeServiceTaskClassName(String id, String className, ObjectNode infoNode) {
setElementProperty(id, SERVICE_TASK_CLASS_NAME, className, infoNode);
}
public ObjectNode changeServiceTaskExpression(String id, String expression) {
ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
changeServiceTaskExpression(id, expression, infoNode);
return infoNode;
}
public void changeServiceTaskExpression(String id, String expression, ObjectNode infoNode) {
setElementProperty(id, SERVICE_TASK_EXPRESSION, expression, infoNode);
}
public ObjectNode changeServiceTaskDelegateExpression(String id, String expression) {
ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
changeServiceTaskDelegateExpression(id, expression, infoNode);
return infoNode;
}
public void changeServiceTaskDelegateExpression(String id, String expression, ObjectNode infoNode) {
setElementProperty(id, SERVICE_TASK_DELEGATE_EXPRESSION, expression, infoNode);
}
public ObjectNode changeUserTaskName(String id, String name) {
ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
changeUserTaskName(id, name, infoNode);
return infoNode;
}
public void changeUserTaskName(String id, String name, ObjectNode infoNode) {
setElementProperty(id, USER_TASK_NAME, name, infoNode);
}
public ObjectNode changeUserTaskDescription(String id, String description) {
ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
changeUserTaskDescription(id, description, infoNode);
return infoNode;
}
public void changeUserTaskDescription(String id, String description, ObjectNode infoNode) {
setElementProperty(id, USER_TASK_DESCRIPTION, description, infoNode);
}
public ObjectNode changeUserTaskDueDate(String id, String dueDate) {
ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
changeUserTaskDueDate(id, dueDate, infoNode);
return infoNode;
}
public void changeUserTaskDueDate(String id, String dueDate, ObjectNode infoNode) {
setElementProperty(id, USER_TASK_DUEDATE, dueDate, infoNode);
}
public ObjectNode changeUserTaskPriority(String id, String priority) {
ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
changeUserTaskPriority(id, priority, infoNode);
return infoNode;
}
public void changeUserTaskPriority(String id, String priority, ObjectNode infoNode) {
setElementProperty(id, USER_TASK_PRIORITY, priority, infoNode);
}
public ObjectNode changeUserTaskCategory(String id, String category) {
ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
changeUserTaskCategory(id, category, infoNode);
return infoNode;
}
public void changeUserTaskCategory(String id, String category, ObjectNode infoNode) {
setElementProperty(id, USER_TASK_CATEGORY, category, infoNode);
}
public ObjectNode changeUserTaskFormKey(String id, String formKey) {
ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
changeUserTaskFormKey(id, formKey, infoNode);
return infoNode;
}
public void changeUserTaskFormKey(String id, String formKey, ObjectNode infoNode) {
setElementProperty(id, USER_TASK_FORM_KEY, formKey, infoNode);
}
public ObjectNode changeUserTaskAssignee(String id, String assignee) {
ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
changeUserTaskAssignee(id, assignee, infoNode);
return infoNode;
}
public void changeUserTaskAssignee(String id, String assignee, ObjectNode infoNode) {
setElementProperty(id, USER_TASK_ASSIGNEE, assignee, infoNode);
}
public ObjectNode changeUserTaskOwner(String id, String owner) {
ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
changeUserTaskOwner(id, owner, infoNode);
return infoNode;
}
public void changeUserTaskOwner(String id, String owner, ObjectNode infoNode) {
setElementProperty(id, USER_TASK_OWNER, owner, infoNode);
}
public ObjectNode changeUserTaskCandidateUser(String id, String candidateUser, boolean overwriteOtherChangedEntries) {
ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
changeUserTaskCandidateUser(id, candidateUser, overwriteOtherChangedEntries, infoNode);
return infoNode;
}
public void changeUserTaskCandidateUser(String id, String candidateUser, boolean overwriteOtherChangedEntries, ObjectNode infoNode) {
ArrayNode valuesNode = null;
if (overwriteOtherChangedEntries) {
valuesNode = processEngineConfiguration.getObjectMapper().createArrayNode();
} else {
if (doesElementPropertyExist(id, USER_TASK_CANDIDATE_USERS, infoNode)) {
valuesNode = (ArrayNode) infoNode.get(BPMN_NODE).get(id).get(USER_TASK_CANDIDATE_USERS);
}
if (valuesNode == null || valuesNode.isNull()) {
valuesNode = processEngineConfiguration.getObjectMapper().createArrayNode();
}
}
valuesNode.add(candidateUser);
setElementProperty(id, USER_TASK_CANDIDATE_USERS, valuesNode, infoNode);
}
public ObjectNode changeUserTaskCandidateGroup(String id, String candidateGroup, boolean overwriteOtherChangedEntries) {
ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
changeUserTaskCandidateGroup(id, candidateGroup, overwriteOtherChangedEntries, infoNode);
return infoNode;
}
public void changeUserTaskCandidateGroup(String id, String candidateGroup, boolean overwriteOtherChangedEntries, ObjectNode infoNode) {
ArrayNode valuesNode = null;
if (overwriteOtherChangedEntries) {
valuesNode = processEngineConfiguration.getObjectMapper().createArrayNode();
} else {
if (doesElementPropertyExist(id, USER_TASK_CANDIDATE_GROUPS, infoNode)) {
valuesNode = (ArrayNode) infoNode.get(BPMN_NODE).get(id).get(USER_TASK_CANDIDATE_GROUPS);
}
if (valuesNode == null || valuesNode.isNull()) {
valuesNode = processEngineConfiguration.getObjectMapper().createArrayNode();
}
}
valuesNode.add(candidateGroup);
setElementProperty(id, USER_TASK_CANDIDATE_GROUPS, valuesNode, infoNode);
}
public ObjectNode getBpmnElementProperties(String id, ObjectNode infoNode) {
ObjectNode propertiesNode = null;
ObjectNode bpmnNode = getBpmnNode(infoNode);
if (bpmnNode != null) {
propertiesNode = (ObjectNode) bpmnNode.get(id);
}
return propertiesNode;
}
public ObjectNode changeLocalizationName(String language, String id, String value) {
ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
changeLocalizationName(language, id, value, infoNode);
return infoNode;
}
public void changeLocalizationName(String language, String id, String value, ObjectNode infoNode) {
setLocalizationProperty(language, id, LOCALIZATION_NAME, value, infoNode);
}
public ObjectNode changeLocalizationDescription(String language, String id, String value) {
ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
changeLocalizationDescription(language, id, value, infoNode);
return infoNode;
}
public void changeLocalizationDescription(String language, String id, String value, ObjectNode infoNode) {
setLocalizationProperty(language, id, LOCALIZATION_DESCRIPTION, value, infoNode);
}
public ObjectNode getLocalizationElementProperties(String language, String id, ObjectNode infoNode) {
ObjectNode propertiesNode = null;
ObjectNode localizationNode = getLocalizationNode(infoNode);
if (localizationNode != null) {
JsonNode languageNode = localizationNode.get(language);
if (languageNode != null) {
propertiesNode = (ObjectNode) languageNode.get(id);
}
}
return propertiesNode;
}
protected boolean doesElementPropertyExist(String id, String propertyName, ObjectNode infoNode) {
boolean exists = false;
if (infoNode.get(BPMN_NODE) != null && infoNode.get(BPMN_NODE).get(id) != null && infoNode.get(BPMN_NODE).get(id).get(propertyName) != null) {
JsonNode propNode = infoNode.get(BPMN_NODE).get(id).get(propertyName);
if (propNode.isNull() == false) {
exists = true;
}
}
return exists;
}
protected void setElementProperty(String id, String propertyName, String propertyValue, ObjectNode infoNode) {
ObjectNode bpmnNode = createOrGetBpmnNode(infoNode);
if (bpmnNode.has(id) == false) {
bpmnNode.put(id, processEngineConfiguration.getObjectMapper().createObjectNode());
}
((ObjectNode) bpmnNode.get(id)).put(propertyName, propertyValue);
}
protected void setElementProperty(String id, String propertyName, JsonNode propertyValue, ObjectNode infoNode) {
ObjectNode bpmnNode = createOrGetBpmnNode(infoNode);
if (bpmnNode.has(id) == false) {
bpmnNode.put(id, processEngineConfiguration.getObjectMapper().createObjectNode());
}
((ObjectNode) bpmnNode.get(id)).put(propertyName, propertyValue);
}
protected ObjectNode createOrGetBpmnNode(ObjectNode infoNode) {
if (infoNode.has(BPMN_NODE) == false) {
infoNode.put(BPMN_NODE, processEngineConfiguration.getObjectMapper().createObjectNode());
}
return (ObjectNode) infoNode.get(BPMN_NODE);
}
protected ObjectNode getBpmnNode(ObjectNode infoNode) {
return (ObjectNode) infoNode.get(BPMN_NODE);
}
protected void setLocalizationProperty(String language, String id, String propertyName, String propertyValue, ObjectNode infoNode) {
ObjectNode localizationNode = createOrGetLocalizationNode(infoNode);
if (localizationNode.has(language) == false) {
localizationNode.put(language, processEngineConfiguration.getObjectMapper().createObjectNode());
}
ObjectNode languageNode = (ObjectNode) localizationNode.get(language);
if (languageNode.has(id) == false) {
languageNode.put(id, processEngineConfiguration.getObjectMapper().createObjectNode());
}
((ObjectNode) languageNode.get(id)).put(propertyName, propertyValue);
}
protected ObjectNode createOrGetLocalizationNode(ObjectNode infoNode) {
if (infoNode.has(LOCALIZATION_NODE) == false) {
infoNode.put(LOCALIZATION_NODE, processEngineConfiguration.getObjectMapper().createObjectNode());
}
return (ObjectNode) infoNode.get(LOCALIZATION_NODE);
}
protected ObjectNode getLocalizationNode(ObjectNode infoNode) {
return (ObjectNode) infoNode.get(LOCALIZATION_NODE);
}
}
\ No newline at end of file
......@@ -14,6 +14,7 @@ package org.activiti5.engine.impl;
import java.util.Map;
import org.activiti5.engine.DynamicBpmnService;
import org.activiti5.engine.FormService;
import org.activiti5.engine.HistoryService;
import org.activiti5.engine.IdentityService;
......@@ -37,6 +38,7 @@ import org.slf4j.LoggerFactory;
/**
* @author Tom Baeyens
* @author Tijs Rademakers
*/
public class ProcessEngineImpl implements ProcessEngine {
......@@ -50,6 +52,7 @@ public class ProcessEngineImpl implements ProcessEngine {
protected TaskService taskService;
protected FormService formService;
protected ManagementService managementService;
protected DynamicBpmnService dynamicBpmnService;
protected JobExecutor jobExecutor;
protected AsyncExecutor asyncExecutor;
protected CommandExecutor commandExecutor;
......@@ -68,6 +71,7 @@ public class ProcessEngineImpl implements ProcessEngine {
this.taskService = processEngineConfiguration.getTaskService();
this.formService = processEngineConfiguration.getFormService();
this.managementService = processEngineConfiguration.getManagementService();
this.dynamicBpmnService = processEngineConfiguration.getDynamicBpmnService();
this.jobExecutor = processEngineConfiguration.getJobExecutor();
this.asyncExecutor = processEngineConfiguration.getAsyncExecutor();
this.commandExecutor = processEngineConfiguration.getCommandExecutor();
......@@ -154,6 +158,10 @@ public class ProcessEngineImpl implements ProcessEngine {
return formService;
}
public DynamicBpmnService getDynamicBpmnService() {
return dynamicBpmnService;
}
public ProcessEngineConfigurationImpl getProcessEngineConfiguration() {
return processEngineConfiguration;
}
......
......@@ -15,6 +15,7 @@ package org.activiti5.engine.impl.bpmn.behavior;
import java.util.List;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.DynamicBpmnConstants;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.delegate.JavaDelegate;
......@@ -30,6 +31,9 @@ import org.activiti5.engine.impl.delegate.ActivityBehaviorInvocation;
import org.activiti5.engine.impl.delegate.JavaDelegateInvocation;
import org.activiti5.engine.impl.pvm.delegate.ActivityExecution;
import org.activiti5.engine.impl.pvm.delegate.SignallableActivityBehavior;
import org.apache.commons.lang3.StringUtils;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
......@@ -43,11 +47,13 @@ import org.activiti5.engine.impl.pvm.delegate.SignallableActivityBehavior;
*/
public class ServiceTaskDelegateExpressionActivityBehavior extends TaskActivityBehavior {
protected String serviceTaskId;
protected Expression expression;
protected Expression skipExpression;
private final List<FieldDeclaration> fieldDeclarations;
public ServiceTaskDelegateExpressionActivityBehavior(Expression expression, Expression skipExpression, List<FieldDeclaration> fieldDeclarations) {
public ServiceTaskDelegateExpressionActivityBehavior(String serviceTaskId, Expression expression, Expression skipExpression, List<FieldDeclaration> fieldDeclarations) {
this.serviceTaskId = serviceTaskId;
this.expression = expression;
this.skipExpression = skipExpression;
this.fieldDeclarations = fieldDeclarations;
......@@ -69,9 +75,18 @@ public class ServiceTaskDelegateExpressionActivityBehavior extends TaskActivityB
if (!isSkipExpressionEnabled ||
(isSkipExpressionEnabled && !SkipExpressionUtil.shouldSkipFlowElement(activityExecution, skipExpression))) {
if (Context.getProcessEngineConfiguration().isEnableProcessDefinitionInfoCache()) {
ObjectNode taskElementProperties = Context.getBpmnOverrideElementProperties(serviceTaskId, execution.getProcessDefinitionId());
if (taskElementProperties != null && taskElementProperties.has(DynamicBpmnConstants.SERVICE_TASK_DELEGATE_EXPRESSION)) {
String overrideExpression = taskElementProperties.get(DynamicBpmnConstants.SERVICE_TASK_DELEGATE_EXPRESSION).asText();
if (StringUtils.isNotEmpty(overrideExpression) && overrideExpression.equals(expression.getExpressionText()) == false) {
expression = Context.getProcessEngineConfiguration().getExpressionManager().createExpression(overrideExpression);
}
}
}
// Note: we can't cache the result of the expression, because the
// execution can change: eg.
// delegateExpression='${mySpringBeanFactory.randomSpringBean()}'
// execution can change: eg. delegateExpression='${mySpringBeanFactory.randomSpringBean()}'
Object delegate = expression.getValue(execution);
ClassDelegate.applyFieldDeclaration(fieldDeclarations, delegate);
......
......@@ -14,12 +14,17 @@
package org.activiti5.engine.impl.bpmn.behavior;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.DynamicBpmnConstants;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.Expression;
import org.activiti5.engine.delegate.BpmnError;
import org.activiti5.engine.impl.bpmn.helper.ErrorPropagation;
import org.activiti5.engine.impl.bpmn.helper.SkipExpressionUtil;
import org.activiti5.engine.impl.context.Context;
import org.activiti5.engine.impl.pvm.delegate.ActivityExecution;
import org.apache.commons.lang3.StringUtils;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* ActivityBehavior that evaluates an expression when executed. Optionally, it
......@@ -33,11 +38,13 @@ import org.activiti5.engine.impl.pvm.delegate.ActivityExecution;
*/
public class ServiceTaskExpressionActivityBehavior extends TaskActivityBehavior {
protected String serviceTaskId;
protected Expression expression;
protected Expression skipExpression;
protected String resultVariable;
public ServiceTaskExpressionActivityBehavior(Expression expression, Expression skipExpression, String resultVariable) {
public ServiceTaskExpressionActivityBehavior(String serviceTaskId, Expression expression, Expression skipExpression, String resultVariable) {
this.serviceTaskId = serviceTaskId;
this.expression = expression;
this.skipExpression = skipExpression;
this.resultVariable = resultVariable;
......@@ -50,6 +57,17 @@ public class ServiceTaskExpressionActivityBehavior extends TaskActivityBehavior
boolean isSkipExpressionEnabled = SkipExpressionUtil.isSkipExpressionEnabled(activityExecution, skipExpression);
if (!isSkipExpressionEnabled ||
(isSkipExpressionEnabled && !SkipExpressionUtil.shouldSkipFlowElement(activityExecution, skipExpression))) {
if (Context.getProcessEngineConfiguration().isEnableProcessDefinitionInfoCache()) {
ObjectNode taskElementProperties = Context.getBpmnOverrideElementProperties(serviceTaskId, execution.getProcessDefinitionId());
if (taskElementProperties != null && taskElementProperties.has(DynamicBpmnConstants.SERVICE_TASK_EXPRESSION)) {
String overrideExpression = taskElementProperties.get(DynamicBpmnConstants.SERVICE_TASK_EXPRESSION).asText();
if (StringUtils.isNotEmpty(overrideExpression) && overrideExpression.equals(expression.getExpressionText()) == false) {
expression = Context.getProcessEngineConfiguration().getExpressionManager().createExpression(overrideExpression);
}
}
}
value = expression.getValue(execution);
if (resultVariable != null) {
execution.setVariable(resultVariable, value);
......
......@@ -15,11 +15,13 @@ package org.activiti5.engine.impl.bpmn.behavior;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.activiti.engine.DynamicBpmnConstants;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.delegate.TaskListener;
......@@ -31,6 +33,7 @@ import org.activiti5.engine.impl.bpmn.helper.SkipExpressionUtil;
import org.activiti5.engine.impl.calendar.BusinessCalendar;
import org.activiti5.engine.impl.calendar.DueDateBusinessCalendar;
import org.activiti5.engine.impl.context.Context;
import org.activiti5.engine.impl.el.ExpressionManager;
import org.activiti5.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti5.engine.impl.persistence.entity.TaskEntity;
import org.activiti5.engine.impl.pvm.delegate.ActivityExecution;
......@@ -38,6 +41,9 @@ import org.activiti5.engine.impl.task.TaskDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* activity implementation for the user task.
*
......@@ -49,9 +55,11 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior {
private static final Logger LOGGER = LoggerFactory.getLogger(UserTaskActivityBehavior.class);
protected String userTaskId;
protected TaskDefinition taskDefinition;
public UserTaskActivityBehavior(TaskDefinition taskDefinition) {
public UserTaskActivityBehavior(String userTaskId, TaskDefinition taskDefinition) {
this.userTaskId = userTaskId;
this.taskDefinition = taskDefinition;
}
......@@ -59,32 +67,84 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior {
ActivityExecution activityExecution = (ActivityExecution) execution;
TaskEntity task = TaskEntity.createAndInsert(activityExecution);
task.setExecution(execution);
Expression activeNameExpression = null;
Expression activeDescriptionExpression = null;
Expression activeDueDateExpression = null;
Expression activePriorityExpression = null;
Expression activeCategoryExpression = null;
Expression activeFormKeyExpression = null;
Expression activeSkipExpression = null;
Expression activeAssigneeExpression = null;
Expression activeOwnerExpression = null;
Set<Expression> activeCandidateUserExpressions = null;
Set<Expression> activeCandidateGroupExpressions = null;
if (Context.getProcessEngineConfiguration().isEnableProcessDefinitionInfoCache()) {
ObjectNode taskElementProperties = Context.getBpmnOverrideElementProperties(userTaskId, execution.getProcessDefinitionId());
activeNameExpression = getActiveValue(taskDefinition.getNameExpression(), DynamicBpmnConstants.USER_TASK_NAME, taskElementProperties);
taskDefinition.setNameExpression(activeNameExpression);
activeDescriptionExpression = getActiveValue(taskDefinition.getDescriptionExpression(), DynamicBpmnConstants.USER_TASK_DESCRIPTION, taskElementProperties);
taskDefinition.setDescriptionExpression(activeDescriptionExpression);
activeDueDateExpression = getActiveValue(taskDefinition.getDueDateExpression(), DynamicBpmnConstants.USER_TASK_DUEDATE, taskElementProperties);
taskDefinition.setDueDateExpression(activeDueDateExpression);
activePriorityExpression = getActiveValue(taskDefinition.getPriorityExpression(), DynamicBpmnConstants.USER_TASK_PRIORITY, taskElementProperties);
taskDefinition.setPriorityExpression(activePriorityExpression);
activeCategoryExpression = getActiveValue(taskDefinition.getCategoryExpression(), DynamicBpmnConstants.USER_TASK_CATEGORY, taskElementProperties);
taskDefinition.setCategoryExpression(activeCategoryExpression);
activeFormKeyExpression = getActiveValue(taskDefinition.getFormKeyExpression(), DynamicBpmnConstants.USER_TASK_FORM_KEY, taskElementProperties);
taskDefinition.setFormKeyExpression(activeFormKeyExpression);
activeSkipExpression = getActiveValue(taskDefinition.getSkipExpression(), DynamicBpmnConstants.TASK_SKIP_EXPRESSION, taskElementProperties);
taskDefinition.setSkipExpression(activeSkipExpression);
activeAssigneeExpression = getActiveValue(taskDefinition.getAssigneeExpression(), DynamicBpmnConstants.USER_TASK_ASSIGNEE, taskElementProperties);
taskDefinition.setAssigneeExpression(activeAssigneeExpression);
activeOwnerExpression = getActiveValue(taskDefinition.getOwnerExpression(), DynamicBpmnConstants.USER_TASK_OWNER, taskElementProperties);
taskDefinition.setOwnerExpression(activeOwnerExpression);
activeCandidateUserExpressions = getActiveValueSet(taskDefinition.getCandidateUserIdExpressions(), DynamicBpmnConstants.USER_TASK_CANDIDATE_USERS, taskElementProperties);
taskDefinition.setCandidateUserIdExpressions(activeCandidateUserExpressions);
activeCandidateGroupExpressions = getActiveValueSet(taskDefinition.getCandidateGroupIdExpressions(), DynamicBpmnConstants.USER_TASK_CANDIDATE_GROUPS, taskElementProperties);
taskDefinition.setCandidateGroupIdExpressions(activeCandidateGroupExpressions);
} else {
activeNameExpression = taskDefinition.getNameExpression();
activeDescriptionExpression = taskDefinition.getDescriptionExpression();
activeDueDateExpression = taskDefinition.getDueDateExpression();
activePriorityExpression = taskDefinition.getPriorityExpression();
activeCategoryExpression = taskDefinition.getCategoryExpression();
activeFormKeyExpression = taskDefinition.getFormKeyExpression();
activeSkipExpression = taskDefinition.getSkipExpression();
activeAssigneeExpression = taskDefinition.getAssigneeExpression();
activeOwnerExpression = taskDefinition.getOwnerExpression();
activeCandidateUserExpressions = taskDefinition.getCandidateUserIdExpressions();
activeCandidateGroupExpressions = taskDefinition.getCandidateGroupIdExpressions();
}
task.setTaskDefinition(taskDefinition);
if (taskDefinition.getNameExpression() != null) {
if (activeNameExpression != null) {
String name = null;
try {
name = (String) taskDefinition.getNameExpression().getValue(execution);
name = (String) activeNameExpression.getValue(execution);
} catch (ActivitiException e) {
name = taskDefinition.getNameExpression().getExpressionText();
name = activeNameExpression.getExpressionText();
LOGGER.warn("property not found in task name expression " + e.getMessage());
}
task.setName(name);
}
if (taskDefinition.getDescriptionExpression() != null) {
if (activeDescriptionExpression != null) {
String description = null;
try {
description = (String) taskDefinition.getDescriptionExpression().getValue(execution);
description = (String) activeDescriptionExpression.getValue(execution);
} catch (ActivitiException e) {
description = taskDefinition.getDescriptionExpression().getExpressionText();
description = activeDescriptionExpression.getExpressionText();
LOGGER.warn("property not found in task description expression " + e.getMessage());
}
task.setDescription(description);
}
if (taskDefinition.getDueDateExpression() != null) {
Object dueDate = taskDefinition.getDueDateExpression().getValue(execution);
if (activeDueDateExpression != null) {
Object dueDate = activeDueDateExpression.getValue(execution);
if (dueDate != null) {
if (dueDate instanceof Date) {
task.setDueDate((Date) dueDate);
......@@ -96,13 +156,13 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior {
task.setDueDate(businessCalendar.resolveDuedate((String) dueDate));
} else {
throw new ActivitiIllegalArgumentException("Due date expression does not resolve to a Date or Date string: " +
taskDefinition.getDueDateExpression().getExpressionText());
activeDueDateExpression.getExpressionText());
}
}
}
if (taskDefinition.getPriorityExpression() != null) {
final Object priority = taskDefinition.getPriorityExpression().getValue(execution);
if (activePriorityExpression != null) {
final Object priority = activePriorityExpression.getValue(execution);
if (priority != null) {
if (priority instanceof String) {
try {
......@@ -114,36 +174,37 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior {
task.setPriority(((Number) priority).intValue());
} else {
throw new ActivitiIllegalArgumentException("Priority expression does not resolve to a number: " +
taskDefinition.getPriorityExpression().getExpressionText());
activePriorityExpression.getExpressionText());
}
}
}
if (taskDefinition.getCategoryExpression() != null) {
final Object category = taskDefinition.getCategoryExpression().getValue(execution);
if (activeCategoryExpression != null) {
final Object category = activeCategoryExpression.getValue(execution);
if (category != null) {
if (category instanceof String) {
task.setCategory((String) category);
} else {
throw new ActivitiIllegalArgumentException("Category expression does not resolve to a string: " +
taskDefinition.getCategoryExpression().getExpressionText());
activeCategoryExpression.getExpressionText());
}
}
}
if (taskDefinition.getFormKeyExpression() != null) {
final Object formKey = taskDefinition.getFormKeyExpression().getValue(execution);
if (activeFormKeyExpression != null) {
final Object formKey = activeFormKeyExpression.getValue(execution);
if (formKey != null) {
if (formKey instanceof String) {
task.setFormKey((String) formKey);
} else {
throw new ActivitiIllegalArgumentException("FormKey expression does not resolve to a string: " +
taskDefinition.getFormKeyExpression().getExpressionText());
activeFormKeyExpression.getExpressionText());
}
}
}
handleAssignments(task, activityExecution);
handleAssignments(activeAssigneeExpression, activeOwnerExpression, activeCandidateUserExpressions,
activeCandidateGroupExpressions, task, activityExecution);
// All properties set, now firing 'create' events
if (Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
......@@ -168,9 +229,11 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior {
}
@SuppressWarnings({ "unchecked", "rawtypes" })
protected void handleAssignments(TaskEntity task, ActivityExecution execution) {
if (taskDefinition.getAssigneeExpression() != null) {
Object assigneeExpressionValue = taskDefinition.getAssigneeExpression().getValue(execution);
protected void handleAssignments(Expression assigneeExpression, Expression ownerExpression, Set<Expression> candidateUserExpressions,
Set<Expression> candidateGroupExpressions, TaskEntity task, ActivityExecution execution) {
if (assigneeExpression != null) {
Object assigneeExpressionValue = assigneeExpression.getValue(execution);
String assigneeValue = null;
if (assigneeExpressionValue != null) {
assigneeValue = assigneeExpressionValue.toString();
......@@ -178,8 +241,8 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior {
task.setAssignee(assigneeValue, true, false);
}
if (taskDefinition.getOwnerExpression() != null) {
Object ownerExpressionValue = taskDefinition.getOwnerExpression().getValue(execution);
if (ownerExpression != null) {
Object ownerExpressionValue = ownerExpression.getValue(execution);
String ownerValue = null;
if (ownerExpressionValue != null) {
ownerValue = ownerExpressionValue.toString();
......@@ -187,8 +250,8 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior {
task.setOwner(ownerValue);
}
if (!taskDefinition.getCandidateGroupIdExpressions().isEmpty()) {
for (Expression groupIdExpr : taskDefinition.getCandidateGroupIdExpressions()) {
if (candidateGroupExpressions != null && !candidateGroupExpressions.isEmpty()) {
for (Expression groupIdExpr : candidateGroupExpressions) {
Object value = groupIdExpr.getValue(execution);
if (value instanceof String) {
List<String> candidates = extractCandidates((String) value);
......@@ -201,8 +264,8 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior {
}
}
if (!taskDefinition.getCandidateUserIdExpressions().isEmpty()) {
for (Expression userIdExpr : taskDefinition.getCandidateUserIdExpressions()) {
if (candidateUserExpressions != null && !candidateUserExpressions.isEmpty()) {
for (Expression userIdExpr : candidateUserExpressions) {
Object value = userIdExpr.getValue(execution);
if (value instanceof String) {
List<String> candiates = extractCandidates((String) value);
......@@ -270,6 +333,40 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior {
return Arrays.asList(str.split("[\\s]*,[\\s]*"));
}
protected Expression getActiveValue(Expression originalValue, String propertyName, ObjectNode taskElementProperties) {
Expression activeValue = originalValue;
if (taskElementProperties != null) {
JsonNode overrideValueNode = taskElementProperties.get(propertyName);
if (overrideValueNode != null) {
if (overrideValueNode.isNull()) {
activeValue = null;
} else {
activeValue = Context.getProcessEngineConfiguration().getExpressionManager().createExpression(overrideValueNode.asText());
}
}
}
return activeValue;
}
protected Set<Expression> getActiveValueSet(Set<Expression> originalValues, String propertyName, ObjectNode taskElementProperties) {
Set<Expression> activeValues = originalValues;
if (taskElementProperties != null) {
JsonNode overrideValuesNode = taskElementProperties.get(propertyName);
if (overrideValuesNode != null) {
if (overrideValuesNode.isNull() || overrideValuesNode.isArray() == false || overrideValuesNode.size() == 0) {
activeValues = null;
} else {
ExpressionManager expressionManager = Context.getProcessEngineConfiguration().getExpressionManager();
activeValues = new HashSet<Expression>();
for (JsonNode valueNode : overrideValuesNode) {
activeValues.add(expressionManager.createExpression(valueNode.asText()));
}
}
}
}
return activeValues;
}
// getters and setters //////////////////////////////////////////////////////
public TaskDefinition getTaskDefinition() {
......
......@@ -40,12 +40,16 @@ import org.activiti5.engine.impl.interceptor.CommandContext;
import org.activiti5.engine.impl.jobexecutor.TimerDeclarationImpl;
import org.activiti5.engine.impl.jobexecutor.TimerStartEventJobHandler;
import org.activiti5.engine.impl.persistence.deploy.Deployer;
import org.activiti5.engine.impl.persistence.deploy.DeploymentManager;
import org.activiti5.engine.impl.persistence.deploy.ProcessDefinitionInfoCacheObject;
import org.activiti5.engine.impl.persistence.entity.DeploymentEntity;
import org.activiti5.engine.impl.persistence.entity.EventSubscriptionEntity;
import org.activiti5.engine.impl.persistence.entity.IdentityLinkEntity;
import org.activiti5.engine.impl.persistence.entity.MessageEventSubscriptionEntity;
import org.activiti5.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti5.engine.impl.persistence.entity.ProcessDefinitionEntityManager;
import org.activiti5.engine.impl.persistence.entity.ProcessDefinitionInfoEntity;
import org.activiti5.engine.impl.persistence.entity.ProcessDefinitionInfoEntityManager;
import org.activiti5.engine.impl.persistence.entity.ResourceEntity;
import org.activiti5.engine.impl.persistence.entity.SignalEventSubscriptionEntity;
import org.activiti5.engine.impl.persistence.entity.TimerEntity;
......@@ -55,6 +59,9 @@ import org.activiti5.engine.task.IdentityLinkType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Tom Baeyens
* @author Joram Barrez
......@@ -234,16 +241,55 @@ public class BpmnDeployer implements Deployer {
}
// Add to cache
processEngineConfiguration
.getDeploymentManager()
.getProcessDefinitionCache()
.add(processDefinition.getId(), processDefinition);
DeploymentManager deploymentManager = processEngineConfiguration.getDeploymentManager();
deploymentManager.getProcessDefinitionCache().add(processDefinition.getId(), processDefinition);
addDefinitionInfoToCache(processDefinition, processEngineConfiguration, commandContext);
// Add to deployment for further usage
deployment.addDeployedArtifact(processDefinition);
}
}
protected void addDefinitionInfoToCache(ProcessDefinitionEntity processDefinition,
ProcessEngineConfigurationImpl processEngineConfiguration, CommandContext commandContext) {
if (processEngineConfiguration.isEnableProcessDefinitionInfoCache() == false) {
return;
}
DeploymentManager deploymentManager = processEngineConfiguration.getDeploymentManager();
ProcessDefinitionInfoEntityManager definitionInfoEntityManager = commandContext.getProcessDefinitionInfoEntityManager();
ObjectMapper objectMapper = commandContext.getProcessEngineConfiguration().getObjectMapper();
ProcessDefinitionInfoEntity definitionInfoEntity = definitionInfoEntityManager.findProcessDefinitionInfoByProcessDefinitionId(processDefinition.getId());
ObjectNode infoNode = null;
if (definitionInfoEntity != null && definitionInfoEntity.getInfoJsonId() != null) {
byte[] infoBytes = definitionInfoEntityManager.findInfoJsonById(definitionInfoEntity.getInfoJsonId());
if (infoBytes != null) {
try {
infoNode = (ObjectNode) objectMapper.readTree(infoBytes);
} catch (Exception e) {
throw new ActivitiException("Error deserializing json info for process definition " + processDefinition.getId());
}
}
}
ProcessDefinitionInfoCacheObject definitionCacheObject = new ProcessDefinitionInfoCacheObject();
if (definitionInfoEntity == null) {
definitionCacheObject.setRevision(0);
} else {
definitionCacheObject.setId(definitionInfoEntity.getId());
definitionCacheObject.setRevision(definitionInfoEntity.getRevision());
}
if (infoNode == null) {
infoNode = objectMapper.createObjectNode();
}
definitionCacheObject.setInfoNode(infoNode);
deploymentManager.getProcessDefinitionInfoCache().add(processDefinition.getId(), definitionCacheObject);
}
private void scheduleTimers(List<TimerEntity> timers) {
for (TimerEntity timer : timers) {
Context
......
......@@ -19,6 +19,7 @@ import java.lang.reflect.Method;
import java.util.List;
import org.activiti.bpmn.model.MapExceptionEntry;
import org.activiti.engine.DynamicBpmnConstants;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.ExecutionListener;
......@@ -39,6 +40,9 @@ import org.activiti5.engine.impl.pvm.delegate.ActivityExecution;
import org.activiti5.engine.impl.pvm.delegate.SignallableActivityBehavior;
import org.activiti5.engine.impl.pvm.delegate.SubProcessActivityBehavior;
import org.activiti5.engine.impl.util.ReflectUtil;
import org.apache.commons.lang3.StringUtils;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
......@@ -59,6 +63,7 @@ public class ClassDelegate extends AbstractBpmnActivityBehavior implements TaskL
protected ActivityBehavior activityBehaviorInstance;
protected Expression skipExpression;
protected List<MapExceptionEntry> mapExceptions;
protected String serviceTaskId;
public ClassDelegate(String className, List<FieldDeclaration> fieldDeclarations, Expression skipExpression) {
this.className = className;
......@@ -67,10 +72,10 @@ public class ClassDelegate extends AbstractBpmnActivityBehavior implements TaskL
}
public ClassDelegate(String className, List<FieldDeclaration> fieldDeclarations, Expression skipExpression, List<MapExceptionEntry> mapExceptions) {
public ClassDelegate(String id, String className, List<FieldDeclaration> fieldDeclarations, Expression skipExpression, List<MapExceptionEntry> mapExceptions) {
this(className, fieldDeclarations, skipExpression);
this.serviceTaskId = id;
this.mapExceptions = mapExceptions;
}
public ClassDelegate(String className, List<FieldDeclaration> fieldDeclarations) {
......@@ -136,6 +141,17 @@ public class ClassDelegate extends AbstractBpmnActivityBehavior implements TaskL
if (!isSkipExpressionEnabled ||
(isSkipExpressionEnabled && !SkipExpressionUtil.shouldSkipFlowElement(activityExecution, skipExpression))) {
if (Context.getProcessEngineConfiguration().isEnableProcessDefinitionInfoCache()) {
ObjectNode taskElementProperties = Context.getBpmnOverrideElementProperties(serviceTaskId, execution.getProcessDefinitionId());
if (taskElementProperties != null && taskElementProperties.has(DynamicBpmnConstants.SERVICE_TASK_CLASS_NAME)) {
String overrideClassName = taskElementProperties.get(DynamicBpmnConstants.SERVICE_TASK_CLASS_NAME).asText();
if (StringUtils.isNotEmpty(overrideClassName) && overrideClassName.equals(className) == false) {
className = overrideClassName;
activityBehaviorInstance = null;
}
}
}
if (activityBehaviorInstance == null) {
activityBehaviorInstance = getActivityBehaviorInstance(activityExecution);
}
......
......@@ -124,7 +124,7 @@ public class DefaultActivityBehaviorFactory extends AbstractBehaviorFactory impl
}
public UserTaskActivityBehavior createUserTaskActivityBehavior(UserTask userTask, TaskDefinition taskDefinition) {
return new UserTaskActivityBehavior(taskDefinition);
return new UserTaskActivityBehavior(userTask.getId(), taskDefinition);
}
// Service task
......@@ -136,7 +136,8 @@ public class DefaultActivityBehaviorFactory extends AbstractBehaviorFactory impl
} else {
skipExpression = null;
}
return new ClassDelegate(serviceTask.getImplementation(), createFieldDeclarations(serviceTask.getFieldExtensions()), skipExpression, serviceTask.getMapExceptions());
return new ClassDelegate(serviceTask.getId(), serviceTask.getImplementation(), createFieldDeclarations(serviceTask.getFieldExtensions()),
skipExpression, serviceTask.getMapExceptions());
}
public ServiceTaskDelegateExpressionActivityBehavior createServiceTaskDelegateExpressionActivityBehavior(ServiceTask serviceTask) {
......@@ -147,7 +148,7 @@ public class DefaultActivityBehaviorFactory extends AbstractBehaviorFactory impl
} else {
skipExpression = null;
}
return new ServiceTaskDelegateExpressionActivityBehavior(delegateExpression, skipExpression, createFieldDeclarations(serviceTask.getFieldExtensions()));
return new ServiceTaskDelegateExpressionActivityBehavior(serviceTask.getId(), delegateExpression, skipExpression, createFieldDeclarations(serviceTask.getFieldExtensions()));
}
public ServiceTaskExpressionActivityBehavior createServiceTaskExpressionActivityBehavior(ServiceTask serviceTask) {
......@@ -158,7 +159,7 @@ public class DefaultActivityBehaviorFactory extends AbstractBehaviorFactory impl
} else {
skipExpression = null;
}
return new ServiceTaskExpressionActivityBehavior(expression, skipExpression, serviceTask.getResultVariableName());
return new ServiceTaskExpressionActivityBehavior(serviceTask.getId(), expression, skipExpression, serviceTask.getResultVariableName());
}
public WebServiceActivityBehavior createWebServiceActivityBehavior(ServiceTask serviceTask) {
......
......@@ -43,6 +43,7 @@ import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.activiti.validation.ProcessValidator;
import org.activiti.validation.ProcessValidatorFactory;
import org.activiti5.engine.ActivitiException;
import org.activiti5.engine.DynamicBpmnService;
import org.activiti5.engine.FormService;
import org.activiti5.engine.HistoryService;
import org.activiti5.engine.IdentityService;
......@@ -58,6 +59,7 @@ import org.activiti5.engine.delegate.event.ActivitiEventListener;
import org.activiti5.engine.delegate.event.ActivitiEventType;
import org.activiti5.engine.delegate.event.impl.ActivitiEventDispatcherImpl;
import org.activiti5.engine.form.AbstractFormType;
import org.activiti5.engine.impl.DynamicBpmnServiceImpl;
import org.activiti5.engine.impl.FormServiceImpl;
import org.activiti5.engine.impl.HistoryServiceImpl;
import org.activiti5.engine.impl.IdentityServiceImpl;
......@@ -165,6 +167,7 @@ import org.activiti5.engine.impl.persistence.deploy.DefaultDeploymentCache;
import org.activiti5.engine.impl.persistence.deploy.Deployer;
import org.activiti5.engine.impl.persistence.deploy.DeploymentCache;
import org.activiti5.engine.impl.persistence.deploy.DeploymentManager;
import org.activiti5.engine.impl.persistence.deploy.ProcessDefinitionInfoCache;
import org.activiti5.engine.impl.persistence.entity.AttachmentEntityManager;
import org.activiti5.engine.impl.persistence.entity.ByteArrayEntityManager;
import org.activiti5.engine.impl.persistence.entity.CommentEntityManager;
......@@ -184,6 +187,7 @@ import org.activiti5.engine.impl.persistence.entity.JobEntityManager;
import org.activiti5.engine.impl.persistence.entity.ModelEntityManager;
import org.activiti5.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti5.engine.impl.persistence.entity.ProcessDefinitionEntityManager;
import org.activiti5.engine.impl.persistence.entity.ProcessDefinitionInfoEntityManager;
import org.activiti5.engine.impl.persistence.entity.PropertyEntityManager;
import org.activiti5.engine.impl.persistence.entity.ResourceEntityManager;
import org.activiti5.engine.impl.persistence.entity.TableDataManager;
......@@ -234,6 +238,8 @@ import org.apache.ibatis.type.JdbcType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* @author Tom Baeyens
......@@ -259,6 +265,7 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
protected TaskService taskService = new TaskServiceImpl(this);
protected FormService formService = new FormServiceImpl();
protected ManagementService managementService = new ManagementServiceImpl();
protected DynamicBpmnService dynamicBpmnService = new DynamicBpmnServiceImpl(this);
// COMMAND EXECUTORS ////////////////////////////////////////////////////////
......@@ -301,6 +308,8 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
protected DeploymentCache<ProcessDefinitionEntity> processDefinitionCache;
protected int bpmnModelCacheLimit = -1; // By default, no limit
protected DeploymentCache<BpmnModel> bpmnModelCache;
protected int processDefinitionInfoCacheLimit = -1; // By default, no limit
protected ProcessDefinitionInfoCache processDefinitionInfoCache;
protected int knowledgeBaseCacheLimit = -1;
protected DeploymentCache<Object> knowledgeBaseCache;
......@@ -407,6 +416,8 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
*/
protected int maxNrOfStatementsInBulkInsert = 100;
protected ObjectMapper objectMapper = new ObjectMapper();
protected boolean enableEventDispatcher = true;
protected ActivitiEventDispatcher eventDispatcher;
protected List<ActivitiEventListener> eventListeners;
......@@ -421,6 +432,8 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
*/
protected int maxLengthStringVariableType = 4000;
protected boolean enableProcessDefinitionInfoCache = false;
// Activiti 5 backwards compatibility handler
protected Activiti5CompatibilityHandler activiti5CompatibilityHandler;
......@@ -561,6 +574,7 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
initService(taskService);
initService(formService);
initService(managementService);
initService(dynamicBpmnService);
}
protected void initService(Object service) {
......@@ -838,6 +852,7 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
addSessionFactory(new GenericManagerFactory(IdentityLinkEntityManager.class));
addSessionFactory(new GenericManagerFactory(JobEntityManager.class));
addSessionFactory(new GenericManagerFactory(ProcessDefinitionEntityManager.class));
addSessionFactory(new GenericManagerFactory(ProcessDefinitionInfoEntityManager.class));
addSessionFactory(new GenericManagerFactory(PropertyEntityManager.class));
addSessionFactory(new GenericManagerFactory(ResourceEntityManager.class));
addSessionFactory(new GenericManagerFactory(ByteArrayEntityManager.class));
......@@ -973,6 +988,14 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
}
}
if (processDefinitionInfoCache == null) {
if (processDefinitionInfoCacheLimit <= 0) {
processDefinitionInfoCache = new ProcessDefinitionInfoCache(commandExecutor);
} else {
processDefinitionInfoCache = new ProcessDefinitionInfoCache(commandExecutor, processDefinitionInfoCacheLimit);
}
}
// Knowledge base cache (used for Drools business task)
if (knowledgeBaseCache == null) {
if (knowledgeBaseCacheLimit <= 0) {
......@@ -984,6 +1007,7 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
deploymentManager.setProcessDefinitionCache(processDefinitionCache);
deploymentManager.setBpmnModelCache(bpmnModelCache);
deploymentManager.setProcessDefinitionInfoCache(processDefinitionInfoCache);
deploymentManager.setKnowledgeBaseCache(knowledgeBaseCache);
}
}
......@@ -1573,6 +1597,10 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
return managementService;
}
public DynamicBpmnService getDynamicBpmnService() {
return dynamicBpmnService;
}
public ProcessEngineConfigurationImpl setManagementService(ManagementService managementService) {
this.managementService = managementService;
return this;
......@@ -2128,6 +2156,10 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
this.maxNrOfStatementsInBulkInsert = maxNrOfStatementsInBulkInsert;
}
public ObjectMapper getObjectMapper() {
return objectMapper;
}
public Activiti5CompatibilityHandler getActiviti5CompatibilityHandler() {
return activiti5CompatibilityHandler;
}
......
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti5.engine.impl.cmd;
import java.io.Serializable;
import org.activiti5.engine.ActivitiIllegalArgumentException;
import org.activiti5.engine.impl.interceptor.Command;
import org.activiti5.engine.impl.interceptor.CommandContext;
import org.activiti5.engine.impl.persistence.deploy.DeploymentManager;
import org.activiti5.engine.impl.persistence.deploy.ProcessDefinitionInfoCacheObject;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Tijs Rademakers
*/
public class GetProcessDefinitionInfoCmd implements Command<ObjectNode>, Serializable {
private static final long serialVersionUID = 1L;
protected String processDefinitionId;
public GetProcessDefinitionInfoCmd(String processDefinitionId) {
this.processDefinitionId = processDefinitionId;
}
public ObjectNode execute(CommandContext commandContext) {
if (processDefinitionId == null) {
throw new ActivitiIllegalArgumentException("process definition id is null");
}
ObjectNode resultNode = null;
DeploymentManager deploymentManager = commandContext.getProcessEngineConfiguration().getDeploymentManager();
// make sure the process definition is in the cache
deploymentManager.findDeployedProcessDefinitionById(processDefinitionId);
ProcessDefinitionInfoCacheObject definitionInfoCacheObject = deploymentManager.getProcessDefinitionInfoCache().get(processDefinitionId);
if (definitionInfoCacheObject != null) {
resultNode = definitionInfoCacheObject.getInfoNode();
}
return resultNode;
}
}
\ No newline at end of file
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti5.engine.impl.cmd;
import java.io.Serializable;
import org.activiti5.engine.ActivitiException;
import org.activiti5.engine.ActivitiIllegalArgumentException;
import org.activiti5.engine.impl.interceptor.Command;
import org.activiti5.engine.impl.interceptor.CommandContext;
import org.activiti5.engine.impl.persistence.entity.ProcessDefinitionInfoEntity;
import org.activiti5.engine.impl.persistence.entity.ProcessDefinitionInfoEntityManager;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Tijs Rademakers
*/
public class SaveProcessDefinitionInfoCmd implements Command<Void>, Serializable {
private static final long serialVersionUID = 1L;
protected String processDefinitionId;
protected ObjectNode infoNode;
public SaveProcessDefinitionInfoCmd(String processDefinitionId, ObjectNode infoNode) {
this.processDefinitionId = processDefinitionId;
this.infoNode = infoNode;
}
public Void execute(CommandContext commandContext) {
if (processDefinitionId == null) {
throw new ActivitiIllegalArgumentException("process definition id is null");
}
if (infoNode == null) {
throw new ActivitiIllegalArgumentException("process definition info node is null");
}
ProcessDefinitionInfoEntityManager definitionInfoEntityManager = commandContext.getProcessDefinitionInfoEntityManager();
ProcessDefinitionInfoEntity definitionInfoEntity = definitionInfoEntityManager.findProcessDefinitionInfoByProcessDefinitionId(processDefinitionId);
if (definitionInfoEntity == null) {
definitionInfoEntity = new ProcessDefinitionInfoEntity();
definitionInfoEntity.setProcessDefinitionId(processDefinitionId);
commandContext.getProcessDefinitionInfoEntityManager().insertProcessDefinitionInfo(definitionInfoEntity);
} else {
commandContext.getProcessDefinitionInfoEntityManager().updateProcessDefinitionInfo(definitionInfoEntity);
}
if (infoNode != null) {
try {
ObjectWriter writer = commandContext.getProcessEngineConfiguration().getObjectMapper().writer();
commandContext.getProcessDefinitionInfoEntityManager().updateInfoJson(definitionInfoEntity.getId(), writer.writeValueAsBytes(infoNode));
} catch (Exception e) {
throw new ActivitiException("Unable to serialize info node " + infoNode);
}
}
return null;
}
}
\ No newline at end of file
......@@ -13,13 +13,18 @@
package org.activiti5.engine.impl.context;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import org.activiti5.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti5.engine.impl.interceptor.CommandContext;
import org.activiti5.engine.impl.jobexecutor.JobExecutorContext;
import org.activiti5.engine.impl.persistence.deploy.ProcessDefinitionInfoCacheObject;
import org.activiti5.engine.impl.pvm.runtime.InterpretableExecution;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Tom Baeyens
......@@ -31,6 +36,7 @@ public class Context {
protected static ThreadLocal<Stack<ProcessEngineConfigurationImpl>> processEngineConfigurationStackThreadLocal = new ThreadLocal<Stack<ProcessEngineConfigurationImpl>>();
protected static ThreadLocal<Stack<ExecutionContext>> executionContextStackThreadLocal = new ThreadLocal<Stack<ExecutionContext>>();
protected static ThreadLocal<JobExecutorContext> jobExecutorContextThreadLocal = new ThreadLocal<JobExecutorContext>();
protected static ThreadLocal<Map<String, ObjectNode>> bpmnOverrideContextThreadLocal = new ThreadLocal<Map<String, ObjectNode>>();
public static CommandContext getCommandContext() {
Stack<CommandContext> stack = getStack(commandContextThreadLocal);
......@@ -101,4 +107,57 @@ public class Context {
public static void removeJobExecutorContext() {
jobExecutorContextThreadLocal.remove();
}
public static ObjectNode getBpmnOverrideElementProperties(String id, String processDefinitionId) {
ObjectNode definitionInfoNode = getProcessDefinitionInfoNode(processDefinitionId);
ObjectNode elementProperties = null;
if (definitionInfoNode != null) {
elementProperties = getProcessEngineConfiguration().getDynamicBpmnService().getBpmnElementProperties(id, definitionInfoNode);
}
return elementProperties;
}
public static ObjectNode getLocalizationElementProperties(String language, String id, String processDefinitionId) {
ObjectNode definitionInfoNode = getProcessDefinitionInfoNode(processDefinitionId);
ObjectNode localizationProperties = null;
if (definitionInfoNode != null) {
localizationProperties = getProcessEngineConfiguration().getDynamicBpmnService().getLocalizationElementProperties(
language, id, definitionInfoNode);
}
return localizationProperties;
}
public static void removeBpmnOverrideContext() {
bpmnOverrideContextThreadLocal.remove();
}
protected static ObjectNode getProcessDefinitionInfoNode(String processDefinitionId) {
Map<String, ObjectNode> bpmnOverrideMap = getBpmnOverrideContext();
if (bpmnOverrideMap.containsKey(processDefinitionId) == false) {
ProcessDefinitionInfoCacheObject cacheObject = getProcessEngineConfiguration().getDeploymentManager()
.getProcessDefinitionInfoCache()
.get(processDefinitionId);
addBpmnOverrideElement(processDefinitionId, cacheObject.getInfoNode());
}
return getBpmnOverrideContext().get(processDefinitionId);
}
protected static Map<String, ObjectNode> getBpmnOverrideContext() {
Map<String, ObjectNode> bpmnOverrideMap = bpmnOverrideContextThreadLocal.get();
if (bpmnOverrideMap == null) {
bpmnOverrideMap = new HashMap<String, ObjectNode>();
}
return bpmnOverrideMap;
}
protected static void addBpmnOverrideElement(String id, ObjectNode infoNode) {
Map<String, ObjectNode> bpmnOverrideMap = bpmnOverrideContextThreadLocal.get();
if (bpmnOverrideMap == null) {
bpmnOverrideMap = new HashMap<String, ObjectNode>();
bpmnOverrideContextThreadLocal.set(bpmnOverrideMap);
}
bpmnOverrideMap.put(id, infoNode);
}
}
......@@ -17,11 +17,11 @@ import java.util.Date;
import java.util.List;
import java.util.Map;
import org.activiti.engine.delegate.Expression;
import org.activiti5.engine.history.HistoricActivityInstance;
import org.activiti5.engine.impl.HistoricActivityInstanceQueryImpl;
import org.activiti5.engine.impl.cfg.IdGenerator;
import org.activiti5.engine.impl.context.Context;
import org.activiti5.engine.impl.form.TaskFormHandler;
import org.activiti5.engine.impl.identity.Authentication;
import org.activiti5.engine.impl.persistence.AbstractManager;
import org.activiti5.engine.impl.persistence.entity.CommentEntity;
......@@ -559,10 +559,9 @@ public void recordTaskDefinitionKeyChange(TaskEntity task, String taskDefinition
historicTaskInstance.setTaskDefinitionKey(taskDefinitionKey);
if (taskDefinitionKey != null) {
TaskFormHandler taskFormHandler = task.getTaskDefinition().getTaskFormHandler();
if (taskFormHandler != null) {
if (taskFormHandler.getFormKey() != null) {
Object formValue = taskFormHandler.getFormKey().getValue(task.getExecution());
Expression taskFormExpression = task.getTaskDefinition().getFormKeyExpression();
if (taskFormExpression != null) {
Object formValue = taskFormExpression.getValue(task.getExecution());
if (formValue != null) {
historicTaskInstance.setFormKey(formValue.toString());
}
......@@ -571,7 +570,6 @@ public void recordTaskDefinitionKeyChange(TaskEntity task, String taskDefinition
}
}
}
}
// Variables related history
......
......@@ -49,6 +49,7 @@ import org.activiti5.engine.impl.persistence.entity.JobEntityManager;
import org.activiti5.engine.impl.persistence.entity.MembershipIdentityManager;
import org.activiti5.engine.impl.persistence.entity.ModelEntityManager;
import org.activiti5.engine.impl.persistence.entity.ProcessDefinitionEntityManager;
import org.activiti5.engine.impl.persistence.entity.ProcessDefinitionInfoEntityManager;
import org.activiti5.engine.impl.persistence.entity.PropertyEntityManager;
import org.activiti5.engine.impl.persistence.entity.ResourceEntityManager;
import org.activiti5.engine.impl.persistence.entity.TableDataManager;
......@@ -283,6 +284,10 @@ public class CommandContext {
return getSession(ProcessDefinitionEntityManager.class);
}
public ProcessDefinitionInfoEntityManager getProcessDefinitionInfoEntityManager() {
return getSession(ProcessDefinitionInfoEntityManager.class);
}
public ModelEntityManager getModelEntityManager() {
return getSession(ModelEntityManager.class);
}
......
......@@ -70,6 +70,7 @@ public class CommandContextInterceptor extends AbstractCommandInterceptor {
// Pop from stack
Context.removeCommandContext();
Context.removeProcessEngineConfiguration();
Context.removeBpmnOverrideContext();
// don't remove the fallback because it's needed in Activiti 6 code like the Camel module
//org.activiti.engine.impl.context.Context.removeFallbackActiviti5CompatibilityHandler();
}
......
......@@ -36,6 +36,7 @@ import org.activiti5.engine.impl.persistence.entity.IdentityLinkEntityManager;
import org.activiti5.engine.impl.persistence.entity.MembershipIdentityManager;
import org.activiti5.engine.impl.persistence.entity.ModelEntityManager;
import org.activiti5.engine.impl.persistence.entity.ProcessDefinitionEntityManager;
import org.activiti5.engine.impl.persistence.entity.ProcessDefinitionInfoEntityManager;
import org.activiti5.engine.impl.persistence.entity.ResourceEntityManager;
import org.activiti5.engine.impl.persistence.entity.TaskEntityManager;
import org.activiti5.engine.impl.persistence.entity.UserIdentityManager;
......@@ -80,6 +81,10 @@ public abstract class AbstractManager implements Session {
return getSession(ProcessDefinitionEntityManager.class);
}
protected ProcessDefinitionInfoEntityManager getProcessDefinitionInfoManager() {
return getSession(ProcessDefinitionInfoEntityManager.class);
}
protected ModelEntityManager getModelManager() {
return getSession(ModelEntityManager.class);
}
......
......@@ -45,6 +45,7 @@ public class DeploymentManager {
protected DeploymentCache<ProcessDefinitionEntity> processDefinitionCache;
protected DeploymentCache<BpmnModel> bpmnModelCache;
protected ProcessDefinitionInfoCache processDefinitionInfoCache;
protected DeploymentCache<Object> knowledgeBaseCache; // Needs to be object to avoid an import to Drools in this core class
protected List<Deployer> deployers;
......@@ -236,6 +237,14 @@ public class DeploymentManager {
this.bpmnModelCache = bpmnModelCache;
}
public ProcessDefinitionInfoCache getProcessDefinitionInfoCache() {
return processDefinitionInfoCache;
}
public void setProcessDefinitionInfoCache(ProcessDefinitionInfoCache processDefinitionInfoCache) {
this.processDefinitionInfoCache = processDefinitionInfoCache;
}
public DeploymentCache<Object> getKnowledgeBaseCache() {
return knowledgeBaseCache;
}
......
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti5.engine.impl.persistence.deploy;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.activiti5.engine.ActivitiException;
import org.activiti5.engine.impl.interceptor.Command;
import org.activiti5.engine.impl.interceptor.CommandContext;
import org.activiti5.engine.impl.interceptor.CommandExecutor;
import org.activiti5.engine.impl.persistence.entity.ProcessDefinitionInfoEntity;
import org.activiti5.engine.impl.persistence.entity.ProcessDefinitionInfoEntityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* Default cache: keep everything in memory, unless a limit is set.
*
* @author Tijs Rademakers
*/
public class ProcessDefinitionInfoCache {
private static final Logger logger = LoggerFactory.getLogger(ProcessDefinitionInfoCache.class);
protected Map<String, ProcessDefinitionInfoCacheObject> cache;
protected CommandExecutor commandExecutor;
/** Cache with no limit */
public ProcessDefinitionInfoCache(CommandExecutor commandExecutor) {
this.commandExecutor = commandExecutor;
this.cache = new HashMap<String, ProcessDefinitionInfoCacheObject>();
}
/** Cache which has a hard limit: no more elements will be cached than the limit. */
public ProcessDefinitionInfoCache(CommandExecutor commandExecutor, final int limit) {
this.commandExecutor = commandExecutor;
this.cache = Collections.synchronizedMap(new LinkedHashMap<String, ProcessDefinitionInfoCacheObject>(limit + 1, 0.75f, true) {
// +1 is needed, because the entry is inserted first, before it is removed
// 0.75 is the default (see javadocs)
// true will keep the 'access-order', which is needed to have a real LRU cache
private static final long serialVersionUID = 1L;
protected boolean removeEldestEntry(Map.Entry<String, ProcessDefinitionInfoCacheObject> eldest) {
boolean removeEldest = size() > limit;
if (removeEldest) {
logger.trace("Cache limit is reached, {} will be evicted", eldest.getKey());
}
return removeEldest;
}
});
}
public ProcessDefinitionInfoCacheObject get(final String processDefinitionId) {
ProcessDefinitionInfoCacheObject infoCacheObject = null;
if (cache.containsKey(processDefinitionId)) {
infoCacheObject = commandExecutor.execute(new Command<ProcessDefinitionInfoCacheObject>() {
@Override
public ProcessDefinitionInfoCacheObject execute(CommandContext commandContext) {
ProcessDefinitionInfoEntityManager infoEntityManager = commandContext.getProcessDefinitionInfoEntityManager();
ObjectMapper objectMapper = commandContext.getProcessEngineConfiguration().getObjectMapper();
ProcessDefinitionInfoCacheObject cacheObject = cache.get(processDefinitionId);
ProcessDefinitionInfoEntity infoEntity = infoEntityManager.findProcessDefinitionInfoByProcessDefinitionId(processDefinitionId);
if (infoEntity != null && infoEntity.getRevision() != cacheObject.getRevision()) {
cacheObject.setRevision(infoEntity.getRevision());
if (infoEntity.getInfoJsonId() != null) {
byte[] infoBytes = infoEntityManager.findInfoJsonById(infoEntity.getInfoJsonId());
try {
ObjectNode infoNode = (ObjectNode) objectMapper.readTree(infoBytes);
cacheObject.setInfoNode(infoNode);
} catch (Exception e) {
throw new ActivitiException("Error reading json info node for process definition " + processDefinitionId, e);
}
}
} else if (infoEntity == null) {
cacheObject.setRevision(0);
cacheObject.setInfoNode(objectMapper.createObjectNode());
}
return cacheObject;
}
});
}
return infoCacheObject;
}
public void add(String id, ProcessDefinitionInfoCacheObject obj) {
cache.put(id, obj);
}
public void remove(String id) {
cache.remove(id);
}
public void clear() {
cache.clear();
}
// For testing purposes only
public int size() {
return cache.size();
}
}
\ No newline at end of file
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti5.engine.impl.persistence.deploy;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Tijs Rademakers
*/
public class ProcessDefinitionInfoCacheObject {
protected String id;
protected int revision;
protected ObjectNode infoNode;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getRevision() {
return revision;
}
public void setRevision(int revision) {
this.revision = revision;
}
public ObjectNode getInfoNode() {
return infoNode;
}
public void setInfoNode(ObjectNode infoNode) {
this.infoNode = infoNode;
}
}
\ No newline at end of file
......@@ -74,7 +74,6 @@ public class DeploymentEntityManager extends AbstractManager {
getProcessInstanceManager()
.deleteProcessInstancesByProcessDefinition(processDefinitionId, "deleted deployment", cascade);
}
}
......@@ -85,6 +84,8 @@ public class DeploymentEntityManager extends AbstractManager {
// event subscriptions
getEventSubscriptionManager().deleteEventSubscriptionsForProcessDefinition(processDefinitionId);
getProcessDefinitionInfoManager().deleteProcessDefinitionInfo(processDefinitionId);
}
// delete process definitions from db
......
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti5.engine.impl.persistence.entity;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.activiti5.engine.impl.db.HasRevision;
import org.activiti5.engine.impl.db.PersistentObject;
/**
* @author Tijs Rademakers
*/
public class ProcessDefinitionInfoEntity implements HasRevision, PersistentObject, Serializable {
private static final long serialVersionUID = 1L;
protected String id;
protected String processDefinitionId;
protected int revision = 1;
protected String infoJsonId;
public Object getPersistentState() {
Map<String, Object> persistentState = new HashMap<String, Object>();
persistentState.put("processDefinitionId", this.processDefinitionId);
persistentState.put("infoJsonId", this.infoJsonId);
return persistentState;
}
// getters and setters //////////////////////////////////////////////////////
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getProcessDefinitionId() {
return processDefinitionId;
}
public void setProcessDefinitionId(String processDefinitionId) {
this.processDefinitionId = processDefinitionId;
}
public int getRevision() {
return revision;
}
public int getRevisionNext() {
return revision + 1;
}
public void setRevision(int revision) {
this.revision = revision;
}
public String getInfoJsonId() {
return infoJsonId;
}
public void setInfoJsonId(String infoJsonId) {
this.infoJsonId = infoJsonId;
}
}
\ No newline at end of file
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti5.engine.impl.persistence.entity;
import org.activiti5.engine.delegate.event.ActivitiEventType;
import org.activiti5.engine.delegate.event.impl.ActivitiEventBuilder;
import org.activiti5.engine.impl.context.Context;
import org.activiti5.engine.impl.db.DbSqlSession;
import org.activiti5.engine.impl.db.PersistentObject;
import org.activiti5.engine.impl.interceptor.CommandContext;
import org.activiti5.engine.impl.persistence.AbstractManager;
/**
* @author Tijs Rademakers
*/
public class ProcessDefinitionInfoEntityManager extends AbstractManager {
public void insertProcessDefinitionInfo(ProcessDefinitionInfoEntity processDefinitionInfo) {
getDbSqlSession().insert((PersistentObject) processDefinitionInfo);
if (Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createEntityEvent(ActivitiEventType.ENTITY_CREATED, processDefinitionInfo));
Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createEntityEvent(ActivitiEventType.ENTITY_INITIALIZED, processDefinitionInfo));
}
}
public void updateProcessDefinitionInfo(ProcessDefinitionInfoEntity updatedProcessDefinitionInfo) {
CommandContext commandContext = Context.getCommandContext();
DbSqlSession dbSqlSession = commandContext.getDbSqlSession();
dbSqlSession.update(updatedProcessDefinitionInfo);
if (Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createEntityEvent(ActivitiEventType.ENTITY_UPDATED, updatedProcessDefinitionInfo));
}
}
public void deleteProcessDefinitionInfo(String processDefinitionId) {
ProcessDefinitionInfoEntity processDefinitionInfo = findProcessDefinitionInfoByProcessDefinitionId(processDefinitionId);
if (processDefinitionInfo != null) {
getDbSqlSession().delete(processDefinitionInfo);
deleteInfoJson(processDefinitionInfo);
if (Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createEntityEvent(ActivitiEventType.ENTITY_DELETED, processDefinitionInfo));
}
}
}
public void updateInfoJson(String id, byte[] json) {
ProcessDefinitionInfoEntity processDefinitionInfo = getDbSqlSession().selectById(ProcessDefinitionInfoEntity.class, id);
if (processDefinitionInfo != null) {
ByteArrayRef ref = new ByteArrayRef(processDefinitionInfo.getInfoJsonId());
ref.setValue("json", json);
if (processDefinitionInfo.getInfoJsonId() == null) {
processDefinitionInfo.setInfoJsonId(ref.getId());
updateProcessDefinitionInfo(processDefinitionInfo);
}
}
}
public void deleteInfoJson(ProcessDefinitionInfoEntity processDefinitionInfo) {
if (processDefinitionInfo.getInfoJsonId() != null) {
ByteArrayRef ref = new ByteArrayRef(processDefinitionInfo.getInfoJsonId());
ref.delete();
}
}
public ProcessDefinitionInfoEntity findProcessDefinitionInfoById(String id) {
return (ProcessDefinitionInfoEntity) getDbSqlSession().selectOne("selectProcessDefinitionInfo", id);
}
public ProcessDefinitionInfoEntity findProcessDefinitionInfoByProcessDefinitionId(String processDefinitionId) {
return (ProcessDefinitionInfoEntity) getDbSqlSession().selectOne("selectProcessDefinitionInfoByProcessDefinitionId", processDefinitionId);
}
public byte[] findInfoJsonById(String infoJsonId) {
ByteArrayRef ref = new ByteArrayRef(infoJsonId);
return ref.getBytes();
}
}
\ No newline at end of file
......@@ -102,6 +102,10 @@ public class TaskDefinition implements Serializable {
candidateUserIdExpressions.add(userId);
}
public void setCandidateUserIdExpressions(Set<Expression> candidateUserIdExpressions) {
this.candidateUserIdExpressions = candidateUserIdExpressions;
}
public Set<Expression> getCandidateGroupIdExpressions() {
return candidateGroupIdExpressions;
}
......@@ -110,6 +114,10 @@ public class TaskDefinition implements Serializable {
candidateGroupIdExpressions.add(groupId);
}
public void setCandidateGroupIdExpressions(Set<Expression> candidateGroupIdExpressions) {
this.candidateGroupIdExpressions = candidateGroupIdExpressions;
}
public Map<String, Set<Expression>> getCustomUserIdentityLinkExpressions() {
return customUserIdentityLinkExpressions;
}
......
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.activiti5.engine.impl.persistence.entity.ProcessDefinitionInfoEntity">
<!-- ProcessDefinitionInfo INSERT -->
<insert id="insertProcessDefinitionInfo" parameterType="org.activiti5.engine.impl.persistence.entity.ProcessDefinitionInfoEntity">
insert into ${prefix}ACT_PROCDEF_INFO(ID_, PROC_DEF_ID_, REV_, INFO_JSON_ID_)
values(#{id, jdbcType=VARCHAR},
#{processDefinitionId, jdbcType=VARCHAR},
1,
#{infoJsonId, jdbcType=VARCHAR})
</insert>
<insert id="bulkInsertProcessDefinitionInfo" parameterType="java.util.List">
INSERT INTO ${prefix}ACT_PROCDEF_INFO(ID_, PROC_DEF_ID_, REV_, INFO_JSON_ID_)
VALUES
<foreach collection="list" item="processDefinitionInfo" index="index" separator=",">
(#{processDefinitionInfo.id, jdbcType=VARCHAR},
#{processDefinitionInfo.processDefinitionId, jdbcType=VARCHAR},
1,
#{processDefinitionInfo.infoJsonId, jdbcType=VARCHAR})
</foreach>
</insert>
<insert id="bulkInsertProcessDefinitionInfo_oracle" parameterType="java.util.List">
INSERT ALL
<foreach collection="list" item="processDefinitionInfo" index="index">
INTO ${prefix}ACT_PROCDEF_INFO(ID_, PROC_DEF_ID_, REV_, INFO_JSON_ID_) VALUES
(#{processDefinitionInfo.id, jdbcType=VARCHAR},
#{processDefinitionInfo.processDefinitionId, jdbcType=VARCHAR},
1,
#{processDefinitionInfo.infoJsonId, jdbcType=VARCHAR})
</foreach>
SELECT * FROM dual
</insert>
<!-- ProcessDefinitionInfo UPDATE -->
<update id="updateProcessDefinitionInfo" parameterType="org.activiti5.engine.impl.persistence.entity.ProcessDefinitionInfoEntity">
update ${prefix}ACT_PROCDEF_INFO set
REV_ = #{revisionNext, jdbcType=INTEGER},
INFO_JSON_ID_ = #{infoJsonId, jdbcType=VARCHAR}
where ID_ = #{id, jdbcType=VARCHAR} and REV_ = #{revision, jdbcType=INTEGER}
</update>
<!-- ProcessDefinitionInfo DELETE -->
<delete id="deleteProcessDefinitionInfo" parameterType="org.activiti5.engine.impl.persistence.entity.ProcessDefinitionInfoEntity">
delete from ${prefix}ACT_PROCDEF_INFO where ID_ = #{id} and REV_ = #{revision}
</delete>
<!-- MODEL RESULTMAP -->
<resultMap id="processDefinitionInfoResultMap" type="org.activiti5.engine.impl.persistence.entity.ProcessDefinitionInfoEntity">
<id property="id" column="ID_" jdbcType="VARCHAR" />
<result property="processDefinitionId" column="PROC_DEF_ID_" jdbcType="VARCHAR" />
<result property="revision" column="REV_" jdbcType="INTEGER"/>
<result property="infoJsonId" column="INFO_JSON_ID_" jdbcType="VARCHAR" />
</resultMap>
<!-- ProcessDefinitionInfo SELECT -->
<select id="selectProcessDefinitionInfo" parameterType="string" resultMap="processDefinitionInfoResultMap">
select * from ${prefix}ACT_PROCDEF_INFO where ID_ = #{id}
</select>
<select id="selectProcessDefinitionInfoByProcessDefinitionId" parameterType="string" resultMap="processDefinitionInfoResultMap">
select * from ${prefix}ACT_PROCDEF_INFO where PROC_DEF_ID_ = #{processDefinitionId}
</select>
</mapper>
\ No newline at end of file
......@@ -33,6 +33,7 @@
<mapper resource="org/activiti5/db/mapping/entity/Membership.xml" />
<mapper resource="org/activiti5/db/mapping/entity/Model.xml" />
<mapper resource="org/activiti5/db/mapping/entity/ProcessDefinition.xml" />
<mapper resource="org/activiti5/db/mapping/entity/ProcessDefinitionInfo.xml" />
<mapper resource="org/activiti5/db/mapping/entity/Property.xml" />
<mapper resource="org/activiti5/db/mapping/entity/Resource.xml" />
<mapper resource="org/activiti5/db/mapping/entity/TableData.xml" />
......
......@@ -26,6 +26,7 @@ import org.activiti.bpmn.model.EndEvent;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.StartEvent;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.DynamicBpmnService;
import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
......@@ -70,6 +71,7 @@ public abstract class AbstractActivitiTestCase extends PvmTestCase {
protected HistoryService historyService;
protected IdentityService identityService;
protected ManagementService managementService;
protected DynamicBpmnService dynamicBpmnService;
@Override
protected void setUp() throws Exception {
......@@ -184,6 +186,7 @@ public abstract class AbstractActivitiTestCase extends PvmTestCase {
historyService = processEngine.getHistoryService();
identityService = processEngine.getIdentityService();
managementService = processEngine.getManagementService();
dynamicBpmnService = processEngine.getDynamicBpmnService();
}
public void assertProcessEnded(final String processInstanceId) {
......
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti5.engine.test.bpmn.servicetask;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.JavaDelegate;
/**
* @author Tijs Rademakers
*/
public class DummyServiceTask2 implements JavaDelegate {
public void execute(DelegateExecution execution) {
Integer count = (Integer) execution.getVariable("count2");
count = count+1;
execution.setVariable("count2", count);
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti5.engine.test.bpmn.servicetask;
import java.io.Serializable;
import org.activiti.engine.delegate.DelegateExecution;
public class DummyTestBean implements Serializable {
private static final long serialVersionUID = 1L;
public void test(DelegateExecution execution) {
execution.setVariable("executed", true);
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti5.engine.test.bpmn.servicetask;
import java.io.Serializable;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.JavaDelegate;
public class DummyTestDelegateBean implements JavaDelegate, Serializable {
private static final long serialVersionUID = 1L;
public void execute(DelegateExecution execution) {
execution.setVariable("executed", true);
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti5.engine.test.bpmn.servicetask;
import java.util.HashMap;
import java.util.Map;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.Deployment;
import org.activiti5.engine.impl.test.PluggableActivitiTestCase;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Tijs Rademakers
*/
public class DynamicServiceTaskTest extends PluggableActivitiTestCase {
@Deployment
public void testChangeClassName() {
// first test without changing the class name
Map<String, Object> varMap = new HashMap<String, Object>();
varMap.put("count", 0);
varMap.put("count2", 0);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("dynamicServiceTask", varMap);
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskService.complete(task.getId());
assertEquals(1, runtimeService.getVariable(processInstance.getId(), "count"));
assertEquals(0, runtimeService.getVariable(processInstance.getId(), "count2"));
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
// now test with changing the class name
varMap = new HashMap<String, Object>();
varMap.put("count", 0);
varMap.put("count2", 0);
processInstance = runtimeService.startProcessInstanceByKey("dynamicServiceTask", varMap);
String processDefinitionId = processInstance.getProcessDefinitionId();
ObjectNode infoNode = dynamicBpmnService.changeServiceTaskClassName("service", "org.activiti5.engine.test.bpmn.servicetask.DummyServiceTask2");
dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode);
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskService.complete(task.getId());
assertEquals(0, runtimeService.getVariable(processInstance.getId(), "count"));
assertEquals(1, runtimeService.getVariable(processInstance.getId(), "count2"));
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
}
@Deployment
public void testChangeExpression() {
// first test without changing the class name
DummyTestBean testBean = new DummyTestBean();
Map<String, Object> varMap = new HashMap<String, Object>();
varMap.put("bean", testBean);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("dynamicServiceTask", varMap);
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskService.complete(task.getId());
HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery()
.processInstanceId(processInstance.getId())
.variableName("executed")
.singleResult();
assertNotNull(historicVariableInstance);
assertTrue((Boolean) historicVariableInstance.getValue());
assertProcessEnded(processInstance.getId());
// now test with changing the class name
testBean = new DummyTestBean();
varMap = new HashMap<String, Object>();
varMap.put("bean2", testBean);
processInstance = runtimeService.startProcessInstanceByKey("dynamicServiceTask", varMap);
String processDefinitionId = processInstance.getProcessDefinitionId();
ObjectNode infoNode = dynamicBpmnService.changeServiceTaskExpression("service", "${bean2.test(execution)}");
dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode);
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskService.complete(task.getId());
historicVariableInstance = historyService.createHistoricVariableInstanceQuery()
.processInstanceId(processInstance.getId())
.variableName("executed")
.singleResult();
assertNotNull(historicVariableInstance);
assertTrue((Boolean) historicVariableInstance.getValue());
assertProcessEnded(processInstance.getId());
}
@Deployment
public void testChangeDelegateExpression() {
// first test without changing the class name
DummyTestDelegateBean testBean = new DummyTestDelegateBean();
Map<String, Object> varMap = new HashMap<String, Object>();
varMap.put("bean", testBean);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("dynamicServiceTask", varMap);
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskService.complete(task.getId());
HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery()
.processInstanceId(processInstance.getId())
.variableName("executed")
.singleResult();
assertNotNull(historicVariableInstance);
assertTrue((Boolean) historicVariableInstance.getValue());
assertProcessEnded(processInstance.getId());
// now test with changing the class name
testBean = new DummyTestDelegateBean();
varMap = new HashMap<String, Object>();
varMap.put("bean2", testBean);
processInstance = runtimeService.startProcessInstanceByKey("dynamicServiceTask", varMap);
String processDefinitionId = processInstance.getProcessDefinitionId();
ObjectNode infoNode = dynamicBpmnService.changeServiceTaskDelegateExpression("service", "${bean2}");
dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode);
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskService.complete(task.getId());
historicVariableInstance = historyService.createHistoricVariableInstanceQuery()
.processInstanceId(processInstance.getId())
.variableName("executed")
.singleResult();
assertNotNull(historicVariableInstance);
assertTrue((Boolean) historicVariableInstance.getValue());
assertProcessEnded(processInstance.getId());
}
}
\ No newline at end of file
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti5.engine.test.bpmn.usertask;
import java.util.HashMap;
import java.util.Map;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.Deployment;
import org.activiti5.engine.impl.test.AbstractActivitiTestCase;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Tijs Rademakers
*/
public class DisabledDefinitionInfoCacheTest extends AbstractActivitiTestCase {
protected static ProcessEngine cachedProcessEngine;
protected void initializeProcessEngine() {
if (cachedProcessEngine==null) {
ProcessEngineConfigurationImpl processEngineConfiguration = (ProcessEngineConfigurationImpl) ProcessEngineConfiguration
.createProcessEngineConfigurationFromResource("org/activiti5/engine/test/bpmn/usertask/activiti.cfg.xml");
cachedProcessEngine = processEngineConfiguration.buildProcessEngine();
}
processEngine = cachedProcessEngine;
}
@Deployment
public void testChangeFormKey() {
// first test without changing the form key
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
String processDefinitionId = processInstance.getProcessDefinitionId();
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
assertEquals("test", task.getFormKey());
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
// now test with changing the form key
ObjectNode infoNode = dynamicBpmnService.changeUserTaskFormKey("task1", "test2");
dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode);
processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
assertEquals("test", task.getFormKey());
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
}
@Deployment
public void testChangeClassName() {
// first test without changing the class name
Map<String, Object> varMap = new HashMap<String, Object>();
varMap.put("count", 0);
varMap.put("count2", 0);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("dynamicServiceTask", varMap);
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskService.complete(task.getId());
assertEquals(1, runtimeService.getVariable(processInstance.getId(), "count"));
assertEquals(0, runtimeService.getVariable(processInstance.getId(), "count2"));
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
// now test with changing the class name
varMap = new HashMap<String, Object>();
varMap.put("count", 0);
varMap.put("count2", 0);
processInstance = runtimeService.startProcessInstanceByKey("dynamicServiceTask", varMap);
String processDefinitionId = processInstance.getProcessDefinitionId();
ObjectNode infoNode = dynamicBpmnService.changeServiceTaskClassName("service", "org.activiti5.engine.test.bpmn.servicetask.DummyServiceTask2");
dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode);
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskService.complete(task.getId());
assertEquals(1, runtimeService.getVariable(processInstance.getId(), "count"));
assertEquals(0, runtimeService.getVariable(processInstance.getId(), "count2"));
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti5.engine.test.bpmn.usertask;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.IdentityLinkType;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.Deployment;
import org.activiti5.engine.impl.test.PluggableActivitiTestCase;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Tijs Rademakers
*/
public class DynamicUserTaskTest extends PluggableActivitiTestCase {
@Deployment(resources={"org/activiti5/engine/test/bpmn/usertask/DynamicUserTaskTest.assignment.bpmn20.xml"})
public void testChangeAssignee() {
// first test without changing the form key
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
String processDefinitionId = processInstance.getProcessDefinitionId();
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
assertEquals("test", task.getAssignee());
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
// now test with changing the form key
ObjectNode infoNode = dynamicBpmnService.changeUserTaskAssignee("task1", "test2");
dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode);
processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
assertEquals("test2", task.getAssignee());
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
}
@Deployment(resources={"org/activiti5/engine/test/bpmn/usertask/DynamicUserTaskTest.assignment.bpmn20.xml"})
public void testChangeOwner() {
// first test without changing the form key
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
String processDefinitionId = processInstance.getProcessDefinitionId();
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
assertEquals("ownerTest", task.getOwner());
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
// now test with changing the form key
ObjectNode infoNode = dynamicBpmnService.changeUserTaskOwner("task1", "ownerTest2");
dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode);
processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
assertEquals("ownerTest2", task.getOwner());
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
}
@Deployment(resources={"org/activiti5/engine/test/bpmn/usertask/DynamicUserTaskTest.basictask.bpmn20.xml"})
public void testChangeCandidateUsers() {
// first test without changing the form key
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
String processDefinitionId = processInstance.getProcessDefinitionId();
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
List<IdentityLink> taskIdentityLinks = taskService.getIdentityLinksForTask(task.getId());
boolean candidateUserTestFound = false;
for (IdentityLink identityLink : taskIdentityLinks) {
if (IdentityLinkType.CANDIDATE.equals(identityLink.getType()) && identityLink.getUserId() != null && identityLink.getGroupId() == null) {
if ("test".equals(identityLink.getUserId())) {
candidateUserTestFound = true;
}
}
}
assertFalse(candidateUserTestFound);
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
// now test with changing the form key
ObjectNode infoNode = dynamicBpmnService.changeUserTaskCandidateUser("task1", "test", true);
dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode);
processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskIdentityLinks = taskService.getIdentityLinksForTask(task.getId());
candidateUserTestFound = false;
for (IdentityLink identityLink : taskIdentityLinks) {
if (IdentityLinkType.CANDIDATE.equals(identityLink.getType()) && identityLink.getUserId() != null && identityLink.getGroupId() == null) {
if ("test".equals(identityLink.getUserId())) {
candidateUserTestFound = true;
}
}
}
assertTrue(candidateUserTestFound);
taskService.complete(task.getId());
infoNode = dynamicBpmnService.getProcessDefinitionInfo(processDefinitionId);
dynamicBpmnService.changeUserTaskCandidateUser("task1", "test2", false, infoNode);
dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode);
processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskIdentityLinks = taskService.getIdentityLinksForTask(task.getId());
candidateUserTestFound = false;
boolean candidateUserTest2Found = false;
for (IdentityLink identityLink : taskIdentityLinks) {
if (IdentityLinkType.CANDIDATE.equals(identityLink.getType()) && identityLink.getUserId() != null && identityLink.getGroupId() == null) {
if ("test".equals(identityLink.getUserId())) {
candidateUserTestFound = true;
} else if ("test2".equals(identityLink.getUserId())) {
candidateUserTest2Found = true;
}
}
}
assertTrue(candidateUserTestFound);
assertTrue(candidateUserTest2Found);
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
}
@Deployment(resources={"org/activiti5/engine/test/bpmn/usertask/DynamicUserTaskTest.basictask.bpmn20.xml"})
public void testChangeCandidateGroups() {
// first test without changing the form key
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
String processDefinitionId = processInstance.getProcessDefinitionId();
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
List<IdentityLink> taskIdentityLinks = taskService.getIdentityLinksForTask(task.getId());
boolean candidateGroupTestFound = false;
for (IdentityLink identityLink : taskIdentityLinks) {
if (IdentityLinkType.CANDIDATE.equals(identityLink.getType()) && identityLink.getGroupId() != null && identityLink.getUserId() == null) {
if ("test".equals(identityLink.getGroupId())) {
candidateGroupTestFound = true;
}
}
}
assertFalse(candidateGroupTestFound);
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
// now test with changing the form key
ObjectNode infoNode = dynamicBpmnService.changeUserTaskCandidateGroup("task1", "test", true);
dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode);
processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskIdentityLinks = taskService.getIdentityLinksForTask(task.getId());
candidateGroupTestFound = false;
for (IdentityLink identityLink : taskIdentityLinks) {
if (IdentityLinkType.CANDIDATE.equals(identityLink.getType()) && identityLink.getGroupId() != null && identityLink.getUserId() == null) {
if ("test".equals(identityLink.getGroupId())) {
candidateGroupTestFound = true;
}
}
}
assertTrue(candidateGroupTestFound);
taskService.complete(task.getId());
infoNode = dynamicBpmnService.getProcessDefinitionInfo(processDefinitionId);
dynamicBpmnService.changeUserTaskCandidateGroup("task1", "test2", false, infoNode);
dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode);
processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskIdentityLinks = taskService.getIdentityLinksForTask(task.getId());
candidateGroupTestFound = false;
boolean candidateGroupTest2Found = false;
for (IdentityLink identityLink : taskIdentityLinks) {
if (IdentityLinkType.CANDIDATE.equals(identityLink.getType()) && identityLink.getGroupId() != null && identityLink.getUserId() == null) {
if ("test".equals(identityLink.getGroupId())) {
candidateGroupTestFound = true;
} else if ("test2".equals(identityLink.getGroupId())) {
candidateGroupTest2Found = true;
}
}
}
assertTrue(candidateGroupTestFound);
assertTrue(candidateGroupTest2Found);
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
}
@Deployment(resources={"org/activiti5/engine/test/bpmn/usertask/DynamicUserTaskTest.basictask.bpmn20.xml"})
public void testChangeCandidateUsersAndGroups() {
// first test without changing the form key
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
String processDefinitionId = processInstance.getProcessDefinitionId();
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
List<IdentityLink> taskIdentityLinks = taskService.getIdentityLinksForTask(task.getId());
boolean candidateUserTestFound = false;
boolean candidateGroupTestFound = false;
for (IdentityLink identityLink : taskIdentityLinks) {
if (IdentityLinkType.CANDIDATE.equals(identityLink.getType()) && identityLink.getUserId() != null && identityLink.getGroupId() == null) {
if ("test".equals(identityLink.getUserId())) {
candidateUserTestFound = true;
}
} else if (IdentityLinkType.CANDIDATE.equals(identityLink.getType()) && identityLink.getGroupId() != null && identityLink.getUserId() == null) {
if ("test".equals(identityLink.getGroupId())) {
candidateGroupTestFound = true;
}
}
}
assertFalse(candidateUserTestFound);
assertFalse(candidateGroupTestFound);
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
// now test with changing the form key
ObjectNode infoNode = dynamicBpmnService.changeUserTaskCandidateGroup("task1", "test", true);
dynamicBpmnService.changeUserTaskCandidateUser("task1", "test", true, infoNode);
dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode);
processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskIdentityLinks = taskService.getIdentityLinksForTask(task.getId());
candidateUserTestFound = false;
candidateGroupTestFound = false;
for (IdentityLink identityLink : taskIdentityLinks) {
if (IdentityLinkType.CANDIDATE.equals(identityLink.getType()) && identityLink.getUserId() != null && identityLink.getGroupId() == null) {
if ("test".equals(identityLink.getUserId())) {
candidateUserTestFound = true;
}
} else if (IdentityLinkType.CANDIDATE.equals(identityLink.getType()) && identityLink.getGroupId() != null && identityLink.getUserId() == null) {
if ("test".equals(identityLink.getGroupId())) {
candidateGroupTestFound = true;
}
}
}
assertTrue(candidateUserTestFound);
assertTrue(candidateGroupTestFound);
taskService.complete(task.getId());
infoNode = dynamicBpmnService.getProcessDefinitionInfo(processDefinitionId);
dynamicBpmnService.changeUserTaskCandidateGroup("task1", "test2", false, infoNode);
dynamicBpmnService.changeUserTaskCandidateUser("task1", "test2", false, infoNode);
dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode);
processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskIdentityLinks = taskService.getIdentityLinksForTask(task.getId());
candidateUserTestFound = false;
boolean candidateUserTestFound2 = false;
candidateGroupTestFound = false;
boolean candidateGroupTest2Found = false;
for (IdentityLink identityLink : taskIdentityLinks) {
if (IdentityLinkType.CANDIDATE.equals(identityLink.getType()) && identityLink.getUserId() != null && identityLink.getGroupId() == null) {
if ("test".equals(identityLink.getUserId())) {
candidateUserTestFound = true;
} else if ("test2".equals(identityLink.getUserId())) {
candidateUserTestFound2 = true;
}
} else if (IdentityLinkType.CANDIDATE.equals(identityLink.getType()) && identityLink.getGroupId() != null && identityLink.getUserId() == null) {
if ("test".equals(identityLink.getGroupId())) {
candidateGroupTestFound = true;
} else if ("test2".equals(identityLink.getGroupId())) {
candidateGroupTest2Found = true;
}
}
}
assertTrue(candidateUserTestFound);
assertTrue(candidateUserTestFound2);
assertTrue(candidateGroupTestFound);
assertTrue(candidateGroupTest2Found);
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
}
@Deployment(resources={"org/activiti5/engine/test/bpmn/usertask/DynamicUserTaskTest.basictask.bpmn20.xml"})
public void testChangeNameAndDescription() {
// first test without changing the form key
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
String processDefinitionId = processInstance.getProcessDefinitionId();
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
assertNull(task.getName());
assertNull(task.getDescription());
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
// now test with changing the form key
ObjectNode infoNode = dynamicBpmnService.changeUserTaskName("task1", "Task name test");
dynamicBpmnService.changeUserTaskDescription("task1", "Task description test", infoNode);
dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode);
processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
assertEquals("Task name test", task.getName());
assertEquals("Task description test", task.getDescription());
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
}
@Deployment(resources={"org/activiti5/engine/test/bpmn/usertask/DynamicUserTaskTest.assignment.bpmn20.xml"})
public void testChangePriorityAndCategory() {
// first test without changing the form key
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
String processDefinitionId = processInstance.getProcessDefinitionId();
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
assertEquals(50, task.getPriority());
assertNull(task.getCategory());
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
// now test with changing the form key
ObjectNode infoNode = dynamicBpmnService.changeUserTaskPriority("task1", "99");
dynamicBpmnService.changeUserTaskCategory("task1", "categoryTest", infoNode);
dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode);
processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
assertEquals(99, task.getPriority());
assertEquals("categoryTest", task.getCategory());
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
}
@Deployment
public void testChangeFormKey() {
// first test without changing the form key
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
String processDefinitionId = processInstance.getProcessDefinitionId();
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
assertEquals("test", task.getFormKey());
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
// now test with changing the form key
ObjectNode infoNode = dynamicBpmnService.changeUserTaskFormKey("task1", "test2");
dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode);
processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask");
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
assertEquals("test2", task.getFormKey());
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
}
@Deployment
public void testChangeFormKeyWithExpression() {
// first test without changing the form key
Map<String, Object> varMap = new HashMap<String, Object>();
varMap.put("start", "test");
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask", varMap);
String processDefinitionId = processInstance.getProcessDefinitionId();
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
assertEquals("test", task.getFormKey());
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
// now test with changing the form key
ObjectNode infoNode = dynamicBpmnService.changeUserTaskFormKey("task1", "${anotherKey}");
dynamicBpmnService.saveProcessDefinitionInfo(processDefinitionId, infoNode);
varMap = new HashMap<String, Object>();
varMap.put("anotherKey", "test2");
processInstance = runtimeService.startProcessInstanceByKey("dynamicUserTask", varMap);
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
assertEquals("test2", task.getFormKey());
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
}
}
......@@ -45,6 +45,8 @@
</property>
<property name="history" value="full" />
<property name="enableProcessDefinitionInfoCache" value="true" />
</bean>
<bean id="asyncExecutor" class="org.activiti.engine.impl.asyncexecutor.DefaultAsyncJobExecutor">
......
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="Examples">
<process id="dynamicServiceTask">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="task1" />
<userTask id="task1" activiti:assignee="test" />
<sequenceFlow id="flow2" sourceRef="task1" targetRef="service" />
<serviceTask id="service" activiti:class="org.activiti5.engine.test.bpmn.servicetask.DummyServiceTask" />
<sequenceFlow id="flow3" sourceRef="service" targetRef="task2" />
<userTask id="task2" activiti:assignee="test" />
<sequenceFlow id="flow4" sourceRef="task2" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="Examples">
<process id="dynamicServiceTask">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="task1" />
<userTask id="task1" activiti:assignee="test" />
<sequenceFlow id="flow2" sourceRef="task1" targetRef="service" />
<serviceTask id="service" activiti:delegateExpression="${bean}" />
<sequenceFlow id="flow3" sourceRef="service" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="Examples">
<process id="dynamicServiceTask">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="task1" />
<userTask id="task1" activiti:assignee="test" />
<sequenceFlow id="flow2" sourceRef="task1" targetRef="service" />
<serviceTask id="service" activiti:expression="${bean.test(execution)}" />
<sequenceFlow id="flow3" sourceRef="service" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="Examples">
<process id="dynamicServiceTask">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="task1" />
<userTask id="task1" activiti:assignee="test" />
<sequenceFlow id="flow2" sourceRef="task1" targetRef="service" />
<serviceTask id="service" activiti:class="org.activiti5.engine.test.bpmn.servicetask.DummyServiceTask" />
<sequenceFlow id="flow3" sourceRef="service" targetRef="task2" />
<userTask id="task2" activiti:assignee="test" />
<sequenceFlow id="flow4" sourceRef="task2" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="Examples">
<process id="dynamicUserTask">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="task1" />
<userTask id="task1" activiti:formKey="test" activiti:assignee="test" />
<sequenceFlow id="flow2" sourceRef="task1" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="Examples">
<process id="dynamicUserTask">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="task1" />
<userTask id="task1" activiti:formKey="test" activiti:assignee="test" activiti:owner="ownerTest" />
<sequenceFlow id="flow2" sourceRef="task1" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="Examples">
<process id="dynamicUserTask">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="task1" />
<userTask id="task1" />
<sequenceFlow id="flow2" sourceRef="task1" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="Examples">
<process id="dynamicUserTask">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="task1" />
<userTask id="task1" activiti:formKey="test" activiti:assignee="test" />
<sequenceFlow id="flow2" sourceRef="task1" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="Examples">
<process id="dynamicUserTask">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="task1" />
<userTask id="task1" activiti:formKey="${start}" activiti:assignee="test" />
<sequenceFlow id="flow2" sourceRef="task1" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
<!-- Database configurations -->
<property name="databaseSchemaUpdate" value="true" />
<property name="jdbcUrl" value="jdbc:h2:mem:DisabledDefinitionInfoCacheTest;DB_CLOSE_DELAY=1000" />
<!-- job executor configurations -->
<property name="jobExecutorActivate" value="false" />
<property name="activiti5CompatibilityEnabled" value="true" />
<!-- mail server configurations -->
<property name="mailServerPort" value="5025" />
</bean>
</beans>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册