From 89cfecbeaa5a3dcaf2a7dd9e8f6864a6e49f0109 Mon Sep 17 00:00:00 2001 From: Tijs Rademakers Date: Tue, 20 Oct 2015 21:14:44 +0200 Subject: [PATCH] Dynamic bpmn functionality for the Activiti 6 engine --- .../activiti/engine/DynamicBpmnConstants.java | 40 ++ .../activiti/engine/DynamicBpmnService.java | 91 ++++ .../org/activiti/engine/ProcessEngine.java | 2 + .../engine/ProcessEngineConfiguration.java | 11 + .../engine/impl/DynamicBpmnServiceImpl.java | 309 +++++++++++++ .../impl/HistoricTaskInstanceQueryImpl.java | 61 ++- .../engine/impl/ProcessEngineImpl.java | 7 + .../activiti/engine/impl/TaskQueryImpl.java | 50 ++- ...askDelegateExpressionActivityBehavior.java | 18 +- ...ServiceTaskExpressionActivityBehavior.java | 20 +- .../behavior/UserTaskActivityBehavior.java | 138 ++++-- .../impl/bpmn/deployer/BpmnDeployer.java | 52 ++- .../impl/bpmn/helper/ClassDelegate.java | 20 +- .../DefaultActivityBehaviorFactory.java | 8 +- .../cfg/ProcessEngineConfigurationImpl.java | 58 ++- .../impl/cmd/GetProcessDefinitionInfoCmd.java | 56 +++ .../cmd/SaveProcessDefinitionInfoCmd.java | 74 ++++ .../activiti/engine/impl/context/Context.java | 59 +++ .../activiti/engine/impl/db/DbSqlSession.java | 1 + .../engine/impl/event/logger/EventLogger.java | 4 +- .../handler/AbstractTaskEventHandler.java | 5 +- .../impl/history/DefaultHistoryManager.java | 17 - .../impl/interceptor/CommandContext.java | 5 + .../CommandContextInterceptor.java | 1 + .../impl/persistence/AbstractManager.java | 5 + .../persistence/deploy/DeploymentManager.java | 9 + .../deploy/ProcessDefinitionInfoCache.java | 133 ++++++ .../ProcessDefinitionInfoCacheObject.java | 49 ++ .../entity/DeploymentEntityManagerImpl.java | 2 + .../entity/HistoricTaskInstanceEntity.java | 6 + .../HistoricTaskInstanceEntityImpl.java | 27 +- .../entity/ProcessDefinitionInfoEntity.java | 34 ++ .../ProcessDefinitionInfoEntityImpl.java | 77 ++++ .../ProcessDefinitionInfoEntityManager.java | 37 ++ ...rocessDefinitionInfoEntityManagerImpl.java | 85 ++++ .../persistence/entity/TaskEntityImpl.java | 30 +- .../ProcessDefinitionInfoDataManager.java | 23 + ...batisProcessDefinitionInfoDataManager.java | 44 ++ .../impl/test/AbstractActivitiTestCase.java | 3 + .../engine/impl/variable/JsonType.java | 7 +- .../engine/impl/variable/LongJsonType.java | 7 +- .../java/org/activiti/engine/task/Task.java | 6 + .../activiti/engine/task/TaskInfoQuery.java | 5 + .../db/create/activiti.db2.create.engine.sql | 29 +- .../db/create/activiti.h2.create.engine.sql | 23 + .../db/create/activiti.hsql.create.engine.sql | 29 +- .../create/activiti.mssql.create.engine.sql | 29 +- .../create/activiti.mysql.create.engine.sql | 29 +- .../create/activiti.mysql55.create.engine.sql | 29 +- .../create/activiti.oracle.create.engine.sql | 23 + .../activiti.postgres.create.engine.sql | 24 + .../db/drop/activiti.db2.drop.engine.sql | 10 +- .../db/drop/activiti.h2.drop.engine.sql | 4 +- .../db/drop/activiti.hsql.drop.engine.sql | 4 +- .../db/drop/activiti.mssql.drop.engine.sql | 4 + .../db/drop/activiti.mysql.drop.engine.sql | 12 +- .../db/drop/activiti.oracle.drop.engine.sql | 10 +- .../db/drop/activiti.postgres.drop.engine.sql | 1 + .../mapping/entity/ProcessDefinitionInfo.xml | 74 ++++ .../org/activiti/db/mapping/mappings.xml | 1 + ....db2.upgradestep.51800.to.51801.engine.sql | 26 ++ ...i.h2.upgradestep.51800.to.51801.engine.sql | 26 ++ ...hsql.upgradestep.51800.to.51801.engine.sql | 26 ++ ...ssql.upgradestep.51800.to.51801.engine.sql | 26 ++ ...ysql.upgradestep.51800.to.51801.engine.sql | 26 ++ ...ql55.upgradestep.51800.to.51801.engine.sql | 26 ++ ...acle.upgradestep.51800.to.51801.engine.sql | 26 ++ ...gres.upgradestep.51800.to.51801.engine.sql | 26 ++ .../test/api/event/ActivityEventsTest.java | 2 +- .../api/event/DatabaseEventLoggerTest.java | 2 +- .../test/api/history/HistoryServiceTest.java | 48 ++ .../engine/test/api/task/TaskQueryTest.java | 49 +- .../bpmn/servicetask/DummyServiceTask2.java | 31 ++ .../test/bpmn/servicetask/DummyTestBean.java | 27 ++ .../servicetask/DummyTestDelegateBean.java | 28 ++ .../servicetask/DynamicServiceTaskTest.java | 159 +++++++ .../DisabledDefinitionInfoCacheTest.java | 115 +++++ .../bpmn/usertask/DynamicUserTaskTest.java | 417 ++++++++++++++++++ .../src/test/resources/activiti.cfg.xml | 2 + ...iceTaskTest.testChangeClassName.bpmn20.xml | 28 ++ ...st.testChangeDelegateExpression.bpmn20.xml | 24 + ...ceTaskTest.testChangeExpression.bpmn20.xml | 24 + ...foCacheTest.testChangeClassName.bpmn20.xml | 28 ++ ...InfoCacheTest.testChangeFormKey.bpmn20.xml | 20 + .../DynamicUserTaskTest.assignment.bpmn20.xml | 20 + .../DynamicUserTaskTest.basictask.bpmn20.xml | 20 + ...cUserTaskTest.testChangeFormKey.bpmn20.xml | 20 + ...testChangeFormKeyWithExpression.bpmn20.xml | 20 + .../test/bpmn/usertask/activiti.cfg.xml | 20 + .../StandaloneDatabaseEventLoggerTest.java | 2 +- qa/activiti5db/activiti.cfg.xml | 1 + qa/cfg/historyaudit.activiti.cfg.xml | 2 + qa/cfg/historyfull.activiti.cfg.xml | 2 + qa/cfg/historynone.activiti.cfg.xml | 2 + qa/db/activiti.cfg.xml | 1 + qa/db/historyfull.activiti.cfg.xml | 2 + qa/db/mssql/activiti.cfg.xml | 4 +- qa/db/schema/activiti.cfg.xml | 1 + qa/jta/mysql/activiti.cfg.xml | 1 + qa/jta/oracle/activiti.cfg.xml | 1 + qa/jta/postgres/activiti.cfg.xml | 1 + qa/spring/h2/activiti.cfg.xml | 1 + qa/spring/mysql/activiti.cfg.xml | 1 + qa/upgrade/activiti.cfg.xml | 2 +- 104 files changed, 3257 insertions(+), 110 deletions(-) create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/DynamicBpmnConstants.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/DynamicBpmnService.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/DynamicBpmnServiceImpl.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/cmd/GetProcessDefinitionInfoCmd.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/cmd/SaveProcessDefinitionInfoCmd.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/deploy/ProcessDefinitionInfoCache.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/deploy/ProcessDefinitionInfoCacheObject.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionInfoEntity.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionInfoEntityImpl.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionInfoEntityManager.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionInfoEntityManagerImpl.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/data/ProcessDefinitionInfoDataManager.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/data/impl/MybatisProcessDefinitionInfoDataManager.java create mode 100644 modules/activiti-engine/src/main/resources/org/activiti/db/mapping/entity/ProcessDefinitionInfo.xml create mode 100644 modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.db2.upgradestep.51800.to.51801.engine.sql create mode 100644 modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.h2.upgradestep.51800.to.51801.engine.sql create mode 100644 modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.hsql.upgradestep.51800.to.51801.engine.sql create mode 100644 modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.mssql.upgradestep.51800.to.51801.engine.sql create mode 100644 modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.mysql.upgradestep.51800.to.51801.engine.sql create mode 100644 modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.mysql55.upgradestep.51800.to.51801.engine.sql create mode 100644 modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.oracle.upgradestep.51800.to.51801.engine.sql create mode 100644 modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.postgres.upgradestep.51800.to.51801.engine.sql create mode 100644 modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/servicetask/DummyServiceTask2.java create mode 100644 modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/servicetask/DummyTestBean.java create mode 100644 modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/servicetask/DummyTestDelegateBean.java create mode 100644 modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/servicetask/DynamicServiceTaskTest.java create mode 100644 modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/usertask/DisabledDefinitionInfoCacheTest.java create mode 100644 modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.java create mode 100644 modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/servicetask/DynamicServiceTaskTest.testChangeClassName.bpmn20.xml create mode 100644 modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/servicetask/DynamicServiceTaskTest.testChangeDelegateExpression.bpmn20.xml create mode 100644 modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/servicetask/DynamicServiceTaskTest.testChangeExpression.bpmn20.xml create mode 100644 modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DisabledDefinitionInfoCacheTest.testChangeClassName.bpmn20.xml create mode 100644 modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DisabledDefinitionInfoCacheTest.testChangeFormKey.bpmn20.xml create mode 100644 modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.assignment.bpmn20.xml create mode 100644 modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.basictask.bpmn20.xml create mode 100644 modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.testChangeFormKey.bpmn20.xml create mode 100644 modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.testChangeFormKeyWithExpression.bpmn20.xml create mode 100644 modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/activiti.cfg.xml diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/DynamicBpmnConstants.java b/modules/activiti-engine/src/main/java/org/activiti/engine/DynamicBpmnConstants.java new file mode 100644 index 0000000000..4f316f6e0d --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/DynamicBpmnConstants.java @@ -0,0 +1,40 @@ +/* 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.activiti.engine; + +public interface DynamicBpmnConstants { + + String BPMN_NODE = "bpmn"; + String LOCALIZATION_NODE = "localization"; + + String TASK_SKIP_EXPRESSION = "taskSkipExpression"; + + String SERVICE_TASK_CLASS_NAME = "serviceTaskClassName"; + String SERVICE_TASK_EXPRESSION = "serviceTaskExpression"; + String SERVICE_TASK_DELEGATE_EXPRESSION = "serviceTaskDelegateExpression"; + + String USER_TASK_NAME = "userTaskName"; + String USER_TASK_DESCRIPTION = "userTaskDescription"; + String USER_TASK_DUEDATE = "userTaskDueDate"; + String USER_TASK_PRIORITY = "userTaskPriority"; + String USER_TASK_CATEGORY = "userTaskCategory"; + String USER_TASK_FORM_KEY = "userTaskFormKey"; + String USER_TASK_ASSIGNEE = "userTaskAssignee"; + String USER_TASK_OWNER = "userTaskOwner"; + String USER_TASK_CANDIDATE_USERS = "userTaskCandidateUsers"; + String USER_TASK_CANDIDATE_GROUPS = "userTaskCandidateGroups"; + + String LOCALIZATION_LANGUAGE = "language"; + String LOCALIZATION_NAME = "name"; + String LOCALIZATION_DESCRIPTION = "description"; +} \ No newline at end of file diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/DynamicBpmnService.java b/modules/activiti-engine/src/main/java/org/activiti/engine/DynamicBpmnService.java new file mode 100644 index 0000000000..18557957b1 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/DynamicBpmnService.java @@ -0,0 +1,91 @@ +/* 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.activiti.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 diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/ProcessEngine.java b/modules/activiti-engine/src/main/java/org/activiti/engine/ProcessEngine.java index 3fc98994c2..73d44fc463 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/ProcessEngine.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/ProcessEngine.java @@ -61,6 +61,8 @@ public interface ProcessEngine { IdentityService getIdentityService(); ManagementService getManagementService(); + + DynamicBpmnService getDynamicBpmnService(); ProcessEngineConfiguration getProcessEngineConfiguration(); } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/ProcessEngineConfiguration.java b/modules/activiti-engine/src/main/java/org/activiti/engine/ProcessEngineConfiguration.java index 87a6e47de6..396c784dc4 100755 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/ProcessEngineConfiguration.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/ProcessEngineConfiguration.java @@ -204,6 +204,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() { @@ -802,4 +804,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; + } } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/DynamicBpmnServiceImpl.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/DynamicBpmnServiceImpl.java new file mode 100644 index 0000000000..9c526587bb --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/DynamicBpmnServiceImpl.java @@ -0,0 +1,309 @@ +/* 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.activiti.engine.impl; + +import org.activiti.engine.DynamicBpmnConstants; +import org.activiti.engine.DynamicBpmnService; +import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.activiti.engine.impl.cmd.GetProcessDefinitionInfoCmd; +import org.activiti.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 diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/HistoricTaskInstanceQueryImpl.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/HistoricTaskInstanceQueryImpl.java index 18bc7b6bf0..30565150ec 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/HistoricTaskInstanceQueryImpl.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/HistoricTaskInstanceQueryImpl.java @@ -19,14 +19,19 @@ import java.util.List; import org.activiti.engine.ActivitiException; import org.activiti.engine.ActivitiIllegalArgumentException; +import org.activiti.engine.DynamicBpmnConstants; import org.activiti.engine.history.HistoricTaskInstance; import org.activiti.engine.history.HistoricTaskInstanceQuery; import org.activiti.engine.identity.Group; import org.activiti.engine.impl.context.Context; import org.activiti.engine.impl.interceptor.CommandContext; import org.activiti.engine.impl.interceptor.CommandExecutor; +import org.activiti.engine.impl.persistence.entity.HistoricTaskInstanceEntity; import org.activiti.engine.impl.variable.VariableTypes; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + /** * @author Tom Baeyens */ @@ -95,6 +100,7 @@ public class HistoricTaskInstanceQueryImpl extends AbstractVariableQueryImpl orQueryObjects = new ArrayList(); @@ -124,11 +130,20 @@ public class HistoricTaskInstanceQueryImpl extends AbstractVariableQueryImpl executeList(CommandContext commandContext, Page page) { ensureVariablesInitialized(); checkQueryOk(); + List tasks = null; if (includeTaskLocalVariables || includeProcessVariables) { - return commandContext.getHistoricTaskInstanceEntityManager().findHistoricTaskInstancesAndVariablesByQueryCriteria(this); + tasks = commandContext.getHistoricTaskInstanceEntityManager().findHistoricTaskInstancesAndVariablesByQueryCriteria(this); } else { - return commandContext.getHistoricTaskInstanceEntityManager().findHistoricTaskInstancesByQueryCriteria(this); + tasks = commandContext.getHistoricTaskInstanceEntityManager().findHistoricTaskInstancesByQueryCriteria(this); + } + + if (tasks != null) { + for (HistoricTaskInstance task : tasks) { + localize(task); + } } + + return tasks; } public HistoricTaskInstanceQueryImpl processInstanceId(String processInstanceId) { @@ -995,6 +1010,11 @@ public class HistoricTaskInstanceQueryImpl extends AbstractVariableQueryImpl getOrQueryObjects() { + + public String getLocale() { + return locale; + } + + public List getOrQueryObjects() { return orQueryObjects; } } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/ProcessEngineImpl.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/ProcessEngineImpl.java index efab25733a..70ccb3c33f 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/ProcessEngineImpl.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/ProcessEngineImpl.java @@ -14,6 +14,7 @@ package org.activiti.engine.impl; import java.util.Map; +import org.activiti.engine.DynamicBpmnService; import org.activiti.engine.FormService; import org.activiti.engine.HistoryService; import org.activiti.engine.IdentityService; @@ -50,6 +51,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 +70,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 +157,10 @@ public class ProcessEngineImpl implements ProcessEngine { public FormService getFormService() { return formService; } + + public DynamicBpmnService getDynamicBpmnService() { + return dynamicBpmnService; + } public ProcessEngineConfigurationImpl getProcessEngineConfiguration() { return processEngineConfiguration; diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/TaskQueryImpl.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/TaskQueryImpl.java index 245a17d5da..879ec46ad2 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/TaskQueryImpl.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/TaskQueryImpl.java @@ -18,6 +18,7 @@ import java.util.List; import org.activiti.engine.ActivitiException; import org.activiti.engine.ActivitiIllegalArgumentException; +import org.activiti.engine.DynamicBpmnConstants; import org.activiti.engine.identity.Group; import org.activiti.engine.impl.context.Context; import org.activiti.engine.impl.interceptor.CommandContext; @@ -28,6 +29,9 @@ import org.activiti.engine.task.DelegationState; import org.activiti.engine.task.Task; import org.activiti.engine.task.TaskQuery; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + /** * @author Joram Barrez * @author Tom Baeyens @@ -100,6 +104,7 @@ public class TaskQueryImpl extends AbstractVariableQueryImpl im protected String userIdForCandidateAndAssignee; protected boolean bothCandidateAndAssigned; protected boolean orActive; + protected String locale; protected List orQueryObjects = new ArrayList(); protected TaskQueryImpl currentOrQueryObject = null; @@ -1042,6 +1047,11 @@ public class TaskQueryImpl extends AbstractVariableQueryImpl im } return this; } + + public TaskQuery locale(String locale) { + this.locale = locale; + return this; + } public TaskQuery includeTaskLocalVariables() { this.includeTaskLocalVariables = true; @@ -1202,11 +1212,20 @@ public class TaskQueryImpl extends AbstractVariableQueryImpl im public List executeList(CommandContext commandContext, Page page) { ensureVariablesInitialized(); checkQueryOk(); + List tasks = null; if (includeTaskLocalVariables || includeProcessVariables) { - return commandContext.getTaskEntityManager().findTasksAndVariablesByQueryCriteria(this); + tasks = commandContext.getTaskEntityManager().findTasksAndVariablesByQueryCriteria(this); } else { - return commandContext.getTaskEntityManager().findTasksByQueryCriteria(this); + tasks = commandContext.getTaskEntityManager().findTasksByQueryCriteria(this); } + + if (tasks != null) { + for (Task task : tasks) { + localize(task); + } + } + + return tasks; } public long executeCount(CommandContext commandContext) { @@ -1214,6 +1233,29 @@ public class TaskQueryImpl extends AbstractVariableQueryImpl im checkQueryOk(); return commandContext.getTaskEntityManager().findTaskCountByQueryCriteria(this); } + + protected void localize(Task task) { + task.setLocalizedName(null); + task.setLocalizedDescription(null); + + if (locale != null) { + String processDefinitionId = task.getProcessDefinitionId(); + if (processDefinitionId != null) { + ObjectNode languageNode = Context.getLocalizationElementProperties(locale, task.getTaskDefinitionKey(), processDefinitionId); + if (languageNode != null) { + JsonNode languageNameNode = languageNode.get(DynamicBpmnConstants.LOCALIZATION_NAME); + if (languageNameNode != null && languageNameNode.isNull() == false) { + task.setLocalizedName(languageNameNode.asText()); + } + + JsonNode languageDescriptionNode = languageNode.get(DynamicBpmnConstants.LOCALIZATION_DESCRIPTION); + if (languageDescriptionNode != null && languageDescriptionNode.isNull() == false) { + task.setLocalizedDescription(languageDescriptionNode.asText()); + } + } + } + } + } // getters //////////////////////////////////////////////////////////////// @@ -1468,6 +1510,10 @@ public class TaskQueryImpl extends AbstractVariableQueryImpl im public String getProcessDefinitionKeyLikeIgnoreCase() { return processDefinitionKeyLikeIgnoreCase; } + + public String getLocale() { + return locale; + } public boolean isOrActive() { return orActive; diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskDelegateExpressionActivityBehavior.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskDelegateExpressionActivityBehavior.java index 5707894ee2..43a3c42341 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskDelegateExpressionActivityBehavior.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskDelegateExpressionActivityBehavior.java @@ -16,6 +16,7 @@ import java.util.List; import org.activiti.engine.ActivitiException; import org.activiti.engine.ActivitiIllegalArgumentException; +import org.activiti.engine.DynamicBpmnConstants; import org.activiti.engine.delegate.BpmnError; import org.activiti.engine.delegate.DelegateExecution; import org.activiti.engine.delegate.Expression; @@ -29,6 +30,9 @@ import org.activiti.engine.impl.delegate.ActivityBehavior; import org.activiti.engine.impl.delegate.ActivityBehaviorInvocation; import org.activiti.engine.impl.delegate.TriggerableActivityBehavior; import org.activiti.engine.impl.delegate.invocation.JavaDelegateInvocation; +import org.apache.commons.lang3.StringUtils; + +import com.fasterxml.jackson.databind.node.ObjectNode; /** * {@link ActivityBehavior} used when 'delegateExpression' is used for a serviceTask. @@ -42,11 +46,13 @@ public class ServiceTaskDelegateExpressionActivityBehavior extends TaskActivityB private static final long serialVersionUID = 1L; + protected String serviceTaskId; protected Expression expression; protected Expression skipExpression; private final List fieldDeclarations; - public ServiceTaskDelegateExpressionActivityBehavior(Expression expression, Expression skipExpression, List fieldDeclarations) { + public ServiceTaskDelegateExpressionActivityBehavior(String serviceTaskId, Expression expression, Expression skipExpression, List fieldDeclarations) { + this.serviceTaskId = serviceTaskId; this.expression = expression; this.skipExpression = skipExpression; this.fieldDeclarations = fieldDeclarations; @@ -67,6 +73,16 @@ public class ServiceTaskDelegateExpressionActivityBehavior extends TaskActivityB boolean isSkipExpressionEnabled = SkipExpressionUtil.isSkipExpressionEnabled(execution, skipExpression); if (!isSkipExpressionEnabled || (isSkipExpressionEnabled && !SkipExpressionUtil.shouldSkipFlowElement(execution, 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()}' Object delegate = expression.getValue(execution); diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskExpressionActivityBehavior.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskExpressionActivityBehavior.java index 364176ae50..8a73913604 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskExpressionActivityBehavior.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskExpressionActivityBehavior.java @@ -14,11 +14,16 @@ package org.activiti.engine.impl.bpmn.behavior; import org.activiti.engine.ActivitiException; +import org.activiti.engine.DynamicBpmnConstants; import org.activiti.engine.delegate.BpmnError; import org.activiti.engine.delegate.DelegateExecution; import org.activiti.engine.delegate.Expression; import org.activiti.engine.impl.bpmn.helper.ErrorPropagation; import org.activiti.engine.impl.bpmn.helper.SkipExpressionUtil; +import org.activiti.engine.impl.context.Context; +import org.apache.commons.lang3.StringUtils; + +import com.fasterxml.jackson.databind.node.ObjectNode; /** * ActivityBehavior that evaluates an expression when executed. Optionally, it sets the result of the expression as a variable on the execution. @@ -33,11 +38,13 @@ public class ServiceTaskExpressionActivityBehavior extends TaskActivityBehavior private static final long serialVersionUID = 1L; + 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; @@ -48,6 +55,17 @@ public class ServiceTaskExpressionActivityBehavior extends TaskActivityBehavior try { boolean isSkipExpressionEnabled = SkipExpressionUtil.isSkipExpressionEnabled(execution, skipExpression); if (!isSkipExpressionEnabled || (isSkipExpressionEnabled && !SkipExpressionUtil.shouldSkipFlowElement(execution, 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); diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/UserTaskActivityBehavior.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/UserTaskActivityBehavior.java index 45337884d7..1dc07f6580 100755 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/UserTaskActivityBehavior.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/UserTaskActivityBehavior.java @@ -12,6 +12,7 @@ */ package org.activiti.engine.impl.bpmn.behavior; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; @@ -21,6 +22,7 @@ import java.util.List; import org.activiti.bpmn.model.UserTask; import org.activiti.engine.ActivitiException; import org.activiti.engine.ActivitiIllegalArgumentException; +import org.activiti.engine.DynamicBpmnConstants; import org.activiti.engine.delegate.DelegateExecution; import org.activiti.engine.delegate.Expression; import org.activiti.engine.delegate.TaskListener; @@ -39,6 +41,9 @@ import org.apache.commons.lang3.StringUtils; 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. * @@ -62,31 +67,71 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior { TaskEntity task = Context.getCommandContext().getTaskEntityManager().createAndInsert(execution); task.setExecution((ExecutionEntity) execution); task.setTaskDefinitionKey(userTask.getId()); + + String activeTaskName = null; + String activeTaskDescription = null; + String activeTaskDueDate = null; + String activeTaskPriority = null; + String activeTaskCategory = null; + String activeTaskFormKey = null; + String activeTaskSkipExpression = null; + String activeTaskAssignee = null; + String activeTaskOwner = null; + List activeTaskCandidateUsers = null; + List activeTaskCandidateGroups = null; + + if (Context.getProcessEngineConfiguration().isEnableProcessDefinitionInfoCache()) { + ObjectNode taskElementProperties = Context.getBpmnOverrideElementProperties(userTask.getId(), execution.getProcessDefinitionId()); + activeTaskName = getActiveValue(userTask.getName(), DynamicBpmnConstants.USER_TASK_NAME, taskElementProperties); + activeTaskDescription = getActiveValue(userTask.getDocumentation(), DynamicBpmnConstants.USER_TASK_DESCRIPTION, taskElementProperties); + activeTaskDueDate = getActiveValue(userTask.getDueDate(), DynamicBpmnConstants.USER_TASK_DUEDATE, taskElementProperties); + activeTaskPriority = getActiveValue(userTask.getPriority(), DynamicBpmnConstants.USER_TASK_PRIORITY, taskElementProperties); + activeTaskCategory = getActiveValue(userTask.getCategory(), DynamicBpmnConstants.USER_TASK_CATEGORY, taskElementProperties); + activeTaskFormKey = getActiveValue(userTask.getFormKey(), DynamicBpmnConstants.USER_TASK_FORM_KEY, taskElementProperties); + activeTaskSkipExpression = getActiveValue(userTask.getSkipExpression(), DynamicBpmnConstants.TASK_SKIP_EXPRESSION, taskElementProperties); + activeTaskAssignee = getActiveValue(userTask.getAssignee(), DynamicBpmnConstants.USER_TASK_ASSIGNEE, taskElementProperties); + activeTaskOwner = getActiveValue(userTask.getOwner(), DynamicBpmnConstants.USER_TASK_OWNER, taskElementProperties); + activeTaskCandidateUsers = getActiveValueList(userTask.getCandidateUsers(), DynamicBpmnConstants.USER_TASK_CANDIDATE_USERS, taskElementProperties); + activeTaskCandidateGroups = getActiveValueList(userTask.getCandidateGroups(), DynamicBpmnConstants.USER_TASK_CANDIDATE_GROUPS, taskElementProperties); + + } else { + activeTaskName = userTask.getName(); + activeTaskDescription = userTask.getDocumentation(); + activeTaskDueDate = userTask.getDueDate(); + activeTaskPriority = userTask.getPriority(); + activeTaskCategory = userTask.getCategory(); + activeTaskFormKey = userTask.getFormKey(); + activeTaskSkipExpression = userTask.getSkipExpression(); + activeTaskAssignee = userTask.getAssignee(); + activeTaskOwner = userTask.getOwner(); + activeTaskCandidateUsers = userTask.getCandidateUsers(); + activeTaskCandidateGroups = userTask.getCandidateGroups(); + } - if (StringUtils.isNotEmpty(userTask.getName())) { + if (StringUtils.isNotEmpty(activeTaskName)) { String name = null; try { - name = (String) expressionManager.createExpression(userTask.getName()).getValue(execution); + name = (String) expressionManager.createExpression(activeTaskName).getValue(execution); } catch (ActivitiException e) { - name = userTask.getName(); + name = activeTaskName; LOGGER.warn("property not found in task name expression " + e.getMessage()); } task.setName(name); } - if (StringUtils.isNotEmpty(userTask.getDocumentation())) { + if (StringUtils.isNotEmpty(activeTaskDescription)) { String description = null; try { - description = (String) expressionManager.createExpression(userTask.getDocumentation()).getValue(execution); + description = (String) expressionManager.createExpression(activeTaskDescription).getValue(execution); } catch (ActivitiException e) { - description = userTask.getDocumentation(); + description = activeTaskDescription; LOGGER.warn("property not found in task description expression " + e.getMessage()); } task.setDescription(description); } - if (StringUtils.isNotEmpty(userTask.getDueDate())) { - Object dueDate = expressionManager.createExpression(userTask.getDueDate()).getValue(execution); + if (StringUtils.isNotEmpty(activeTaskDueDate)) { + Object dueDate = expressionManager.createExpression(activeTaskDueDate).getValue(execution); if (dueDate != null) { if (dueDate instanceof Date) { task.setDueDate((Date) dueDate); @@ -94,13 +139,13 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior { BusinessCalendar businessCalendar = Context.getProcessEngineConfiguration().getBusinessCalendarManager().getBusinessCalendar(DueDateBusinessCalendar.NAME); task.setDueDate(businessCalendar.resolveDuedate((String) dueDate)); } else { - throw new ActivitiIllegalArgumentException("Due date expression does not resolve to a Date or Date string: " + userTask.getDueDate()); + throw new ActivitiIllegalArgumentException("Due date expression does not resolve to a Date or Date string: " + activeTaskDueDate); } } } - if (StringUtils.isNotEmpty(userTask.getPriority())) { - final Object priority = expressionManager.createExpression(userTask.getPriority()).getValue(execution); + if (StringUtils.isNotEmpty(activeTaskPriority)) { + final Object priority = expressionManager.createExpression(activeTaskPriority).getValue(execution); if (priority != null) { if (priority instanceof String) { try { @@ -111,34 +156,34 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior { } else if (priority instanceof Number) { task.setPriority(((Number) priority).intValue()); } else { - throw new ActivitiIllegalArgumentException("Priority expression does not resolve to a number: " + userTask.getPriority()); + throw new ActivitiIllegalArgumentException("Priority expression does not resolve to a number: " + activeTaskPriority); } } } - if (StringUtils.isNotEmpty(userTask.getCategory())) { - final Object category = expressionManager.createExpression(userTask.getCategory()).getValue(execution); + if (StringUtils.isNotEmpty(activeTaskCategory)) { + final Object category = expressionManager.createExpression(activeTaskCategory).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: " + userTask.getCategory()); + throw new ActivitiIllegalArgumentException("Category expression does not resolve to a string: " + activeTaskCategory); } } } - if (StringUtils.isNotEmpty(userTask.getFormKey())) { - final Object formKey = expressionManager.createExpression(userTask.getFormKey()).getValue(execution); + if (StringUtils.isNotEmpty(activeTaskFormKey)) { + final Object formKey = expressionManager.createExpression(activeTaskFormKey).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: " + userTask.getFormKey()); + throw new ActivitiIllegalArgumentException("FormKey expression does not resolve to a string: " + activeTaskFormKey); } } } - handleAssignments(task, execution); + handleAssignments(activeTaskAssignee, activeTaskOwner, activeTaskCandidateUsers, activeTaskCandidateGroups, task, execution); // All properties set, now firing 'create' events if (Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) { @@ -148,8 +193,8 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior { Context.getCommandContext().getTaskEntityManager().update(task); Context.getCommandContext().getTaskEntityManager().fireTaskListenerEvent(task, TaskListener.EVENTNAME_CREATE); - if (StringUtils.isNotEmpty(userTask.getSkipExpression())) { - Expression skipExpression = expressionManager.createExpression(userTask.getSkipExpression()); + if (StringUtils.isNotEmpty(activeTaskSkipExpression)) { + Expression skipExpression = expressionManager.createExpression(activeTaskSkipExpression); if (SkipExpressionUtil.isSkipExpressionEnabled(execution, skipExpression) && SkipExpressionUtil.shouldSkipFlowElement(execution, skipExpression)) { CommandContext commandContext = Context.getCommandContext(); commandContext.getTaskEntityManager().deleteTask(task, TaskEntity.DELETE_REASON_COMPLETED, false, false); @@ -172,10 +217,11 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior { } @SuppressWarnings({ "unchecked", "rawtypes" }) - protected void handleAssignments(TaskEntity task, DelegateExecution execution) { + protected void handleAssignments(String assignee, String owner, List candidateUsers, + List candidateGroups, TaskEntity task, DelegateExecution execution) { - if (StringUtils.isNotEmpty(userTask.getAssignee())) { - Object assigneeExpressionValue = expressionManager.createExpression(userTask.getAssignee()).getValue(execution); + if (StringUtils.isNotEmpty(assignee)) { + Object assigneeExpressionValue = expressionManager.createExpression(assignee).getValue(execution); String assigneeValue = null; if (assigneeExpressionValue != null) { assigneeValue = assigneeExpressionValue.toString(); @@ -184,8 +230,8 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior { Context.getCommandContext().getTaskEntityManager().update(task); } - if (StringUtils.isNotEmpty(userTask.getOwner())) { - Object ownerExpressionValue = expressionManager.createExpression(userTask.getOwner()).getValue(execution); + if (StringUtils.isNotEmpty(owner)) { + Object ownerExpressionValue = expressionManager.createExpression(owner).getValue(execution); String ownerValue = null; if (ownerExpressionValue != null) { ownerValue = ownerExpressionValue.toString(); @@ -194,8 +240,8 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior { Context.getCommandContext().getTaskEntityManager().update(task); } - if (userTask.getCandidateGroups() != null && !userTask.getCandidateGroups().isEmpty()) { - for (String candidateGroup : userTask.getCandidateGroups()) { + if (candidateGroups != null && !candidateGroups.isEmpty()) { + for (String candidateGroup : candidateGroups) { Expression groupIdExpr = expressionManager.createExpression(candidateGroup); Object value = groupIdExpr.getValue(execution); if (value instanceof String) { @@ -209,8 +255,8 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior { } } - if (userTask.getCandidateUsers() != null && !userTask.getCandidateUsers().isEmpty()) { - for (String candidateUser : userTask.getCandidateUsers()) { + if (candidateUsers != null && !candidateUsers.isEmpty()) { + for (String candidateUser : candidateUsers) { Expression userIdExpr = expressionManager.createExpression(candidateUser); Object value = userIdExpr.getValue(execution); if (value instanceof String) { @@ -287,4 +333,36 @@ public class UserTaskActivityBehavior extends TaskActivityBehavior { return Arrays.asList(str.split("[\\s]*,[\\s]*")); } + protected String getActiveValue(String originalValue, String propertyName, ObjectNode taskElementProperties) { + String activeValue = originalValue; + if (taskElementProperties != null) { + JsonNode overrideValueNode = taskElementProperties.get(propertyName); + if (overrideValueNode != null) { + if (overrideValueNode.isNull()) { + activeValue = null; + } else { + activeValue = overrideValueNode.asText(); + } + } + } + return activeValue; + } + + protected List getActiveValueList(List originalValues, String propertyName, ObjectNode taskElementProperties) { + List 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 { + activeValues = new ArrayList(); + for (JsonNode valueNode : overrideValuesNode) { + activeValues.add(valueNode.asText()); + } + } + } + } + return activeValues; + } } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/deployer/BpmnDeployer.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/deployer/BpmnDeployer.java index a0a77dc04b..ad93d6b307 100755 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/deployer/BpmnDeployer.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/deployer/BpmnDeployer.java @@ -49,7 +49,9 @@ import org.activiti.engine.impl.interceptor.CommandContext; import org.activiti.engine.impl.jobexecutor.TimerEventHandler; import org.activiti.engine.impl.jobexecutor.TimerStartEventJobHandler; import org.activiti.engine.impl.persistence.deploy.Deployer; +import org.activiti.engine.impl.persistence.deploy.DeploymentManager; import org.activiti.engine.impl.persistence.deploy.ProcessDefinitionCacheEntry; +import org.activiti.engine.impl.persistence.deploy.ProcessDefinitionInfoCacheObject; import org.activiti.engine.impl.persistence.entity.DeploymentEntity; import org.activiti.engine.impl.persistence.entity.EventSubscriptionEntity; import org.activiti.engine.impl.persistence.entity.EventSubscriptionEntityManager; @@ -57,6 +59,8 @@ import org.activiti.engine.impl.persistence.entity.IdentityLinkEntity; import org.activiti.engine.impl.persistence.entity.MessageEventSubscriptionEntity; import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityManager; +import org.activiti.engine.impl.persistence.entity.ProcessDefinitionInfoEntity; +import org.activiti.engine.impl.persistence.entity.ProcessDefinitionInfoEntityManager; import org.activiti.engine.impl.persistence.entity.ResourceEntity; import org.activiti.engine.impl.persistence.entity.ResourceEntityManager; import org.activiti.engine.impl.persistence.entity.SignalEventSubscriptionEntity; @@ -69,6 +73,9 @@ import org.apache.commons.collections.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; + /** * @author Joram Barrez * @author Tijs Rademakers @@ -256,13 +263,54 @@ public class BpmnDeployer implements Deployer { // Add to cache ProcessDefinitionCacheEntry cacheEntry = new ProcessDefinitionCacheEntry(processDefinition, bpmnModels.get(processDefinition.getKey()), processModels.get(processDefinition.getKey())); processEngineConfiguration.getDeploymentManager().getProcessDefinitionCache().add(processDefinition.getId(), cacheEntry); - + 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 timers) { + protected void scheduleTimers(List timers) { for (TimerEntity timer : timers) { Context.getCommandContext().getJobEntityManager().schedule(timer); } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java index 0f108641ad..260eb9d6ed 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java @@ -21,6 +21,7 @@ import java.util.List; import org.activiti.bpmn.model.MapExceptionEntry; import org.activiti.engine.ActivitiException; import org.activiti.engine.ActivitiIllegalArgumentException; +import org.activiti.engine.DynamicBpmnConstants; import org.activiti.engine.delegate.BpmnError; import org.activiti.engine.delegate.DelegateExecution; import org.activiti.engine.delegate.DelegateTask; @@ -39,6 +40,9 @@ import org.activiti.engine.impl.delegate.invocation.ExecutionListenerInvocation; import org.activiti.engine.impl.delegate.invocation.TaskListenerInvocation; import org.activiti.engine.impl.persistence.entity.ExecutionEntity; import org.activiti.engine.impl.util.ReflectUtil; +import org.apache.commons.lang3.StringUtils; + +import com.fasterxml.jackson.databind.node.ObjectNode; /** * Helper class for bpmn constructs that allow class delegation. @@ -53,6 +57,7 @@ public class ClassDelegate extends AbstractBpmnActivityBehavior implements TaskL private static final long serialVersionUID = 1L; + protected String serviceTaskId; protected String className; protected List fieldDeclarations; protected ExecutionListener executionListenerInstance; @@ -68,10 +73,10 @@ public class ClassDelegate extends AbstractBpmnActivityBehavior implements TaskL } - public ClassDelegate(String className, List fieldDeclarations, Expression skipExpression, List mapExceptions) { + public ClassDelegate(String id, String className, List fieldDeclarations, Expression skipExpression, List mapExceptions) { this(className, fieldDeclarations, skipExpression); + this.serviceTaskId = id; this.mapExceptions = mapExceptions; - } public ClassDelegate(String className, List fieldDeclarations) { @@ -131,6 +136,17 @@ public class ClassDelegate extends AbstractBpmnActivityBehavior implements TaskL boolean isSkipExpressionEnabled = SkipExpressionUtil.isSkipExpressionEnabled(execution, skipExpression); if (!isSkipExpressionEnabled || (isSkipExpressionEnabled && !SkipExpressionUtil.shouldSkipFlowElement(execution, 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(execution); } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/parser/factory/DefaultActivityBehaviorFactory.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/parser/factory/DefaultActivityBehaviorFactory.java index f757a96f43..e95ad677b7 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/parser/factory/DefaultActivityBehaviorFactory.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/parser/factory/DefaultActivityBehaviorFactory.java @@ -137,7 +137,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) { @@ -148,7 +149,8 @@ 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) { @@ -159,7 +161,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) { diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/cfg/ProcessEngineConfigurationImpl.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/cfg/ProcessEngineConfigurationImpl.java index ab84a27bf4..39e4b5ecfd 100755 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/cfg/ProcessEngineConfigurationImpl.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/cfg/ProcessEngineConfigurationImpl.java @@ -35,6 +35,7 @@ import javax.naming.InitialContext; import javax.sql.DataSource; import org.activiti.engine.ActivitiException; +import org.activiti.engine.DynamicBpmnService; import org.activiti.engine.FormService; import org.activiti.engine.HistoryService; import org.activiti.engine.IdentityService; @@ -53,6 +54,7 @@ import org.activiti.engine.delegate.event.ActivitiEventListener; import org.activiti.engine.delegate.event.ActivitiEventType; import org.activiti.engine.delegate.event.impl.ActivitiEventDispatcherImpl; import org.activiti.engine.form.AbstractFormType; +import org.activiti.engine.impl.DynamicBpmnServiceImpl; import org.activiti.engine.impl.FormServiceImpl; import org.activiti.engine.impl.HistoryServiceImpl; import org.activiti.engine.impl.IdentityServiceImpl; @@ -160,6 +162,7 @@ import org.activiti.engine.impl.persistence.deploy.Deployer; import org.activiti.engine.impl.persistence.deploy.DeploymentCache; import org.activiti.engine.impl.persistence.deploy.DeploymentManager; import org.activiti.engine.impl.persistence.deploy.ProcessDefinitionCacheEntry; +import org.activiti.engine.impl.persistence.deploy.ProcessDefinitionInfoCache; import org.activiti.engine.impl.persistence.entity.AttachmentEntityManager; import org.activiti.engine.impl.persistence.entity.AttachmentEntityManagerImpl; import org.activiti.engine.impl.persistence.entity.ByteArrayEntityManager; @@ -200,6 +203,8 @@ import org.activiti.engine.impl.persistence.entity.ModelEntityManager; import org.activiti.engine.impl.persistence.entity.ModelEntityManagerImpl; import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityManager; import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityManagerImpl; +import org.activiti.engine.impl.persistence.entity.ProcessDefinitionInfoEntityManager; +import org.activiti.engine.impl.persistence.entity.ProcessDefinitionInfoEntityManagerImpl; import org.activiti.engine.impl.persistence.entity.PropertyEntityManager; import org.activiti.engine.impl.persistence.entity.PropertyEntityManagerImpl; import org.activiti.engine.impl.persistence.entity.ResourceEntityManager; @@ -232,6 +237,7 @@ import org.activiti.engine.impl.persistence.entity.data.JobDataManager; import org.activiti.engine.impl.persistence.entity.data.MembershipDataManager; import org.activiti.engine.impl.persistence.entity.data.ModelDataManager; import org.activiti.engine.impl.persistence.entity.data.ProcessDefinitionDataManager; +import org.activiti.engine.impl.persistence.entity.data.ProcessDefinitionInfoDataManager; import org.activiti.engine.impl.persistence.entity.data.PropertyDataManager; import org.activiti.engine.impl.persistence.entity.data.ResourceDataManager; import org.activiti.engine.impl.persistence.entity.data.TaskDataManager; @@ -257,6 +263,7 @@ import org.activiti.engine.impl.persistence.entity.data.impl.MybatisJobDataManag import org.activiti.engine.impl.persistence.entity.data.impl.MybatisMembershipDataManager; import org.activiti.engine.impl.persistence.entity.data.impl.MybatisModelDataManager; import org.activiti.engine.impl.persistence.entity.data.impl.MybatisProcessDefinitionDataManager; +import org.activiti.engine.impl.persistence.entity.data.impl.MybatisProcessDefinitionInfoDataManager; import org.activiti.engine.impl.persistence.entity.data.impl.MybatisPropertyDataManager; import org.activiti.engine.impl.persistence.entity.data.impl.MybatisResourceDataManager; import org.activiti.engine.impl.persistence.entity.data.impl.MybatisTaskDataManager; @@ -312,6 +319,8 @@ import org.apache.ibatis.type.JdbcType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.ObjectMapper; + /** * @author Tom Baeyens * @author Joram Barrez @@ -336,6 +345,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 //////////////////////////////////////////////////////// @@ -377,6 +387,7 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig protected MembershipDataManager membershipDataManager; protected ModelDataManager modelDataManager; protected ProcessDefinitionDataManager processDefinitionDataManager; + protected ProcessDefinitionInfoDataManager processDefinitionInfoDataManager; protected PropertyDataManager propertyDataManager; protected ResourceDataManager resourceDataManager; protected TaskDataManager taskDataManager; @@ -406,6 +417,7 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig protected MembershipEntityManager membershipEntityManager; protected ModelEntityManager modelEntityManager; protected ProcessDefinitionEntityManager processDefinitionEntityManager; + protected ProcessDefinitionInfoEntityManager processDefinitionInfoEntityManager; protected PropertyEntityManager propertyEntityManager; protected ResourceEntityManager resourceEntityManager; protected TableDataManager tableDataManager; @@ -440,6 +452,9 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig protected int processDefinitionCacheLimit = -1; // By default, no limit protected DeploymentCache processDefinitionCache; + + protected int processDefinitionInfoCacheLimit = -1; // By default, no limit + protected ProcessDefinitionInfoCache processDefinitionInfoCache; protected int knowledgeBaseCacheLimit = -1; protected DeploymentCache knowledgeBaseCache; @@ -557,6 +572,8 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig */ protected int maxNrOfStatementsInBulkInsert = 100; + protected ObjectMapper objectMapper = new ObjectMapper(); + /** * Flag that can be set to configure or nota relational database is used. * This is useful for custom implementations that do not use relational databases at all. @@ -751,6 +768,7 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig initService(taskService); initService(formService); initService(managementService); + initService(dynamicBpmnService); } protected void initService(Object service) { @@ -1013,6 +1031,7 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig membershipDataManager = new MybatisMembershipDataManager(this); modelDataManager = new MybatisModelDataManager(this); processDefinitionDataManager = new MybatisProcessDefinitionDataManager(this); + processDefinitionInfoDataManager = new MybatisProcessDefinitionInfoDataManager(this); propertyDataManager = new MybatisPropertyDataManager(this); resourceDataManager = new MybatisResourceDataManager(this); taskDataManager = new MybatisTaskDataManager(this); @@ -1043,6 +1062,7 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig membershipEntityManager = new MembershipEntityManagerImpl(this, membershipDataManager); modelEntityManager = new ModelEntityManagerImpl(this, modelDataManager); processDefinitionEntityManager = new ProcessDefinitionEntityManagerImpl(this, processDefinitionDataManager); + processDefinitionInfoEntityManager = new ProcessDefinitionInfoEntityManagerImpl(this, processDefinitionInfoDataManager); propertyEntityManager = new PropertyEntityManagerImpl(this, propertyDataManager); resourceEntityManager = new ResourceEntityManagerImpl(this, resourceDataManager); tableDataManager = new TableDataManagerImpl(this); @@ -1204,6 +1224,14 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig processDefinitionCache = new DefaultDeploymentCache(processDefinitionCacheLimit); } } + + 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) { @@ -1215,6 +1243,7 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig } deploymentManager.setProcessDefinitionCache(processDefinitionCache); + deploymentManager.setProcessDefinitionInfoCache(processDefinitionInfoCache); deploymentManager.setKnowledgeBaseCache(knowledgeBaseCache); } } @@ -1511,8 +1540,8 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig variableTypes.addType(new DateType()); variableTypes.addType(new DoubleType()); variableTypes.addType(new UUIDType()); - variableTypes.addType(new JsonType(maxLengthStringVariableType)); - variableTypes.addType(new LongJsonType(maxLengthStringVariableType + 1)); + variableTypes.addType(new JsonType(maxLengthStringVariableType, objectMapper)); + variableTypes.addType(new LongJsonType(maxLengthStringVariableType + 1, objectMapper)); variableTypes.addType(new ByteArrayType()); variableTypes.addType(new SerializableType()); variableTypes.addType(new CustomObjectType("item", ItemInstance.class)); @@ -1682,10 +1711,9 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig protected void initDatabaseEventLogging() { if (enableDatabaseEventLogging) { - // Database event logging uses the default logging mechanism and - // adds + // Database event logging uses the default logging mechanism and adds // a specific event listener to the list of event listeners - getEventDispatcher().addEventListener(new EventLogger(clock)); + getEventDispatcher().addEventListener(new EventLogger(clock, objectMapper)); } } @@ -1835,6 +1863,15 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig this.managementService = managementService; return this; } + + public DynamicBpmnService getDynamicBpmnService() { + return dynamicBpmnService; + } + + public ProcessEngineConfigurationImpl setDynamicBpmnService(DynamicBpmnService dynamicBpmnService) { + this.dynamicBpmnService = dynamicBpmnService; + return this; + } public ProcessEngineConfiguration getProcessEngineConfiguration() { return this; @@ -2560,6 +2597,14 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig public void setProcessDefinitionEntityManager(ProcessDefinitionEntityManager processDefinitionEntityManager) { this.processDefinitionEntityManager = processDefinitionEntityManager; } + + public ProcessDefinitionInfoEntityManager getProcessDefinitionInfoEntityManager() { + return processDefinitionInfoEntityManager; + } + + public void setProcessDefinitionInfoEntityManager(ProcessDefinitionInfoEntityManager processDefinitionInfoEntityManager) { + this.processDefinitionInfoEntityManager = processDefinitionInfoEntityManager; + } public PropertyEntityManager getPropertyEntityManager() { return propertyEntityManager; @@ -2639,6 +2684,9 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig } } + public ObjectMapper getObjectMapper() { + return objectMapper; + } // Activiti 5 diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/cmd/GetProcessDefinitionInfoCmd.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/cmd/GetProcessDefinitionInfoCmd.java new file mode 100644 index 0000000000..92f89a87f6 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/cmd/GetProcessDefinitionInfoCmd.java @@ -0,0 +1,56 @@ +/* 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.activiti.engine.impl.cmd; + +import java.io.Serializable; + +import org.activiti.engine.ActivitiIllegalArgumentException; +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 com.fasterxml.jackson.databind.node.ObjectNode; + + +/** + * @author Tijs Rademakers + */ +public class GetProcessDefinitionInfoCmd implements Command, 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 diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/cmd/SaveProcessDefinitionInfoCmd.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/cmd/SaveProcessDefinitionInfoCmd.java new file mode 100644 index 0000000000..cbe7b6bcdd --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/cmd/SaveProcessDefinitionInfoCmd.java @@ -0,0 +1,74 @@ +/* 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.activiti.engine.impl.cmd; + +import java.io.Serializable; + +import org.activiti.engine.ActivitiException; +import org.activiti.engine.ActivitiIllegalArgumentException; +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 com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.databind.node.ObjectNode; + + +/** + * @author Tijs Rademakers + */ +public class SaveProcessDefinitionInfoCmd implements Command, 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 = definitionInfoEntityManager.create(); + 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 diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/context/Context.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/context/Context.java index 85137b55ef..da6f4cef94 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/context/Context.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/context/Context.java @@ -13,6 +13,8 @@ package org.activiti.engine.impl.context; +import java.util.HashMap; +import java.util.Map; import java.util.Stack; import org.activiti.engine.compatibility.Activiti5CompatibilityHandler; @@ -20,8 +22,11 @@ import org.activiti.engine.impl.agenda.Agenda; import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl; import org.activiti.engine.impl.interceptor.CommandContext; import org.activiti.engine.impl.jobexecutor.JobExecutorContext; +import org.activiti.engine.impl.persistence.deploy.ProcessDefinitionInfoCacheObject; import org.activiti.engine.impl.persistence.entity.ExecutionEntity; +import com.fasterxml.jackson.databind.node.ObjectNode; + /** * @author Tom Baeyens * @author Daniel Meyer @@ -33,6 +38,7 @@ public class Context { protected static ThreadLocal> processEngineConfigurationStackThreadLocal = new ThreadLocal>(); protected static ThreadLocal> executionContextStackThreadLocal = new ThreadLocal>(); protected static ThreadLocal jobExecutorContextThreadLocal = new ThreadLocal(); + protected static ThreadLocal> bpmnOverrideContextThreadLocal = new ThreadLocal>(); protected static ThreadLocal activiti5CompatibilityHandlerThreadLocal = new ThreadLocal(); protected static ThreadLocal fallbackActiviti5CompatibilityHandlerThreadLocal = new ThreadLocal(); @@ -110,6 +116,59 @@ public class Context { 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 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 getBpmnOverrideContext() { + Map bpmnOverrideMap = bpmnOverrideContextThreadLocal.get(); + if (bpmnOverrideMap == null) { + bpmnOverrideMap = new HashMap(); + } + return bpmnOverrideMap; + } + + protected static void addBpmnOverrideElement(String id, ObjectNode infoNode) { + Map bpmnOverrideMap = bpmnOverrideContextThreadLocal.get(); + if (bpmnOverrideMap == null) { + bpmnOverrideMap = new HashMap(); + bpmnOverrideContextThreadLocal.set(bpmnOverrideMap); + } + bpmnOverrideMap.put(id, infoNode); + } + public static Activiti5CompatibilityHandler getActiviti5CompatibilityHandler() { return activiti5CompatibilityHandlerThreadLocal.get(); } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/db/DbSqlSession.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/db/DbSqlSession.java index 85f8a44ab7..92fabcad2c 100755 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/db/DbSqlSession.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/db/DbSqlSession.java @@ -114,6 +114,7 @@ public class DbSqlSession implements Session { ACTIVITI_VERSIONS.add(new ActivitiVersion("5.17.0.1")); ACTIVITI_VERSIONS.add(new ActivitiVersion("5.17.0.2")); ACTIVITI_VERSIONS.add(new ActivitiVersion("5.18.0.0")); + ACTIVITI_VERSIONS.add(new ActivitiVersion("5.18.0.1")); // This is the latest version of the 5 branch. It's a 'virtual' version cause it doesn't exist, but it is // there to make sure all previous version can upgrade to the 6 version correctly. diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/event/logger/EventLogger.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/event/logger/EventLogger.java index 73dba0ae71..196b8a1a9c 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/event/logger/EventLogger.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/event/logger/EventLogger.java @@ -53,9 +53,9 @@ public class EventLogger implements ActivitiEventListener { // Listeners for new events protected List listeners; - public EventLogger(Clock clock) { + public EventLogger(Clock clock, ObjectMapper objectMapper) { this.clock = clock; - this.objectMapper = new ObjectMapper(); + this.objectMapper = objectMapper; // Initialization of all event handlers diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/event/logger/handler/AbstractTaskEventHandler.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/event/logger/handler/AbstractTaskEventHandler.java index 80a5081c73..08219fc256 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/event/logger/handler/AbstractTaskEventHandler.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/event/logger/handler/AbstractTaskEventHandler.java @@ -29,10 +29,7 @@ public abstract class AbstractTaskEventHandler extends AbstractDatabaseEventLogg putInMapIfNotNull(data, Fields.EXECUTION_ID, task.getExecutionId()); if (task.getTenantId() != null && !ProcessEngineConfigurationImpl.NO_TENANT_ID.equals(task.getTenantId())) { - putInMapIfNotNull(data, Fields.TENANT_ID, task.getTenantId()); // Important - // for - // standalone - // tasks + putInMapIfNotNull(data, Fields.TENANT_ID, task.getTenantId()); // Important for standalone tasks } return data; } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/history/DefaultHistoryManager.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/history/DefaultHistoryManager.java index 072e9c261f..9ac44cfff8 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/history/DefaultHistoryManager.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/history/DefaultHistoryManager.java @@ -22,7 +22,6 @@ import org.activiti.bpmn.model.FlowElement; import org.activiti.bpmn.model.FlowNode; import org.activiti.engine.impl.cfg.IdGenerator; import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl; -import org.activiti.engine.impl.form.TaskFormHandler; import org.activiti.engine.impl.identity.Authentication; import org.activiti.engine.impl.persistence.AbstractManager; import org.activiti.engine.impl.persistence.cache.EntityCache; @@ -37,7 +36,6 @@ import org.activiti.engine.impl.persistence.entity.HistoricVariableInstanceEntit import org.activiti.engine.impl.persistence.entity.IdentityLinkEntity; import org.activiti.engine.impl.persistence.entity.TaskEntity; import org.activiti.engine.impl.persistence.entity.VariableInstanceEntity; -import org.activiti.engine.impl.util.FormHandlerUtil; import org.activiti.engine.task.Event; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -606,21 +604,6 @@ public class DefaultHistoryManager extends AbstractManager implements HistoryMan HistoricTaskInstanceEntity historicTaskInstance = getHistoricTaskInstanceEntityManager().findById(taskId); if (historicTaskInstance != null) { historicTaskInstance.setTaskDefinitionKey(taskDefinitionKey); - - if (taskDefinitionKey != null) { - TaskEntity taskEntity = getTaskEntityManager().findById(taskId); - - TaskFormHandler taskFormHandler = FormHandlerUtil.getTaskFormHandlder(taskEntity); - if (taskFormHandler != null) { - if (taskFormHandler.getFormKey() != null) { - Object formValue = taskFormHandler.getFormKey().getValue(taskEntity.getExecution()); - if (formValue != null) { - historicTaskInstance.setFormKey(formValue.toString()); - } - } - } - - } } } } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/interceptor/CommandContext.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/interceptor/CommandContext.java index 701dd38f44..d20a0b2cab 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/interceptor/CommandContext.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/interceptor/CommandContext.java @@ -52,6 +52,7 @@ import org.activiti.engine.impl.persistence.entity.JobEntityManager; import org.activiti.engine.impl.persistence.entity.MembershipEntityManager; import org.activiti.engine.impl.persistence.entity.ModelEntityManager; import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityManager; +import org.activiti.engine.impl.persistence.entity.ProcessDefinitionInfoEntityManager; import org.activiti.engine.impl.persistence.entity.PropertyEntityManager; import org.activiti.engine.impl.persistence.entity.ResourceEntityManager; import org.activiti.engine.impl.persistence.entity.TableDataManager; @@ -273,6 +274,10 @@ public class CommandContext { public ModelEntityManager getModelEntityManager() { return processEngineConfiguration.getModelEntityManager(); } + + public ProcessDefinitionInfoEntityManager getProcessDefinitionInfoEntityManager() { + return processEngineConfiguration.getProcessDefinitionInfoEntityManager(); + } public ExecutionEntityManager getExecutionEntityManager() { return processEngineConfiguration.getExecutionEntityManager(); diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/interceptor/CommandContextInterceptor.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/interceptor/CommandContextInterceptor.java index 382f8a173a..80c844de42 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/interceptor/CommandContextInterceptor.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/interceptor/CommandContextInterceptor.java @@ -72,6 +72,7 @@ public class CommandContextInterceptor extends AbstractCommandInterceptor { // Pop from stack Context.removeCommandContext(); Context.removeProcessEngineConfiguration(); + Context.removeBpmnOverrideContext(); Context.removeActiviti5CompatibilityHandler(); } } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/AbstractManager.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/AbstractManager.java index 1d4409e446..7e84cedb05 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/AbstractManager.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/AbstractManager.java @@ -40,6 +40,7 @@ import org.activiti.engine.impl.persistence.entity.JobEntityManager; import org.activiti.engine.impl.persistence.entity.MembershipEntityManager; import org.activiti.engine.impl.persistence.entity.ModelEntityManager; import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityManager; +import org.activiti.engine.impl.persistence.entity.ProcessDefinitionInfoEntityManager; import org.activiti.engine.impl.persistence.entity.ResourceEntityManager; import org.activiti.engine.impl.persistence.entity.TaskEntityManager; import org.activiti.engine.impl.persistence.entity.UserEntityManager; @@ -113,6 +114,10 @@ public abstract class AbstractManager { protected ProcessDefinitionEntityManager getProcessDefinitionEntityManager() { return getProcessEngineConfiguration().getProcessDefinitionEntityManager(); } + + protected ProcessDefinitionInfoEntityManager getProcessDefinitionInfoEntityManager() { + return getProcessEngineConfiguration().getProcessDefinitionInfoEntityManager(); + } protected ModelEntityManager getModelEntityManager() { return getProcessEngineConfiguration().getModelEntityManager(); diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/deploy/DeploymentManager.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/deploy/DeploymentManager.java index 731940157e..8eabb913df 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/deploy/DeploymentManager.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/deploy/DeploymentManager.java @@ -40,6 +40,7 @@ import org.activiti.engine.repository.ProcessDefinition; public class DeploymentManager { protected DeploymentCache processDefinitionCache; + protected ProcessDefinitionInfoCache processDefinitionInfoCache; protected DeploymentCache knowledgeBaseCache; // Needs to be object to avoid an import to Drools in this core class protected List deployers; @@ -182,6 +183,14 @@ public class DeploymentManager { public void setProcessDefinitionCache(DeploymentCache processDefinitionCache) { this.processDefinitionCache = processDefinitionCache; } + + public ProcessDefinitionInfoCache getProcessDefinitionInfoCache() { + return processDefinitionInfoCache; + } + + public void setProcessDefinitionInfoCache(ProcessDefinitionInfoCache processDefinitionInfoCache) { + this.processDefinitionInfoCache = processDefinitionInfoCache; + } public DeploymentCache getKnowledgeBaseCache() { return knowledgeBaseCache; diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/deploy/ProcessDefinitionInfoCache.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/deploy/ProcessDefinitionInfoCache.java new file mode 100644 index 0000000000..cfe05784ad --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/deploy/ProcessDefinitionInfoCache.java @@ -0,0 +1,133 @@ +/* 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.activiti.engine.impl.persistence.deploy; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.activiti.engine.ActivitiException; +import org.activiti.engine.impl.context.Context; +import org.activiti.engine.impl.interceptor.Command; +import org.activiti.engine.impl.interceptor.CommandContext; +import org.activiti.engine.impl.interceptor.CommandExecutor; +import org.activiti.engine.impl.persistence.entity.ProcessDefinitionInfoEntity; +import org.activiti.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 cache; + protected CommandExecutor commandExecutor; + + /** Cache with no limit */ + public ProcessDefinitionInfoCache(CommandExecutor commandExecutor) { + this.commandExecutor = commandExecutor; + this.cache = new HashMap(); + } + + /** 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(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 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)) { + + Command cacheCommand = new Command() { + + @Override + public ProcessDefinitionInfoCacheObject execute(CommandContext commandContext) { + return retrieveProcessDefinitionInfoCacheObject(processDefinitionId, commandContext); + } + }; + + if (Context.getCommandContext() != null) { + infoCacheObject = retrieveProcessDefinitionInfoCacheObject(processDefinitionId, Context.getCommandContext()); + } else { + infoCacheObject = commandExecutor.execute(cacheCommand); + } + } + 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(); + } + + protected ProcessDefinitionInfoCacheObject retrieveProcessDefinitionInfoCacheObject(String processDefinitionId, 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; + } + +} \ No newline at end of file diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/deploy/ProcessDefinitionInfoCacheObject.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/deploy/ProcessDefinitionInfoCacheObject.java new file mode 100644 index 0000000000..75468ecec0 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/deploy/ProcessDefinitionInfoCacheObject.java @@ -0,0 +1,49 @@ +/* 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.activiti.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 diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/DeploymentEntityManagerImpl.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/DeploymentEntityManagerImpl.java index 2f433a8fb4..dff672106f 100755 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/DeploymentEntityManagerImpl.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/DeploymentEntityManagerImpl.java @@ -99,6 +99,8 @@ public class DeploymentEntityManagerImpl extends AbstractEntityManager 0) { + return localizedName; + } else { + return name; + } } - public void setName(String name) { this.name = name; } - + + public void setLocalizedName(String name) { + this.localizedName = name; + } + public String getDescription() { - return description; + if (localizedDescription != null && localizedDescription.length() > 0) { + return localizedDescription; + } else { + return description; + } } - + public void setDescription(String description) { this.description = description; } + + public void setLocalizedDescription(String description) { + this.localizedDescription = description; + } public String getAssignee() { return assignee; diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionInfoEntity.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionInfoEntity.java new file mode 100644 index 0000000000..03c47a35a4 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionInfoEntity.java @@ -0,0 +1,34 @@ +/* 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.activiti.engine.impl.persistence.entity; + +import org.activiti.engine.impl.db.Entity; +import org.activiti.engine.impl.db.HasRevision; + +/** + * @author Tijs Rademakers + */ +public interface ProcessDefinitionInfoEntity extends Entity, HasRevision { + + String getId(); + + void setId(String id); + + String getProcessDefinitionId(); + + void setProcessDefinitionId(String processDefinitionId); + + String getInfoJsonId(); + + void setInfoJsonId(String infoJsonId); +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionInfoEntityImpl.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionInfoEntityImpl.java new file mode 100644 index 0000000000..2935ef4405 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionInfoEntityImpl.java @@ -0,0 +1,77 @@ +/* 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.activiti.engine.impl.persistence.entity; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + + +/** + * @author Tijs Rademakers + */ +public class ProcessDefinitionInfoEntityImpl implements ProcessDefinitionInfoEntity, Serializable { + + private static final long serialVersionUID = 1L; + + protected String id; + protected String processDefinitionId; + protected int revision = 1; + protected String infoJsonId; + + public Object getPersistentState() { + Map persistentState = new HashMap(); + 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 diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionInfoEntityManager.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionInfoEntityManager.java new file mode 100644 index 0000000000..eecf0b3f6f --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionInfoEntityManager.java @@ -0,0 +1,37 @@ +/* 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.activiti.engine.impl.persistence.entity; + + +/** + * @author Tijs Rademakers + */ +public interface ProcessDefinitionInfoEntityManager extends EntityManager { + + void insertProcessDefinitionInfo(ProcessDefinitionInfoEntity processDefinitionInfo); + + void updateProcessDefinitionInfo(ProcessDefinitionInfoEntity updatedProcessDefinitionInfo); + + void deleteProcessDefinitionInfo(String processDefinitionId); + + void updateInfoJson(String id, byte[] json); + + void deleteInfoJson(ProcessDefinitionInfoEntity processDefinitionInfo); + + ProcessDefinitionInfoEntity findById(String id); + + ProcessDefinitionInfoEntity findProcessDefinitionInfoByProcessDefinitionId(String processDefinitionId); + + byte[] findInfoJsonById(String infoJsonId); + +} \ No newline at end of file diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionInfoEntityManagerImpl.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionInfoEntityManagerImpl.java new file mode 100644 index 0000000000..729992d7e7 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionInfoEntityManagerImpl.java @@ -0,0 +1,85 @@ +/* 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.activiti.engine.impl.persistence.entity; + +import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.activiti.engine.impl.persistence.entity.data.DataManager; +import org.activiti.engine.impl.persistence.entity.data.ProcessDefinitionInfoDataManager; + + +/** + * @author Tijs Rademakers + */ +public class ProcessDefinitionInfoEntityManagerImpl extends + AbstractEntityManager implements ProcessDefinitionInfoEntityManager { + + protected ProcessDefinitionInfoDataManager processDefinitionInfoDataManager; + + public ProcessDefinitionInfoEntityManagerImpl(ProcessEngineConfigurationImpl processEngineConfiguration, + ProcessDefinitionInfoDataManager processDefinitionInfoDataManager) { + + super(processEngineConfiguration); + this.processDefinitionInfoDataManager = processDefinitionInfoDataManager; + } + + @Override + protected DataManager getDataManager() { + return processDefinitionInfoDataManager; + } + + public void insertProcessDefinitionInfo(ProcessDefinitionInfoEntity processDefinitionInfo) { + insert(processDefinitionInfo); + } + + public void updateProcessDefinitionInfo(ProcessDefinitionInfoEntity updatedProcessDefinitionInfo) { + update(updatedProcessDefinitionInfo, true); + } + + public void deleteProcessDefinitionInfo(String processDefinitionId) { + ProcessDefinitionInfoEntity processDefinitionInfo = findProcessDefinitionInfoByProcessDefinitionId(processDefinitionId); + if (processDefinitionInfo != null) { + delete(processDefinitionInfo); + deleteInfoJson(processDefinitionInfo); + } + } + + public void updateInfoJson(String id, byte[] json) { + ProcessDefinitionInfoEntity processDefinitionInfo = findById(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 findProcessDefinitionInfoByProcessDefinitionId(String processDefinitionId) { + return processDefinitionInfoDataManager.findProcessDefinitionInfoByProcessDefinitionId(processDefinitionId); + } + + public byte[] findInfoJsonById(String infoJsonId) { + ByteArrayRef ref = new ByteArrayRef(infoJsonId); + return ref.getBytes(); + } +} \ No newline at end of file diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/TaskEntityImpl.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/TaskEntityImpl.java index 416f61b0a3..aed1458d41 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/TaskEntityImpl.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/TaskEntityImpl.java @@ -58,7 +58,9 @@ public class TaskEntityImpl extends VariableScopeImpl implements TaskEntity, Ser protected String parentTaskId; protected String name; + protected String localizedName; protected String description; + protected String localizedDescription; protected int priority = DEFAULT_PRIORITY; protected Date createTime; // The time when the task has been created protected Date dueDate; @@ -374,11 +376,35 @@ public class TaskEntityImpl extends VariableScopeImpl implements TaskEntity, Ser } public String getName() { - return name; + if (localizedName != null && localizedName.length() > 0) { + return localizedName; + } else { + return name; + } + } + + public String getLocalizedName() { + return localizedName; + } + + public void setLocalizedName(String localizedName) { + this.localizedName = localizedName; } public String getDescription() { - return description; + if (localizedDescription != null && localizedDescription.length() > 0) { + return localizedDescription; + } else { + return description; + } + } + + public String getLocalizedDescription() { + return localizedDescription; + } + + public void setLocalizedDescription(String localizedDescription) { + this.localizedDescription = localizedDescription; } public Date getDueDate() { diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/data/ProcessDefinitionInfoDataManager.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/data/ProcessDefinitionInfoDataManager.java new file mode 100644 index 0000000000..4751ddcf82 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/data/ProcessDefinitionInfoDataManager.java @@ -0,0 +1,23 @@ +/* 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.activiti.engine.impl.persistence.entity.data; + +import org.activiti.engine.impl.persistence.entity.ProcessDefinitionInfoEntity; + +/** + * @author Tijs Rademakers + */ +public interface ProcessDefinitionInfoDataManager extends DataManager { + + ProcessDefinitionInfoEntity findProcessDefinitionInfoByProcessDefinitionId(String processDefinitionId); +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/data/impl/MybatisProcessDefinitionInfoDataManager.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/data/impl/MybatisProcessDefinitionInfoDataManager.java new file mode 100644 index 0000000000..e06ee8fd01 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/data/impl/MybatisProcessDefinitionInfoDataManager.java @@ -0,0 +1,44 @@ +/* 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.activiti.engine.impl.persistence.entity.data.impl; + +import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.activiti.engine.impl.persistence.entity.ProcessDefinitionInfoEntity; +import org.activiti.engine.impl.persistence.entity.ProcessDefinitionInfoEntityImpl; +import org.activiti.engine.impl.persistence.entity.data.AbstractDataManager; +import org.activiti.engine.impl.persistence.entity.data.ProcessDefinitionInfoDataManager; + +/** + * @author Tijs Rademakers + */ +public class MybatisProcessDefinitionInfoDataManager extends AbstractDataManager implements ProcessDefinitionInfoDataManager { + + public MybatisProcessDefinitionInfoDataManager(ProcessEngineConfigurationImpl processEngineConfiguration) { + super(processEngineConfiguration); + } + + @Override + public Class getManagedEntityClass() { + return ProcessDefinitionInfoEntityImpl.class; + } + + @Override + public ProcessDefinitionInfoEntity create() { + return new ProcessDefinitionInfoEntityImpl(); + } + + @Override + public ProcessDefinitionInfoEntity findProcessDefinitionInfoByProcessDefinitionId(String processDefinitionId) { + return (ProcessDefinitionInfoEntity) getDbSqlSession().selectOne("selectProcessDefinitionInfoByProcessDefinitionId", processDefinitionId); + } +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/test/AbstractActivitiTestCase.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/test/AbstractActivitiTestCase.java index 4f11b79e22..c9a6c651d9 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/test/AbstractActivitiTestCase.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/test/AbstractActivitiTestCase.java @@ -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; @@ -68,6 +69,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 { @@ -182,6 +184,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) { diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/variable/JsonType.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/variable/JsonType.java index 5c44d84db3..057a1d07b2 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/variable/JsonType.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/variable/JsonType.java @@ -28,9 +28,12 @@ public class JsonType implements VariableType { private static final Logger logger = LoggerFactory.getLogger(JsonType.class); protected final int maxLength; - protected ObjectMapper objectMapper = new ObjectMapper(); + protected ObjectMapper objectMapper; - public JsonType(int maxLength) {this.maxLength = maxLength;} + public JsonType(int maxLength, ObjectMapper objectMapper) { + this.maxLength = maxLength; + this.objectMapper = objectMapper; + } public String getTypeName() { return "json"; diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/variable/LongJsonType.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/variable/LongJsonType.java index a06c822365..7fca8d824e 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/variable/LongJsonType.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/variable/LongJsonType.java @@ -25,9 +25,12 @@ import com.fasterxml.jackson.databind.ObjectMapper; public class LongJsonType extends SerializableType { protected final int minLength; - protected ObjectMapper objectMapper = new ObjectMapper(); + protected ObjectMapper objectMapper; - public LongJsonType(int minLength) {this.minLength = minLength;} + public LongJsonType(int minLength, ObjectMapper objectMapper) { + this.minLength = minLength; + this.objectMapper = objectMapper; + } public String getTypeName() { return "longJson"; diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/task/Task.java b/modules/activiti-engine/src/main/java/org/activiti/engine/task/Task.java index ed6e95caf4..71ff49933d 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/task/Task.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/task/Task.java @@ -29,9 +29,15 @@ public interface Task extends TaskInfo { /** Name or title of the task. */ void setName(String name); + + /** Sets an optional localized name for the task. */ + void setLocalizedName(String name); /** Change the description of the task */ void setDescription(String description); + + /** Sets an optional localized description for the task. */ + void setLocalizedDescription(String description); /** Sets the indication of how important/urgent this task is */ void setPriority(int priority); diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/task/TaskInfoQuery.java b/modules/activiti-engine/src/main/java/org/activiti/engine/task/TaskInfoQuery.java index 8ab33501b1..690944fb8e 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/task/TaskInfoQuery.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/task/TaskInfoQuery.java @@ -488,6 +488,11 @@ public interface TaskInfoQuery, V extends TaskInfo * Include global task variables in the task query result */ T includeProcessVariables(); + + /** + * Localize task name and description to specified locale. + */ + T locale(String locale); /** * All query clauses called will be added to a single or-statement. This or-statement will be included with the other already existing clauses in the query, joined by an 'and'. diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.db2.create.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.db2.create.engine.sql index 4cd19ef1eb..a31081b8f9 100644 --- a/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.db2.create.engine.sql +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.db2.create.engine.sql @@ -195,6 +195,14 @@ create table ACT_EVT_LOG ( primary key (LOG_NR_) ); +create table ACT_PROCDEF_INFO ( + ID_ varchar(64) not null, + PROC_DEF_ID_ varchar(64) not null, + REV_ integer, + INFO_JSON_ID_ varchar(64), + primary key (ID_) +); + create index ACT_IDX_EXEC_BUSKEY on ACT_RU_EXECUTION(BUSINESS_KEY_); create index ACT_IDC_EXEC_ROOT on ACT_RU_EXECUTION(ROOT_PROC_INST_ID_); create index ACT_IDX_TASK_CREATE on ACT_RU_TASK(CREATE_TIME_); @@ -218,6 +226,7 @@ create index ACT_IDX_EXEC_PROC_INST_ID on ACT_RU_EXECUTION(PROC_INST_ID_); create index ACT_IDX_TASK_PROC_DEF_ID on ACT_RU_TASK(PROC_DEF_ID_); create index ACT_IDX_EVENT_SUBSCR_EXEC_ID on ACT_RU_EVENT_SUBSCR(EXECUTION_ID_); create index ACT_IDX_JOB_EXCEPTION_STACK_ID on ACT_RU_JOB(EXCEPTION_STACK_ID_); +create index ACT_IDX_INFO_PROCDEF on ACT_PROCDEF_INFO(PROC_DEF_ID_); alter table ACT_GE_BYTEARRAY add constraint ACT_FK_BYTEARR_DEPL @@ -274,9 +283,9 @@ alter table ACT_RU_TASK references ACT_RU_EXECUTION (ID_); alter table ACT_RU_TASK - add constraint ACT_FK_TASK_PROCDEF - foreign key (PROC_DEF_ID_) - references ACT_RE_PROCDEF (ID_); + add constraint ACT_FK_TASK_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); alter table ACT_RU_VARIABLE add constraint ACT_FK_VAR_EXE @@ -317,3 +326,17 @@ alter table ACT_RE_MODEL add constraint ACT_FK_MODEL_DEPLOYMENT foreign key (DEPLOYMENT_ID_) references ACT_RE_DEPLOYMENT (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_JSON_BA + foreign key (INFO_JSON_ID_) + references ACT_GE_BYTEARRAY (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_UNIQ_INFO_PROCDEF + unique (PROC_DEF_ID_); \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.h2.create.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.h2.create.engine.sql index 4e12d86681..c1e92271e1 100644 --- a/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.h2.create.engine.sql +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.h2.create.engine.sql @@ -194,6 +194,14 @@ create table ACT_EVT_LOG ( IS_PROCESSED_ bit default 0 ); +create table ACT_PROCDEF_INFO ( + ID_ varchar(64) not null, + PROC_DEF_ID_ varchar(64) not null, + REV_ integer, + INFO_JSON_ID_ varchar(64), + primary key (ID_) +); + create index ACT_IDX_EXEC_BUSKEY on ACT_RU_EXECUTION(BUSINESS_KEY_); create index ACT_IDC_EXEC_ROOT on ACT_RU_EXECUTION(ROOT_PROC_INST_ID_); create index ACT_IDX_TASK_CREATE on ACT_RU_TASK(CREATE_TIME_); @@ -202,6 +210,7 @@ create index ACT_IDX_IDENT_LNK_GROUP on ACT_RU_IDENTITYLINK(GROUP_ID_); create index ACT_IDX_EVENT_SUBSCR_CONFIG_ on ACT_RU_EVENT_SUBSCR(CONFIGURATION_); create index ACT_IDX_VARIABLE_TASK_ID on ACT_RU_VARIABLE(TASK_ID_); create index ACT_IDX_ATHRZ_PROCEDEF on ACT_RU_IDENTITYLINK(PROC_DEF_ID_); +create index ACT_IDX_INFO_PROCDEF on ACT_PROCDEF_INFO(PROC_DEF_ID_); alter table ACT_GE_BYTEARRAY add constraint ACT_FK_BYTEARR_DEPL @@ -301,3 +310,17 @@ alter table ACT_RE_MODEL add constraint ACT_FK_MODEL_DEPLOYMENT foreign key (DEPLOYMENT_ID_) references ACT_RE_DEPLOYMENT (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_JSON_BA + foreign key (INFO_JSON_ID_) + references ACT_GE_BYTEARRAY (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_UNIQ_INFO_PROCDEF + unique (PROC_DEF_ID_); \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.hsql.create.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.hsql.create.engine.sql index 67b1054409..6258b17536 100644 --- a/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.hsql.create.engine.sql +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.hsql.create.engine.sql @@ -194,6 +194,14 @@ create table ACT_EVT_LOG ( IS_PROCESSED_ bit default 0 ); +create table ACT_PROCDEF_INFO ( + ID_ varchar(64) not null, + PROC_DEF_ID_ varchar(64) not null, + REV_ integer, + INFO_JSON_ID_ varchar(64), + primary key (ID_) +); + create index ACT_IDX_EXEC_BUSKEY on ACT_RU_EXECUTION(BUSINESS_KEY_); create index ACT_IDX_EXE_ROOT on ACT_RU_EXECUTION(ROOT_PROC_INST_ID_); create index ACT_IDX_TASK_CREATE on ACT_RU_TASK(CREATE_TIME_); @@ -202,6 +210,7 @@ create index ACT_IDX_IDENT_LNK_GROUP on ACT_RU_IDENTITYLINK(GROUP_ID_); create index ACT_IDX_EVENT_SUBSCR_CONFIG_ on ACT_RU_EVENT_SUBSCR(CONFIGURATION_); create index ACT_IDX_VARIABLE_TASK_ID on ACT_RU_VARIABLE(TASK_ID_); create index ACT_IDX_ATHRZ_PROCEDEF on ACT_RU_IDENTITYLINK(PROC_DEF_ID_); +create index ACT_IDX_INFO_PROCDEF on ACT_PROCDEF_INFO(PROC_DEF_ID_); alter table ACT_GE_BYTEARRAY add constraint ACT_FK_BYTEARR_DEPL @@ -258,9 +267,9 @@ alter table ACT_RU_TASK references ACT_RU_EXECUTION; alter table ACT_RU_TASK - add constraint ACT_FK_TASK_PROCDEF - foreign key (PROC_DEF_ID_) - references ACT_RE_PROCDEF; + add constraint ACT_FK_TASK_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF; alter table ACT_RU_VARIABLE add constraint ACT_FK_VAR_EXE @@ -301,3 +310,17 @@ alter table ACT_RE_MODEL add constraint ACT_FK_MODEL_DEPLOYMENT foreign key (DEPLOYMENT_ID_) references ACT_RE_DEPLOYMENT (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_JSON_BA + foreign key (INFO_JSON_ID_) + references ACT_GE_BYTEARRAY (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_UNIQ_INFO_PROCDEF + unique (PROC_DEF_ID_); \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.mssql.create.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.mssql.create.engine.sql index 984b5ea3fe..8df9e42d2b 100644 --- a/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.mssql.create.engine.sql +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.mssql.create.engine.sql @@ -195,6 +195,14 @@ create table ACT_EVT_LOG ( primary key (LOG_NR_) ); +create table ACT_PROCDEF_INFO ( + ID_ nvarchar(64) not null, + PROC_DEF_ID_ nvarchar(64) not null, + REV_ int, + INFO_JSON_ID_ nvarchar(64), + primary key (ID_) +); + create index ACT_IDX_EXEC_BUSKEY on ACT_RU_EXECUTION(BUSINESS_KEY_); create index ACT_IDX_EXEC_ROOT on ACT_RU_EXECUTION(ROOT_PROC_INST_ID_); create index ACT_IDX_TASK_CREATE on ACT_RU_TASK(CREATE_TIME_); @@ -218,6 +226,7 @@ create index ACT_IDX_EXEC_PROC_INST_ID on ACT_RU_EXECUTION(PROC_INST_ID_); create index ACT_IDX_TASK_PROC_DEF_ID on ACT_RU_TASK(PROC_DEF_ID_); create index ACT_IDX_EVENT_SUBSCR_EXEC_ID on ACT_RU_EVENT_SUBSCR(EXECUTION_ID_); create index ACT_IDX_JOB_EXCEPTION_STACK_ID on ACT_RU_JOB(EXCEPTION_STACK_ID_); +create index ACT_IDX_INFO_PROCDEF on ACT_PROCDEF_INFO(PROC_DEF_ID_); alter table ACT_GE_BYTEARRAY add constraint ACT_FK_BYTEARR_DEPL @@ -269,9 +278,9 @@ alter table ACT_RU_TASK references ACT_RU_EXECUTION (ID_); alter table ACT_RU_TASK - add constraint ACT_FK_TASK_PROCDEF - foreign key (PROC_DEF_ID_) - references ACT_RE_PROCDEF (ID_); + add constraint ACT_FK_TASK_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); alter table ACT_RU_VARIABLE add constraint ACT_FK_VAR_EXE @@ -312,3 +321,17 @@ alter table ACT_RE_MODEL add constraint ACT_FK_MODEL_DEPLOYMENT foreign key (DEPLOYMENT_ID_) references ACT_RE_DEPLOYMENT (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_JSON_BA + foreign key (INFO_JSON_ID_) + references ACT_GE_BYTEARRAY (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_UNIQ_INFO_PROCDEF + unique (PROC_DEF_ID_); \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.mysql.create.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.mysql.create.engine.sql index f7050b33b3..5102588df1 100644 --- a/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.mysql.create.engine.sql +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.mysql.create.engine.sql @@ -195,6 +195,14 @@ create table ACT_EVT_LOG ( primary key (LOG_NR_) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; +create table ACT_PROCDEF_INFO ( + ID_ varchar(64) not null, + PROC_DEF_ID_ varchar(64) not null, + REV_ integer, + INFO_JSON_ID_ varchar(64), + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + create index ACT_IDX_EXEC_BUSKEY on ACT_RU_EXECUTION(BUSINESS_KEY_); create index ACT_IDC_EXEC_ROOT on ACT_RU_EXECUTION(ROOT_PROC_INST_ID_); create index ACT_IDX_TASK_CREATE on ACT_RU_TASK(CREATE_TIME_); @@ -203,6 +211,7 @@ create index ACT_IDX_IDENT_LNK_GROUP on ACT_RU_IDENTITYLINK(GROUP_ID_); create index ACT_IDX_EVENT_SUBSCR_CONFIG_ on ACT_RU_EVENT_SUBSCR(CONFIGURATION_); create index ACT_IDX_VARIABLE_TASK_ID on ACT_RU_VARIABLE(TASK_ID_); create index ACT_IDX_ATHRZ_PROCEDEF on ACT_RU_IDENTITYLINK(PROC_DEF_ID_); +create index ACT_IDX_INFO_PROCDEF on ACT_PROCDEF_INFO(PROC_DEF_ID_); alter table ACT_GE_BYTEARRAY add constraint ACT_FK_BYTEARR_DEPL @@ -259,9 +268,9 @@ alter table ACT_RU_TASK references ACT_RU_EXECUTION (ID_); alter table ACT_RU_TASK - add constraint ACT_FK_TASK_PROCDEF - foreign key (PROC_DEF_ID_) - references ACT_RE_PROCDEF (ID_); + add constraint ACT_FK_TASK_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); alter table ACT_RU_VARIABLE add constraint ACT_FK_VAR_EXE @@ -302,3 +311,17 @@ alter table ACT_RE_MODEL add constraint ACT_FK_MODEL_DEPLOYMENT foreign key (DEPLOYMENT_ID_) references ACT_RE_DEPLOYMENT (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_JSON_BA + foreign key (INFO_JSON_ID_) + references ACT_GE_BYTEARRAY (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_UNIQ_INFO_PROCDEF + unique (PROC_DEF_ID_); \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.mysql55.create.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.mysql55.create.engine.sql index a10798faa7..2d373e3904 100644 --- a/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.mysql55.create.engine.sql +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.mysql55.create.engine.sql @@ -195,6 +195,14 @@ create table ACT_EVT_LOG ( primary key (LOG_NR_) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; +create table ACT_PROCDEF_INFO ( + ID_ varchar(64) not null, + PROC_DEF_ID_ varchar(64) not null, + REV_ integer, + INFO_JSON_ID_ varchar(64), + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + create index ACT_IDX_EXEC_BUSKEY on ACT_RU_EXECUTION(BUSINESS_KEY_); create index ACT_IDX_EXEC_ROOT on ACT_RU_EXECUTION(ROOT_PROC_INST_ID_); create index ACT_IDX_TASK_CREATE on ACT_RU_TASK(CREATE_TIME_); @@ -203,6 +211,7 @@ create index ACT_IDX_IDENT_LNK_GROUP on ACT_RU_IDENTITYLINK(GROUP_ID_); create index ACT_IDX_EVENT_SUBSCR_CONFIG_ on ACT_RU_EVENT_SUBSCR(CONFIGURATION_); create index ACT_IDX_VARIABLE_TASK_ID on ACT_RU_VARIABLE(TASK_ID_); create index ACT_IDX_ATHRZ_PROCEDEF on ACT_RU_IDENTITYLINK(PROC_DEF_ID_); +create index ACT_IDX_INFO_PROCDEF on ACT_PROCDEF_INFO(PROC_DEF_ID_); alter table ACT_GE_BYTEARRAY add constraint ACT_FK_BYTEARR_DEPL @@ -259,9 +268,9 @@ alter table ACT_RU_TASK references ACT_RU_EXECUTION (ID_); alter table ACT_RU_TASK - add constraint ACT_FK_TASK_PROCDEF - foreign key (PROC_DEF_ID_) - references ACT_RE_PROCDEF (ID_); + add constraint ACT_FK_TASK_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); alter table ACT_RU_VARIABLE add constraint ACT_FK_VAR_EXE @@ -302,3 +311,17 @@ alter table ACT_RE_MODEL add constraint ACT_FK_MODEL_DEPLOYMENT foreign key (DEPLOYMENT_ID_) references ACT_RE_DEPLOYMENT (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_JSON_BA + foreign key (INFO_JSON_ID_) + references ACT_GE_BYTEARRAY (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_UNIQ_INFO_PROCDEF + unique (PROC_DEF_ID_); \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.oracle.create.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.oracle.create.engine.sql index 7caff03975..49c6259d53 100644 --- a/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.oracle.create.engine.sql +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.oracle.create.engine.sql @@ -197,6 +197,14 @@ create table ACT_EVT_LOG ( create sequence act_evt_log_seq; +create table ACT_PROCDEF_INFO ( + ID_ NVARCHAR2(64) not null, + PROC_DEF_ID_ NVARCHAR2(64) not null, + REV_ integer, + INFO_JSON_ID_ NVARCHAR2(64), + primary key (ID_) +); + create index ACT_IDX_EXEC_BUSKEY on ACT_RU_EXECUTION(BUSINESS_KEY_); create index ACT_IDX_EXEC_ROOT on ACT_RU_EXECUTION(ROOT_PROC_INST_ID_); create index ACT_IDX_TASK_CREATE on ACT_RU_TASK(CREATE_TIME_); @@ -323,3 +331,18 @@ alter table ACT_RE_MODEL foreign key (DEPLOYMENT_ID_) references ACT_RE_DEPLOYMENT (ID_); +create index ACT_IDX_PROCDEF_INFO_JSON on ACT_PROCDEF_INFO(INFO_JSON_ID_); +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_JSON_BA + foreign key (INFO_JSON_ID_) + references ACT_GE_BYTEARRAY (ID_); + +create index ACT_IDX_PROCDEF_INFO_PROC on ACT_PROCDEF_INFO(PROC_DEF_ID_); +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_UNIQ_INFO_PROCDEF + unique (PROC_DEF_ID_); \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.postgres.create.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.postgres.create.engine.sql index c1f047becb..285fd43604 100644 --- a/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.postgres.create.engine.sql +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/create/activiti.postgres.create.engine.sql @@ -194,6 +194,14 @@ create table ACT_EVT_LOG ( IS_PROCESSED_ smallint default 0 ); +create table ACT_PROCDEF_INFO ( + ID_ varchar(64) not null, + PROC_DEF_ID_ varchar(64) not null, + REV_ integer, + INFO_JSON_ID_ varchar(64), + primary key (ID_) +); + create index ACT_IDX_EXEC_BUSKEY on ACT_RU_EXECUTION(BUSINESS_KEY_); create index ACT_IDX_EXE_ROOT on ACT_RU_EXECUTION(ROOT_PROC_INST_ID_); create index ACT_IDX_TASK_CREATE on ACT_RU_TASK(CREATE_TIME_); @@ -321,3 +329,19 @@ alter table ACT_RE_MODEL add constraint ACT_FK_MODEL_DEPLOYMENT foreign key (DEPLOYMENT_ID_) references ACT_RE_DEPLOYMENT (ID_); + +create index ACT_IDX_PROCDEF_INFO_JSON on ACT_PROCDEF_INFO(INFO_JSON_ID_); +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_JSON_BA + foreign key (INFO_JSON_ID_) + references ACT_GE_BYTEARRAY (ID_); + +create index ACT_IDX_PROCDEF_INFO_PROC on ACT_PROCDEF_INFO(PROC_DEF_ID_); +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_UNIQ_INFO_PROCDEF + unique (PROC_DEF_ID_); \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.db2.drop.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.db2.drop.engine.sql index 466645f7bf..9795949a1e 100644 --- a/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.db2.drop.engine.sql +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.db2.drop.engine.sql @@ -3,6 +3,7 @@ drop index ACT_IDX_TASK_CREATE; drop index ACT_IDX_IDENT_LNK_USER; drop index ACT_IDX_IDENT_LNK_GROUP; drop index ACT_IDX_VARIABLE_TASK_ID; +drop index ACT_IDX_INFO_PROCDEF; alter table ACT_GE_BYTEARRAY drop foreign key ACT_FK_BYTEARR_DEPL; @@ -56,7 +57,13 @@ alter table ACT_RE_MODEL drop foreign key ACT_FK_MODEL_SOURCE_EXTRA; alter table ACT_RE_MODEL - drop foreign key ACT_FK_MODEL_DEPLOYMENT; + drop foreign key ACT_FK_MODEL_DEPLOYMENT; + +alter table ACT_PROCDEF_INFO + drop foreign key ACT_FK_INFO_JSON_BA; + +alter table ACT_PROCDEF_INFO + drop foreign key ACT_FK_INFO_PROCDEF; drop index ACT_IDX_EVENT_SUBSCR_CONFIG_; drop index ACT_IDX_ATHRZ_PROCEDEF; @@ -73,3 +80,4 @@ drop table ACT_RU_EXECUTION; drop table ACT_RU_JOB; drop table ACT_RU_EVENT_SUBSCR; drop table ACT_EVT_LOG; +drop table ACT_PROCDEF_INFO; diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.h2.drop.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.h2.drop.engine.sql index f17bb5ece5..15ccd69005 100644 --- a/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.h2.drop.engine.sql +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.h2.drop.engine.sql @@ -10,6 +10,7 @@ drop table if exists ACT_RU_IDENTITYLINK cascade constraints; drop table if exists ACT_RU_VARIABLE cascade constraints; drop table if exists ACT_RU_EVENT_SUBSCR cascade constraints; drop table if exists ACT_EVT_LOG cascade constraints; +drop table if exists ACT_PROCDEF_INFO cascade constraints; drop index if exists ACT_IDX_EXEC_BUSKEY; drop index if exists ACT_IDX_TASK_CREATE; @@ -17,4 +18,5 @@ drop index if exists ACT_IDX_IDENT_LNK_USER; drop index if exists ACT_IDX_IDENT_LNK_GROUP; drop index if exists ACT_IDX_VARIABLE_TASK_ID; drop index if exists ACT_IDX_EVENT_SUBSCR_CONFIG_; -drop index if exists ACT_IDX_ATHRZ_PROCEDEF; \ No newline at end of file +drop index if exists ACT_IDX_ATHRZ_PROCEDEF; +drop index if exists ACT_IDX_INFO_PROCDEF; \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.hsql.drop.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.hsql.drop.engine.sql index a2df5769ba..4cacb47328 100644 --- a/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.hsql.drop.engine.sql +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.hsql.drop.engine.sql @@ -10,6 +10,7 @@ drop table if exists ACT_RU_IDENTITYLINK cascade; drop table if exists ACT_RU_VARIABLE cascade; drop table if exists ACT_RU_EVENT_SUBSCR cascade; drop table if exists ACT_EVT_LOG cascade; +drop table if exists ACT_PROCDEF_INFO cascade; drop index if exists ACT_IDX_EXEC_BUSKEY; drop index if exists ACT_IDX_TASK_CREATE; @@ -17,4 +18,5 @@ drop index if exists ACT_IDX_IDENT_LNK_USER; drop index if exists ACT_IDX_IDENT_LNK_GROUP; drop index if exists ACT_IDX_VARIABLE_TASK_ID; drop index if exists ACT_IDX_EVENT_SUBSCR_CONFIG_; -drop index if exists ACT_IDX_ATHRZ_PROCEDEF; \ No newline at end of file +drop index if exists ACT_IDX_ATHRZ_PROCEDEF; +drop index if exists ACT_IDX_INFO_PROCDEF; \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.mssql.drop.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.mssql.drop.engine.sql index 1843d1d33d..231d25970f 100644 --- a/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.mssql.drop.engine.sql +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.mssql.drop.engine.sql @@ -4,6 +4,7 @@ IF EXISTS (SELECT name FROM sysindexes WHERE name = 'ACT_IDX_IDENT_LNK_USER') dr IF EXISTS (SELECT name FROM sysindexes WHERE name = 'ACT_IDX_IDENT_LNK_GROUP') drop index ACT_RU_IDENTITYLINK.ACT_IDX_IDENT_LNK_GROUP; IF EXISTS (SELECT name FROM sysindexes WHERE name = 'ACT_IDX_VARIABLE_TASK_ID') drop index ACT_RU_VARIABLE.ACT_IDX_VARIABLE_TASK_ID; IF EXISTS (SELECT name FROM sysindexes WHERE name = 'ACT_IDX_EVENT_SUBSCR_CONFIG_') drop index ACT_RU_EVENT_SUBSCR.ACT_IDX_EVENT_SUBSCR_CONFIG_; +IF EXISTS (SELECT name FROM sysindexes WHERE name = 'ACT_IDX_INFO_PROCDEF') drop index ACT_PROCDEF_INFO.ACT_IDX_INFO_PROCDEF; if exists (select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'ACT_GE_BYTEARRAY') alter table ACT_GE_BYTEARRAY drop constraint ACT_FK_BYTEARR_DEPL; if exists (select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'ACT_RE_PROCDEF') alter table ACT_RE_PROCDEF drop constraint ACT_UNIQ_PROCDEF; @@ -23,6 +24,8 @@ if exists (select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_NAME = ' if exists (select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'ACT_RE_MODEL') alter table ACT_RE_MODEL drop constraint ACT_FK_MODEL_SOURCE; if exists (select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'ACT_RE_MODEL') alter table ACT_RE_MODEL drop constraint ACT_FK_MODEL_SOURCE_EXTRA; if exists (select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'ACT_RE_MODEL') alter table ACT_RE_MODEL drop constraint ACT_FK_MODEL_DEPLOYMENT; +if exists (select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'ACT_PROCDEF_INFO') alter table ACT_PROCDEF_INFO drop constraint ACT_FK_INFO_JSON_BA; +if exists (select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'ACT_PROCDEF_INFO') alter table ACT_PROCDEF_INFO drop constraint ACT_FK_INFO_PROCDEF; IF EXISTS (SELECT name FROM sysindexes WHERE name = 'ACT_IDX_ATHRZ_PROCEDEF') drop index ACT_RU_IDENTITYLINK.ACT_IDX_ATHRZ_PROCEDEF; @@ -38,3 +41,4 @@ if exists (select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_NAME = ' if exists (select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'ACT_RU_EVENT_SUBSCR') drop table ACT_RU_EVENT_SUBSCR; if exists (select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'ACT_RU_JOB') drop table ACT_RU_JOB; if exists (select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'ACT_EVT_LOG') drop table ACT_EVT_LOG; +if exists (select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'ACT_PROCDEF_INFO') drop table ACT_PROCDEF_INFO; \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.mysql.drop.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.mysql.drop.engine.sql index 98cd86f342..73f1fee904 100644 --- a/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.mysql.drop.engine.sql +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.mysql.drop.engine.sql @@ -3,6 +3,7 @@ drop index ACT_IDX_TASK_CREATE on ACT_RU_TASK; drop index ACT_IDX_IDENT_LNK_USER on ACT_RU_IDENTITYLINK; drop index ACT_IDX_IDENT_LNK_GROUP on ACT_RU_IDENTITYLINK; drop index ACT_IDX_VARIABLE_TASK_ID on ACT_RU_VARIABLE; +drop index ACT_IDX_INFO_PROCDEF on ACT_PROCDEF_INFO; alter table ACT_GE_BYTEARRAY drop FOREIGN KEY ACT_FK_BYTEARR_DEPL; @@ -56,7 +57,13 @@ alter table ACT_RE_MODEL drop FOREIGN KEY ACT_FK_MODEL_SOURCE_EXTRA; alter table ACT_RE_MODEL - drop FOREIGN KEY ACT_FK_MODEL_DEPLOYMENT; + drop FOREIGN KEY ACT_FK_MODEL_DEPLOYMENT; + +alter table ACT_PROCDEF_INFO + drop FOREIGN KEY ACT_FK_INFO_JSON_BA; + +alter table ACT_PROCDEF_INFO + drop FOREIGN KEY ACT_FK_INFO_PROCDEF; drop index ACT_IDX_ATHRZ_PROCEDEF on ACT_RU_IDENTITYLINK; drop index ACT_IDX_EVENT_SUBSCR_CONFIG_ on ACT_RU_EVENT_SUBSCR; @@ -72,4 +79,5 @@ drop table if exists ACT_RE_PROCDEF; drop table if exists ACT_RU_EXECUTION; drop table if exists ACT_RU_JOB; drop table if exists ACT_RU_EVENT_SUBSCR; -drop table if exists ACT_EVT_LOG; \ No newline at end of file +drop table if exists ACT_EVT_LOG; +drop table if exists ACT_PROCDEF_INFO; \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.oracle.drop.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.oracle.drop.engine.sql index cc33016f1a..a6e84908cd 100644 --- a/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.oracle.drop.engine.sql +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.oracle.drop.engine.sql @@ -75,11 +75,18 @@ alter table ACT_RE_MODEL drop CONSTRAINT ACT_FK_MODEL_SOURCE_EXTRA; alter table ACT_RE_MODEL - drop CONSTRAINT ACT_FK_MODEL_DEPLOYMENT; + drop CONSTRAINT ACT_FK_MODEL_DEPLOYMENT; + +alter table ACT_PROCDEF_INFO + drop CONSTRAINT ACT_FK_INFO_JSON_BA; + +alter table ACT_PROCDEF_INFO + drop CONSTRAINT ACT_FK_INFO_PROCDEF; drop index ACT_IDX_EVENT_SUBSCR_CONFIG_; drop index ACT_IDX_EVENT_SUBSCR; drop index ACT_IDX_ATHRZ_PROCEDEF; +drop index ACT_IDX_INFO_PROCDEF; drop table ACT_GE_PROPERTY; drop table ACT_GE_BYTEARRAY; @@ -95,3 +102,4 @@ drop table ACT_RU_EVENT_SUBSCR; drop sequence act_evt_log_seq; drop table ACT_EVT_LOG; +drop table ACT_PROCDEF_INFO; \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.postgres.drop.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.postgres.drop.engine.sql index d68e2c3f7a..5ec910b6e9 100644 --- a/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.postgres.drop.engine.sql +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/drop/activiti.postgres.drop.engine.sql @@ -10,3 +10,4 @@ drop table if exists ACT_RU_IDENTITYLINK cascade; drop table if exists ACT_RU_VARIABLE cascade; drop table if exists ACT_RU_EVENT_SUBSCR cascade; drop table if exists ACT_EVT_LOG cascade; +drop table if exists ACT_PROCDEF_INFO cascade; \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/mapping/entity/ProcessDefinitionInfo.xml b/modules/activiti-engine/src/main/resources/org/activiti/db/mapping/entity/ProcessDefinitionInfo.xml new file mode 100644 index 0000000000..20222de04a --- /dev/null +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/mapping/entity/ProcessDefinitionInfo.xml @@ -0,0 +1,74 @@ + + + + + + + + + + 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 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}) + + + + + INSERT ALL + + 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}) + + SELECT * FROM dual + + + + + 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} + + + + + + + delete from ${prefix}ACT_PROCDEF_INFO where ID_ = #{id} and REV_ = #{revision} + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/mapping/mappings.xml b/modules/activiti-engine/src/main/resources/org/activiti/db/mapping/mappings.xml index 4cd8992201..1be2cdbff8 100644 --- a/modules/activiti-engine/src/main/resources/org/activiti/db/mapping/mappings.xml +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/mapping/mappings.xml @@ -33,6 +33,7 @@ + diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.db2.upgradestep.51800.to.51801.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.db2.upgradestep.51800.to.51801.engine.sql new file mode 100644 index 0000000000..2ce3e3c659 --- /dev/null +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.db2.upgradestep.51800.to.51801.engine.sql @@ -0,0 +1,26 @@ +update ACT_GE_PROPERTY set VALUE_ = '5.18.0.1' where NAME_ = 'schema.version'; + +create table ACT_PROCDEF_INFO ( + ID_ varchar(64) not null, + PROC_DEF_ID_ varchar(64) not null, + REV_ integer, + INFO_JSON_ID_ varchar(64), + primary key (ID_) +); + +create index ACT_IDX_INFO_PROCDEF on ACT_PROCDEF_INFO(PROC_DEF_ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_JSON_BA + foreign key (INFO_JSON_ID_) + references ACT_GE_BYTEARRAY (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_UNIQ_INFO_PROCDEF + unique (PROC_DEF_ID_); + \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.h2.upgradestep.51800.to.51801.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.h2.upgradestep.51800.to.51801.engine.sql new file mode 100644 index 0000000000..2ce3e3c659 --- /dev/null +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.h2.upgradestep.51800.to.51801.engine.sql @@ -0,0 +1,26 @@ +update ACT_GE_PROPERTY set VALUE_ = '5.18.0.1' where NAME_ = 'schema.version'; + +create table ACT_PROCDEF_INFO ( + ID_ varchar(64) not null, + PROC_DEF_ID_ varchar(64) not null, + REV_ integer, + INFO_JSON_ID_ varchar(64), + primary key (ID_) +); + +create index ACT_IDX_INFO_PROCDEF on ACT_PROCDEF_INFO(PROC_DEF_ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_JSON_BA + foreign key (INFO_JSON_ID_) + references ACT_GE_BYTEARRAY (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_UNIQ_INFO_PROCDEF + unique (PROC_DEF_ID_); + \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.hsql.upgradestep.51800.to.51801.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.hsql.upgradestep.51800.to.51801.engine.sql new file mode 100644 index 0000000000..2ce3e3c659 --- /dev/null +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.hsql.upgradestep.51800.to.51801.engine.sql @@ -0,0 +1,26 @@ +update ACT_GE_PROPERTY set VALUE_ = '5.18.0.1' where NAME_ = 'schema.version'; + +create table ACT_PROCDEF_INFO ( + ID_ varchar(64) not null, + PROC_DEF_ID_ varchar(64) not null, + REV_ integer, + INFO_JSON_ID_ varchar(64), + primary key (ID_) +); + +create index ACT_IDX_INFO_PROCDEF on ACT_PROCDEF_INFO(PROC_DEF_ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_JSON_BA + foreign key (INFO_JSON_ID_) + references ACT_GE_BYTEARRAY (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_UNIQ_INFO_PROCDEF + unique (PROC_DEF_ID_); + \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.mssql.upgradestep.51800.to.51801.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.mssql.upgradestep.51800.to.51801.engine.sql new file mode 100644 index 0000000000..f55d5d5146 --- /dev/null +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.mssql.upgradestep.51800.to.51801.engine.sql @@ -0,0 +1,26 @@ +update ACT_GE_PROPERTY set VALUE_ = '5.18.0.1' where NAME_ = 'schema.version'; + +create table ACT_PROCDEF_INFO ( + ID_ nvarchar(64) not null, + PROC_DEF_ID_ nvarchar(64) not null, + REV_ int, + INFO_JSON_ID_ nvarchar(64), + primary key (ID_) +); + +create index ACT_IDX_INFO_PROCDEF on ACT_PROCDEF_INFO(PROC_DEF_ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_JSON_BA + foreign key (INFO_JSON_ID_) + references ACT_GE_BYTEARRAY (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_UNIQ_INFO_PROCDEF + unique (PROC_DEF_ID_); + \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.mysql.upgradestep.51800.to.51801.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.mysql.upgradestep.51800.to.51801.engine.sql new file mode 100644 index 0000000000..5a234a451e --- /dev/null +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.mysql.upgradestep.51800.to.51801.engine.sql @@ -0,0 +1,26 @@ +update ACT_GE_PROPERTY set VALUE_ = '5.18.0.1' where NAME_ = 'schema.version'; + +create table ACT_PROCDEF_INFO ( + ID_ varchar(64) not null, + PROC_DEF_ID_ varchar(64) not null, + REV_ integer, + INFO_JSON_ID_ varchar(64), + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create index ACT_IDX_INFO_PROCDEF on ACT_PROCDEF_INFO(PROC_DEF_ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_JSON_BA + foreign key (INFO_JSON_ID_) + references ACT_GE_BYTEARRAY (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_UNIQ_INFO_PROCDEF + unique (PROC_DEF_ID_); + \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.mysql55.upgradestep.51800.to.51801.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.mysql55.upgradestep.51800.to.51801.engine.sql new file mode 100644 index 0000000000..5a234a451e --- /dev/null +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.mysql55.upgradestep.51800.to.51801.engine.sql @@ -0,0 +1,26 @@ +update ACT_GE_PROPERTY set VALUE_ = '5.18.0.1' where NAME_ = 'schema.version'; + +create table ACT_PROCDEF_INFO ( + ID_ varchar(64) not null, + PROC_DEF_ID_ varchar(64) not null, + REV_ integer, + INFO_JSON_ID_ varchar(64), + primary key (ID_) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; + +create index ACT_IDX_INFO_PROCDEF on ACT_PROCDEF_INFO(PROC_DEF_ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_JSON_BA + foreign key (INFO_JSON_ID_) + references ACT_GE_BYTEARRAY (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_UNIQ_INFO_PROCDEF + unique (PROC_DEF_ID_); + \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.oracle.upgradestep.51800.to.51801.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.oracle.upgradestep.51800.to.51801.engine.sql new file mode 100644 index 0000000000..d4f6a87912 --- /dev/null +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.oracle.upgradestep.51800.to.51801.engine.sql @@ -0,0 +1,26 @@ +update ACT_GE_PROPERTY set VALUE_ = '5.18.0.1' where NAME_ = 'schema.version'; + +create table ACT_PROCDEF_INFO ( + ID_ NVARCHAR2(64) not null, + PROC_DEF_ID_ NVARCHAR2(64) not null, + REV_ integer, + INFO_JSON_ID_ NVARCHAR2(64), + primary key (ID_) +); + +create index ACT_IDX_PROCDEF_INFO_JSON on ACT_PROCDEF_INFO(INFO_JSON_ID_); +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_JSON_BA + foreign key (INFO_JSON_ID_) + references ACT_GE_BYTEARRAY (ID_); + +create index ACT_IDX_PROCDEF_INFO_PROC on ACT_PROCDEF_INFO(PROC_DEF_ID_); +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_UNIQ_INFO_PROCDEF + unique (PROC_DEF_ID_); + \ No newline at end of file diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.postgres.upgradestep.51800.to.51801.engine.sql b/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.postgres.upgradestep.51800.to.51801.engine.sql new file mode 100644 index 0000000000..128e4b6df0 --- /dev/null +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/upgrade/activiti.postgres.upgradestep.51800.to.51801.engine.sql @@ -0,0 +1,26 @@ +update ACT_GE_PROPERTY set VALUE_ = '5.18.0.1' where NAME_ = 'schema.version'; + +create table ACT_PROCDEF_INFO ( + ID_ varchar(64) not null, + PROC_DEF_ID_ varchar(64) not null, + REV_ integer, + INFO_JSON_ID_ varchar(64), + primary key (ID_) +); + +create index ACT_IDX_PROCDEF_INFO_JSON on ACT_PROCDEF_INFO(INFO_JSON_ID_); +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_JSON_BA + foreign key (INFO_JSON_ID_) + references ACT_GE_BYTEARRAY (ID_); + +create index ACT_IDX_PROCDEF_INFO_PROC on ACT_PROCDEF_INFO(PROC_DEF_ID_); +alter table ACT_PROCDEF_INFO + add constraint ACT_FK_INFO_PROCDEF + foreign key (PROC_DEF_ID_) + references ACT_RE_PROCDEF (ID_); + +alter table ACT_PROCDEF_INFO + add constraint ACT_UNIQ_INFO_PROCDEF + unique (PROC_DEF_ID_); + \ No newline at end of file diff --git a/modules/activiti-engine/src/test/java/org/activiti/engine/test/api/event/ActivityEventsTest.java b/modules/activiti-engine/src/test/java/org/activiti/engine/test/api/event/ActivityEventsTest.java index db6d913660..4caa41e566 100755 --- a/modules/activiti-engine/src/test/java/org/activiti/engine/test/api/event/ActivityEventsTest.java +++ b/modules/activiti-engine/src/test/java/org/activiti/engine/test/api/event/ActivityEventsTest.java @@ -55,7 +55,7 @@ public class ActivityEventsTest extends PluggableActivitiTestCase { super.setUp(); // Database event logger setup - databaseEventLogger = new EventLogger(processEngineConfiguration.getClock()); + databaseEventLogger = new EventLogger(processEngineConfiguration.getClock(), processEngineConfiguration.getObjectMapper()); runtimeService.addEventListener(databaseEventLogger); } diff --git a/modules/activiti-engine/src/test/java/org/activiti/engine/test/api/event/DatabaseEventLoggerTest.java b/modules/activiti-engine/src/test/java/org/activiti/engine/test/api/event/DatabaseEventLoggerTest.java index 6568f830d1..6ac0fc8409 100644 --- a/modules/activiti-engine/src/test/java/org/activiti/engine/test/api/event/DatabaseEventLoggerTest.java +++ b/modules/activiti-engine/src/test/java/org/activiti/engine/test/api/event/DatabaseEventLoggerTest.java @@ -36,7 +36,7 @@ public class DatabaseEventLoggerTest extends PluggableActivitiTestCase { super.setUp(); // Database event logger setup - databaseEventLogger = new EventLogger(processEngineConfiguration.getClock()); + databaseEventLogger = new EventLogger(processEngineConfiguration.getClock(), processEngineConfiguration.getObjectMapper()); runtimeService.addEventListener(databaseEventLogger); } diff --git a/modules/activiti-engine/src/test/java/org/activiti/engine/test/api/history/HistoryServiceTest.java b/modules/activiti-engine/src/test/java/org/activiti/engine/test/api/history/HistoryServiceTest.java index 694e2bf80a..58824e3be4 100644 --- a/modules/activiti-engine/src/test/java/org/activiti/engine/test/api/history/HistoryServiceTest.java +++ b/modules/activiti-engine/src/test/java/org/activiti/engine/test/api/history/HistoryServiceTest.java @@ -36,6 +36,8 @@ import org.activiti.engine.task.TaskQuery; import org.activiti.engine.test.Deployment; import org.activiti.engine.test.api.runtime.ProcessInstanceQueryTest; +import com.fasterxml.jackson.databind.node.ObjectNode; + /** * @author Frederik Heremans * @author Falko Menge @@ -452,6 +454,52 @@ public class HistoryServiceTest extends PluggableActivitiTestCase { taskInstanceQuery = historyService.createHistoricTaskInstanceQuery().taskDefinitionKey("theTask").or().deploymentIdIn(deploymentIds).endOr(); assertEquals(0, taskInstanceQuery.count()); } + + @Deployment(resources={"org/activiti/engine/test/api/oneTaskProcess.bpmn20.xml"}) + public void testLocalizeTasks() throws Exception { + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess"); + + List tasks = historyService.createHistoricTaskInstanceQuery().processDefinitionId(processInstance.getProcessDefinitionId()).list(); + assertEquals(1, tasks.size()); + assertEquals("my task", tasks.get(0).getName()); + assertNull(tasks.get(0).getDescription()); + + ObjectNode infoNode = dynamicBpmnService.changeLocalizationName("en-GB", "theTask", "My localized name"); + dynamicBpmnService.changeLocalizationDescription("en-GB".toString(), "theTask", "My localized description", infoNode); + dynamicBpmnService.saveProcessDefinitionInfo(processInstance.getProcessDefinitionId(), infoNode); + + tasks = historyService.createHistoricTaskInstanceQuery().processDefinitionId(processInstance.getProcessDefinitionId()).list(); + assertEquals(1, tasks.size()); + assertEquals("my task", tasks.get(0).getName()); + assertNull(tasks.get(0).getDescription()); + + tasks = historyService.createHistoricTaskInstanceQuery().processDefinitionId(processInstance.getProcessDefinitionId()).locale("en-GB").list(); + assertEquals(1, tasks.size()); + assertEquals("My localized name", tasks.get(0).getName()); + assertEquals("My localized description", tasks.get(0).getDescription()); + + tasks = historyService.createHistoricTaskInstanceQuery().processDefinitionId(processInstance.getProcessDefinitionId()).listPage(0, 10); + assertEquals(1, tasks.size()); + assertEquals("my task", tasks.get(0).getName()); + assertNull(tasks.get(0).getDescription()); + + tasks = historyService.createHistoricTaskInstanceQuery().processDefinitionId(processInstance.getProcessDefinitionId()).locale("en-GB").listPage(0, 10); + assertEquals(1, tasks.size()); + assertEquals("My localized name", tasks.get(0).getName()); + assertEquals("My localized description", tasks.get(0).getDescription()); + + HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().processDefinitionId(processInstance.getProcessDefinitionId()).singleResult(); + assertEquals("my task", task.getName()); + assertNull(task.getDescription()); + + task = historyService.createHistoricTaskInstanceQuery().processDefinitionId(processInstance.getProcessDefinitionId()).locale("en-GB").singleResult(); + assertEquals("My localized name", task.getName()); + assertEquals("My localized description", task.getDescription()); + + task = historyService.createHistoricTaskInstanceQuery().processDefinitionId(processInstance.getProcessDefinitionId()).singleResult(); + assertEquals("my task", task.getName()); + assertNull(task.getDescription()); + } @Deployment(resources = { "org/activiti/engine/test/api/runtime/concurrentExecution.bpmn20.xml" }) public void testHistoricVariableInstancesOnParallelExecution() { diff --git a/modules/activiti-engine/src/test/java/org/activiti/engine/test/api/task/TaskQueryTest.java b/modules/activiti-engine/src/test/java/org/activiti/engine/test/api/task/TaskQueryTest.java index a1cf157950..ddbb8b8fed 100644 --- a/modules/activiti-engine/src/test/java/org/activiti/engine/test/api/task/TaskQueryTest.java +++ b/modules/activiti-engine/src/test/java/org/activiti/engine/test/api/task/TaskQueryTest.java @@ -34,6 +34,8 @@ import org.activiti.engine.task.Task; import org.activiti.engine.task.TaskQuery; import org.activiti.engine.test.Deployment; +import com.fasterxml.jackson.databind.node.ObjectNode; + /** * @author Joram Barrez * @author Frederik Heremans @@ -2502,7 +2504,52 @@ public class TaskQueryTest extends PluggableActivitiTestCase { .endOr() .list() .size()); - + } + + @Deployment(resources={"org/activiti/engine/test/api/task/TaskQueryTest.testProcessDefinition.bpmn20.xml"}) + public void testLocalizeTasks() throws Exception { + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess"); + + List tasks = taskService.createTaskQuery().processDefinitionId(processInstance.getProcessDefinitionId()).list(); + assertEquals(1, tasks.size()); + assertEquals("my task", tasks.get(0).getName()); + assertNull(tasks.get(0).getDescription()); + + ObjectNode infoNode = dynamicBpmnService.changeLocalizationName("en-GB", "theTask", "My localized name"); + dynamicBpmnService.changeLocalizationDescription("en-GB".toString(), "theTask", "My localized description", infoNode); + dynamicBpmnService.saveProcessDefinitionInfo(processInstance.getProcessDefinitionId(), infoNode); + + tasks = taskService.createTaskQuery().processDefinitionId(processInstance.getProcessDefinitionId()).list(); + assertEquals(1, tasks.size()); + assertEquals("my task", tasks.get(0).getName()); + assertNull(tasks.get(0).getDescription()); + + tasks = taskService.createTaskQuery().processDefinitionId(processInstance.getProcessDefinitionId()).locale("en-GB").list(); + assertEquals(1, tasks.size()); + assertEquals("My localized name", tasks.get(0).getName()); + assertEquals("My localized description", tasks.get(0).getDescription()); + + tasks = taskService.createTaskQuery().processDefinitionId(processInstance.getProcessDefinitionId()).listPage(0, 10); + assertEquals(1, tasks.size()); + assertEquals("my task", tasks.get(0).getName()); + assertNull(tasks.get(0).getDescription()); + + tasks = taskService.createTaskQuery().processDefinitionId(processInstance.getProcessDefinitionId()).locale("en-GB").listPage(0, 10); + assertEquals(1, tasks.size()); + assertEquals("My localized name", tasks.get(0).getName()); + assertEquals("My localized description", tasks.get(0).getDescription()); + + Task task = taskService.createTaskQuery().processDefinitionId(processInstance.getProcessDefinitionId()).singleResult(); + assertEquals("my task", task.getName()); + assertNull(task.getDescription()); + + task = taskService.createTaskQuery().processDefinitionId(processInstance.getProcessDefinitionId()).locale("en-GB").singleResult(); + assertEquals("My localized name", task.getName()); + assertEquals("My localized description", task.getDescription()); + + task = taskService.createTaskQuery().processDefinitionId(processInstance.getProcessDefinitionId()).singleResult(); + assertEquals("my task", task.getName()); + assertNull(task.getDescription()); } /** diff --git a/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/servicetask/DummyServiceTask2.java b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/servicetask/DummyServiceTask2.java new file mode 100644 index 0000000000..200f16de0a --- /dev/null +++ b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/servicetask/DummyServiceTask2.java @@ -0,0 +1,31 @@ +/* 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.activiti.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); + } + +} diff --git a/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/servicetask/DummyTestBean.java b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/servicetask/DummyTestBean.java new file mode 100644 index 0000000000..e95d02a88a --- /dev/null +++ b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/servicetask/DummyTestBean.java @@ -0,0 +1,27 @@ +/* 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.activiti.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); + } +} diff --git a/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/servicetask/DummyTestDelegateBean.java b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/servicetask/DummyTestDelegateBean.java new file mode 100644 index 0000000000..6ef12ed2f5 --- /dev/null +++ b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/servicetask/DummyTestDelegateBean.java @@ -0,0 +1,28 @@ +/* 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.activiti.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); + } +} diff --git a/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/servicetask/DynamicServiceTaskTest.java b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/servicetask/DynamicServiceTaskTest.java new file mode 100644 index 0000000000..97f20dc6cf --- /dev/null +++ b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/servicetask/DynamicServiceTaskTest.java @@ -0,0 +1,159 @@ +/* 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.activiti.engine.test.bpmn.servicetask; + +import java.util.HashMap; +import java.util.Map; + +import org.activiti.engine.history.HistoricVariableInstance; +import org.activiti.engine.impl.test.PluggableActivitiTestCase; +import org.activiti.engine.runtime.ProcessInstance; +import org.activiti.engine.task.Task; +import org.activiti.engine.test.Deployment; + +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 varMap = new HashMap(); + 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(); + varMap.put("count", 0); + varMap.put("count2", 0); + processInstance = runtimeService.startProcessInstanceByKey("dynamicServiceTask", varMap); + + String processDefinitionId = processInstance.getProcessDefinitionId(); + ObjectNode infoNode = dynamicBpmnService.changeServiceTaskClassName("service", "org.activiti.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 varMap = new HashMap(); + 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(); + 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 varMap = new HashMap(); + 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(); + 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()); + } +} diff --git a/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/usertask/DisabledDefinitionInfoCacheTest.java b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/usertask/DisabledDefinitionInfoCacheTest.java new file mode 100644 index 0000000000..653e59e6a4 --- /dev/null +++ b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/usertask/DisabledDefinitionInfoCacheTest.java @@ -0,0 +1,115 @@ +/* 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.activiti.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.impl.test.AbstractActivitiTestCase; +import org.activiti.engine.runtime.ProcessInstance; +import org.activiti.engine.task.Task; +import org.activiti.engine.test.Deployment; + +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/activiti/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 varMap = new HashMap(); + 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(); + varMap.put("count", 0); + varMap.put("count2", 0); + processInstance = runtimeService.startProcessInstanceByKey("dynamicServiceTask", varMap); + + String processDefinitionId = processInstance.getProcessDefinitionId(); + ObjectNode infoNode = dynamicBpmnService.changeServiceTaskClassName("service", "org.activiti.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()); + } + +} \ No newline at end of file diff --git a/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.java b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.java new file mode 100644 index 0000000000..1900447d38 --- /dev/null +++ b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.java @@ -0,0 +1,417 @@ +/* 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.activiti.engine.test.bpmn.usertask; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.activiti.engine.impl.test.PluggableActivitiTestCase; +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 com.fasterxml.jackson.databind.node.ObjectNode; + + +/** + * @author Tijs Rademakers + */ +public class DynamicUserTaskTest extends PluggableActivitiTestCase { + + @Deployment(resources={"org/activiti/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/activiti/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/activiti/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 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/activiti/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 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/activiti/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 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/activiti/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/activiti/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 varMap = new HashMap(); + 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(); + 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()); + } + +} \ No newline at end of file diff --git a/modules/activiti-engine/src/test/resources/activiti.cfg.xml b/modules/activiti-engine/src/test/resources/activiti.cfg.xml index 2caf3389d4..5958d125a6 100644 --- a/modules/activiti-engine/src/test/resources/activiti.cfg.xml +++ b/modules/activiti-engine/src/test/resources/activiti.cfg.xml @@ -51,6 +51,8 @@ + + diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/servicetask/DynamicServiceTaskTest.testChangeClassName.bpmn20.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/servicetask/DynamicServiceTaskTest.testChangeClassName.bpmn20.xml new file mode 100644 index 0000000000..e5186e1114 --- /dev/null +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/servicetask/DynamicServiceTaskTest.testChangeClassName.bpmn20.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/servicetask/DynamicServiceTaskTest.testChangeDelegateExpression.bpmn20.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/servicetask/DynamicServiceTaskTest.testChangeDelegateExpression.bpmn20.xml new file mode 100644 index 0000000000..0cb323a007 --- /dev/null +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/servicetask/DynamicServiceTaskTest.testChangeDelegateExpression.bpmn20.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/servicetask/DynamicServiceTaskTest.testChangeExpression.bpmn20.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/servicetask/DynamicServiceTaskTest.testChangeExpression.bpmn20.xml new file mode 100644 index 0000000000..a0a4179b70 --- /dev/null +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/servicetask/DynamicServiceTaskTest.testChangeExpression.bpmn20.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DisabledDefinitionInfoCacheTest.testChangeClassName.bpmn20.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DisabledDefinitionInfoCacheTest.testChangeClassName.bpmn20.xml new file mode 100644 index 0000000000..21a4144a24 --- /dev/null +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DisabledDefinitionInfoCacheTest.testChangeClassName.bpmn20.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DisabledDefinitionInfoCacheTest.testChangeFormKey.bpmn20.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DisabledDefinitionInfoCacheTest.testChangeFormKey.bpmn20.xml new file mode 100644 index 0000000000..fcf1a0b915 --- /dev/null +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DisabledDefinitionInfoCacheTest.testChangeFormKey.bpmn20.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.assignment.bpmn20.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.assignment.bpmn20.xml new file mode 100644 index 0000000000..fce4e9268e --- /dev/null +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.assignment.bpmn20.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.basictask.bpmn20.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.basictask.bpmn20.xml new file mode 100644 index 0000000000..76a34f1796 --- /dev/null +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.basictask.bpmn20.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.testChangeFormKey.bpmn20.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.testChangeFormKey.bpmn20.xml new file mode 100644 index 0000000000..fcf1a0b915 --- /dev/null +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.testChangeFormKey.bpmn20.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.testChangeFormKeyWithExpression.bpmn20.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.testChangeFormKeyWithExpression.bpmn20.xml new file mode 100644 index 0000000000..714588cf27 --- /dev/null +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/DynamicUserTaskTest.testChangeFormKeyWithExpression.bpmn20.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/activiti.cfg.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/activiti.cfg.xml new file mode 100644 index 0000000000..88f5c6799d --- /dev/null +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/activiti.cfg.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/activiti5-test/src/test/java/org/activiti5/engine/test/api/event/StandaloneDatabaseEventLoggerTest.java b/modules/activiti5-test/src/test/java/org/activiti5/engine/test/api/event/StandaloneDatabaseEventLoggerTest.java index 5fed07d51c..0e083aa53d 100644 --- a/modules/activiti5-test/src/test/java/org/activiti5/engine/test/api/event/StandaloneDatabaseEventLoggerTest.java +++ b/modules/activiti5-test/src/test/java/org/activiti5/engine/test/api/event/StandaloneDatabaseEventLoggerTest.java @@ -27,7 +27,7 @@ public class StandaloneDatabaseEventLoggerTest extends PluggableActivitiTestCase super.setUp(); // Database event logger setup - databaseEventLogger = new EventLogger(processEngineConfiguration.getClock()); + databaseEventLogger = new EventLogger(processEngineConfiguration.getClock(), processEngineConfiguration.getObjectMapper()); runtimeService.addEventListener(databaseEventLogger); } diff --git a/qa/activiti5db/activiti.cfg.xml b/qa/activiti5db/activiti.cfg.xml index 51a73eb2d0..43f4256813 100644 --- a/qa/activiti5db/activiti.cfg.xml +++ b/qa/activiti5db/activiti.cfg.xml @@ -44,6 +44,7 @@ + diff --git a/qa/cfg/historyaudit.activiti.cfg.xml b/qa/cfg/historyaudit.activiti.cfg.xml index 5fc3e9f8c0..ae5752febc 100644 --- a/qa/cfg/historyaudit.activiti.cfg.xml +++ b/qa/cfg/historyaudit.activiti.cfg.xml @@ -38,6 +38,8 @@ + + diff --git a/qa/cfg/historyfull.activiti.cfg.xml b/qa/cfg/historyfull.activiti.cfg.xml index 9d687716c4..19152ca9c3 100644 --- a/qa/cfg/historyfull.activiti.cfg.xml +++ b/qa/cfg/historyfull.activiti.cfg.xml @@ -38,6 +38,8 @@ + + diff --git a/qa/cfg/historynone.activiti.cfg.xml b/qa/cfg/historynone.activiti.cfg.xml index 8c0d6e44b8..15f8d66316 100644 --- a/qa/cfg/historynone.activiti.cfg.xml +++ b/qa/cfg/historynone.activiti.cfg.xml @@ -39,6 +39,8 @@ + + diff --git a/qa/db/activiti.cfg.xml b/qa/db/activiti.cfg.xml index c348f3cf2f..71112309bf 100644 --- a/qa/db/activiti.cfg.xml +++ b/qa/db/activiti.cfg.xml @@ -42,6 +42,7 @@ + diff --git a/qa/db/historyfull.activiti.cfg.xml b/qa/db/historyfull.activiti.cfg.xml index b40d701799..bb129640fc 100644 --- a/qa/db/historyfull.activiti.cfg.xml +++ b/qa/db/historyfull.activiti.cfg.xml @@ -43,6 +43,8 @@ + + diff --git a/qa/db/mssql/activiti.cfg.xml b/qa/db/mssql/activiti.cfg.xml index 9c809ae07a..29958edee5 100644 --- a/qa/db/mssql/activiti.cfg.xml +++ b/qa/db/mssql/activiti.cfg.xml @@ -41,7 +41,9 @@ - + + + diff --git a/qa/db/schema/activiti.cfg.xml b/qa/db/schema/activiti.cfg.xml index f22d57bc0b..d460083cdf 100644 --- a/qa/db/schema/activiti.cfg.xml +++ b/qa/db/schema/activiti.cfg.xml @@ -43,6 +43,7 @@ + diff --git a/qa/jta/mysql/activiti.cfg.xml b/qa/jta/mysql/activiti.cfg.xml index 5a1690c45c..9adee4b4b0 100644 --- a/qa/jta/mysql/activiti.cfg.xml +++ b/qa/jta/mysql/activiti.cfg.xml @@ -53,6 +53,7 @@ + diff --git a/qa/jta/oracle/activiti.cfg.xml b/qa/jta/oracle/activiti.cfg.xml index ca80b088ef..cd10e723d7 100644 --- a/qa/jta/oracle/activiti.cfg.xml +++ b/qa/jta/oracle/activiti.cfg.xml @@ -66,6 +66,7 @@ + diff --git a/qa/jta/postgres/activiti.cfg.xml b/qa/jta/postgres/activiti.cfg.xml index 1f4a46c470..51dd020200 100644 --- a/qa/jta/postgres/activiti.cfg.xml +++ b/qa/jta/postgres/activiti.cfg.xml @@ -68,6 +68,7 @@ + diff --git a/qa/spring/h2/activiti.cfg.xml b/qa/spring/h2/activiti.cfg.xml index b11337a766..ec5ba09851 100644 --- a/qa/spring/h2/activiti.cfg.xml +++ b/qa/spring/h2/activiti.cfg.xml @@ -46,6 +46,7 @@ + diff --git a/qa/spring/mysql/activiti.cfg.xml b/qa/spring/mysql/activiti.cfg.xml index 19f8fa9c5c..94d8520dcd 100644 --- a/qa/spring/mysql/activiti.cfg.xml +++ b/qa/spring/mysql/activiti.cfg.xml @@ -58,6 +58,7 @@ + diff --git a/qa/upgrade/activiti.cfg.xml b/qa/upgrade/activiti.cfg.xml index b2e16c585f..71b51ab219 100644 --- a/qa/upgrade/activiti.cfg.xml +++ b/qa/upgrade/activiti.cfg.xml @@ -14,7 +14,7 @@ - + -- GitLab