diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ExecutionEntity.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ExecutionEntity.java index 649af7d8119073da197219efc2a9f255d9c5c0cf..63e81dfd766fea95abc5d5caebaec240ef54f0ef 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ExecutionEntity.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ExecutionEntity.java @@ -59,7 +59,9 @@ import org.slf4j.LoggerFactory; * @author Tom Baeyens * @author Daniel Meyer * @author Falko Menge + * @author Saeid Mirzaei */ + public class ExecutionEntity extends VariableScopeImpl implements ActivityExecution, ExecutionListenerExecution, Execution, PvmExecution, ProcessInstance, InterpretableExecution, PersistentObject, HasRevision { private static final long serialVersionUID = 1L; @@ -929,7 +931,17 @@ public class ExecutionEntity extends VariableScopeImpl implements ActivityExecut // update the related tasks for (TaskEntity task: getTasks()) { task.setExecutionId(replacedBy.getId()); - task.setExecution(this.replacedBy); + task.setExecution(this.replacedBy); + + // update the related local task variables + List variables = (List) commandContext + .getVariableInstanceEntityManager() + .findVariableInstancesByTaskId(task.getId()); + + for (VariableInstanceEntity variable : variables) { + variable.setExecution(this.replacedBy); + } + this.replacedBy.addTask(task); } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/VariableInstanceEntity.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/VariableInstanceEntity.java index d27b1cfb8e740477d8d88e82580989d50bec2ab2..16e6351e71ff779c04cb5185fe23b14619ffab49 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/VariableInstanceEntity.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/VariableInstanceEntity.java @@ -50,6 +50,8 @@ public class VariableInstanceEntity implements ValueFields, PersistentObject, Ha protected VariableType type; + boolean forcedUpdate; + // Default constructor for SQL mapping protected VariableInstanceEntity() { } @@ -77,6 +79,7 @@ public class VariableInstanceEntity implements ValueFields, PersistentObject, Ha public void setExecution(ExecutionEntity execution) { this.executionId = execution.getId(); this.processInstanceId = execution.getProcessInstanceId(); + forcedUpdate = true; } public void delete() { @@ -103,6 +106,9 @@ public class VariableInstanceEntity implements ValueFields, PersistentObject, Ha if (byteArrayValueId != null) { persistentState.put("byteArrayValueId", byteArrayValueId); } + if (forcedUpdate) { + persistentState.put("forcedUpdate", Boolean.TRUE); + } return persistentState; } diff --git a/modules/activiti-engine/src/main/resources/org/activiti/db/mapping/entity/VariableInstance.xml b/modules/activiti-engine/src/main/resources/org/activiti/db/mapping/entity/VariableInstance.xml index 18e5c201a0afab16d5c657516a80276a46d9d893..261719a4cbfc825d0888fe453aeb4a1a14999f8e 100644 --- a/modules/activiti-engine/src/main/resources/org/activiti/db/mapping/entity/VariableInstance.xml +++ b/modules/activiti-engine/src/main/resources/org/activiti/db/mapping/entity/VariableInstance.xml @@ -30,6 +30,7 @@ update ${prefix}ACT_RU_VARIABLE set REV_ = #{revisionNext, jdbcType=INTEGER}, + EXECUTION_ID_ = #{executionId, jdbcType=VARCHAR}, BYTEARRAY_ID_ = #{byteArrayValueId, jdbcType=VARCHAR}, DOUBLE_ = #{doubleValue, jdbcType=DOUBLE}, LONG_ = #{longValue, jdbcType=BIGINT}, diff --git a/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/usertask/UserTaskTest.java b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/usertask/UserTaskTest.java index ce49ac1b12f3487cc7f61f78bfe36f11a811384c..4db15f1d2c7686abc305c935232720605e5b6c65 100644 --- a/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/usertask/UserTaskTest.java +++ b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/usertask/UserTaskTest.java @@ -13,6 +13,8 @@ package org.activiti.engine.test.bpmn.usertask; +import java.util.List; + import org.activiti.engine.impl.history.HistoryLevel; import org.activiti.engine.impl.test.PluggableActivitiTestCase; import org.activiti.engine.runtime.ProcessInstance; @@ -53,4 +55,21 @@ public class UserTaskTest extends PluggableActivitiTestCase { assertEquals(1, taskService.createTaskQuery().processInstanceId(processInstance.getId()).list().size()); } + @Deployment + public void testCompleteAfterParallelGateway() throws InterruptedException { + // related to http://jira.codehaus.org/browse/ACT-1054 + + // start the process + runtimeService.startProcessInstanceByKey("ForkProcess"); + List taskList = taskService.createTaskQuery().list(); + assertNotNull(taskList); + assertEquals(2, taskList.size()); + + // make sure user task exists + Task task = taskService.createTaskQuery().taskDefinitionKey("SimpleUser").singleResult(); + assertNotNull(task); + + // attempt to complete the task and get PersistenceException pointing to "referential integrity constraint violation" + taskService.complete(task.getId()); + } } diff --git a/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/usertask/UserTaskTestCreateTaskListener.java b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/usertask/UserTaskTestCreateTaskListener.java new file mode 100755 index 0000000000000000000000000000000000000000..b0fa859c8338d8c0747ea111ddb880b15bb8bdf0 --- /dev/null +++ b/modules/activiti-engine/src/test/java/org/activiti/engine/test/bpmn/usertask/UserTaskTestCreateTaskListener.java @@ -0,0 +1,54 @@ +/* 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 org.activiti.engine.delegate.DelegateTask; +import org.activiti.engine.delegate.TaskListener; +import org.activiti.engine.impl.el.Expression; + + + +/** + * @author Tom Baeyens + * @author Daniel Meyer + * @author Falko Menge + * @author Saeid Mirzaei + */ + +/** + * This is for test case UserTaskTest.testCompleteAfterParallelGateway + * + */ + +public class UserTaskTestCreateTaskListener implements TaskListener { + + private static final long serialVersionUID = 1L; + private Expression expression; + + @Override + public void notify(DelegateTask delegateTask) { + + if (this.expression != null && this.expression.getValue(delegateTask) != null) { + // get the expression variable + String expression = this.expression.getValue(delegateTask).toString(); + + // this expression will be evaluated when completing the task + delegateTask.setVariableLocal("validationRule", expression); + } + + } + +} + + diff --git a/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/UserTaskTest.testCompleteAfterParallelGateway.bpmn20.xml b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/UserTaskTest.testCompleteAfterParallelGateway.bpmn20.xml new file mode 100644 index 0000000000000000000000000000000000000000..46ad993fca7b33c6c284c33d58a587ebcda9baa6 --- /dev/null +++ b/modules/activiti-engine/src/test/resources/org/activiti/engine/test/bpmn/usertask/UserTaskTest.testCompleteAfterParallelGateway.bpmn20.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file