diff --git a/engine/src/main/java/org/camunda/bpm/engine/impl/history/producer/DefaultHistoryEventProducer.java b/engine/src/main/java/org/camunda/bpm/engine/impl/history/producer/DefaultHistoryEventProducer.java index 15a7c15766f..392d614f8b5 100644 --- a/engine/src/main/java/org/camunda/bpm/engine/impl/history/producer/DefaultHistoryEventProducer.java +++ b/engine/src/main/java/org/camunda/bpm/engine/impl/history/producer/DefaultHistoryEventProducer.java @@ -25,7 +25,6 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; - import org.camunda.bpm.engine.ProcessEngineException; import org.camunda.bpm.engine.batch.Batch; import org.camunda.bpm.engine.delegate.DelegateExecution; @@ -65,6 +64,7 @@ import org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity; import org.camunda.bpm.engine.impl.persistence.entity.ExternalTaskEntity; import org.camunda.bpm.engine.impl.persistence.entity.HistoricJobLogEventEntity; +import org.camunda.bpm.engine.impl.persistence.entity.HistoricVariableInstanceEntity; import org.camunda.bpm.engine.impl.persistence.entity.IncidentEntity; import org.camunda.bpm.engine.impl.persistence.entity.JobEntity; import org.camunda.bpm.engine.impl.persistence.entity.ProcessDefinitionEntity; @@ -422,6 +422,7 @@ protected void initHistoricIncidentEvent(HistoricIncidentEventEntity evt, Incide protected HistoryEvent createHistoricVariableEvent(VariableInstanceEntity variableInstance, VariableScope sourceVariableScope, HistoryEventType eventType) { String scopeActivityInstanceId = null; String sourceActivityInstanceId = null; + String taskId = null; if(variableInstance.getExecutionId() != null) { ExecutionEntity scopeExecution = Context.getCommandContext() @@ -449,6 +450,13 @@ else if (variableInstance.getCaseExecutionId() != null) { } else if (sourceVariableScope instanceof TaskEntity) { sourceExecution = ((TaskEntity) sourceVariableScope).getExecution(); if (sourceExecution != null) { + + //this block when executed for task listener variables, gets task id from source execution + List taskEntityList = sourceExecution.getTasks(); + if(taskEntityList!=null && !taskEntityList.isEmpty()){ + taskId = taskEntityList.get(0).getId(); + } + sourceActivityInstanceId = sourceExecution.getActivityInstanceId(); } else { @@ -476,6 +484,11 @@ else if (sourceVariableScope instanceof CaseExecutionEntity) { // set source activity instance id evt.setActivityInstanceId(sourceActivityInstanceId); + // set task id for task listener variables + if(taskId!=null && evt.getTaskId()==null) { + evt.setTaskId(taskId); + } + // mark initial variables on process start if (sourceExecution != null && sourceExecution.isProcessInstanceStarting() && HistoryEventTypes.VARIABLE_INSTANCE_CREATE.equals(eventType)) { @@ -727,6 +740,23 @@ public HistoryEvent createActivityInstanceUpdateEvt(DelegateExecution execution, if(task != null) { evt.setTaskId(task.getId()); evt.setTaskAssignee(task.getAssignee()); + + /* + * this code is required for input variables of the task as the historic variable instance is created first + * and then task entity is created + * get historic variable instances from the cache as the transaction is still not committed + */ + List cachedHistoricVariableInstances = Context.getCommandContext().getDbEntityManager().getCachedEntitiesByType(HistoricVariableInstanceEntity.class); + String executionActivityInstanceId = executionEntity.getActivityInstanceId(); + for (HistoricVariableInstanceEntity historicVariableInstance : cachedHistoricVariableInstances) { + String historicActivityInstanceId = historicVariableInstance.getActivityInstanceId(); + //update task id for historic variable instances only specific to that task + if(executionActivityInstanceId!=null && historicActivityInstanceId!=null) { + if (historicActivityInstanceId.equals(executionActivityInstanceId)) { + historicVariableInstance.setTaskId(task.getId()); + } + } + } } return evt; diff --git a/engine/src/test/java/org/camunda/bpm/engine/test/history/HistoricVariableInstanceScopeTest.java b/engine/src/test/java/org/camunda/bpm/engine/test/history/HistoricVariableInstanceScopeTest.java index 7063113ad62..ed9f6a7a7dc 100644 --- a/engine/src/test/java/org/camunda/bpm/engine/test/history/HistoricVariableInstanceScopeTest.java +++ b/engine/src/test/java/org/camunda/bpm/engine/test/history/HistoricVariableInstanceScopeTest.java @@ -18,6 +18,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import java.util.HashMap; import java.util.List; @@ -86,6 +87,7 @@ public void testSetVariableLocalOnUserTask() { HistoricVariableInstance variable = query.singleResult(); assertNotNull(variable); + assertEquals(task.getId(),variable.getTaskId()); // the variable is in the task scope assertEquals(taskExecution.getActivityInstanceId(), variable.getActivityInstanceId()); @@ -118,12 +120,14 @@ public void testSetVariableOnProcessIntanceStartAndSetVariableLocalOnUserTask() assertEquals("testValue", firstVar.getValue()); // the variable is in the process instance scope assertEquals(pi.getId(), firstVar.getActivityInstanceId()); + assertNull(firstVar.getTaskId()); HistoricVariableInstance secondVar = result.get(1); assertEquals("testVar", secondVar.getVariableName()); assertEquals("anotherTestValue", secondVar.getValue()); // the variable is in the task scope assertEquals(taskExecution.getActivityInstanceId(), secondVar.getActivityInstanceId()); + assertEquals(task.getId(),secondVar.getTaskId()); taskService.complete(task.getId()); testRule.assertProcessEnded(pi.getId()); @@ -145,6 +149,7 @@ public void testSetVariableOnUserTaskInsideSubProcess() { HistoricVariableInstance variable = query.singleResult(); // the variable is in the process instance scope assertEquals(pi.getId(), variable.getActivityInstanceId()); + assertEquals(task.getId(),variable.getTaskId()); taskService.complete(task.getId()); testRule.assertProcessEnded(pi.getId()); @@ -161,6 +166,7 @@ public void testSetVariableOnServiceTaskInsideSubProcess() { HistoricVariableInstance variable = query.singleResult(); // the variable is in the process instance scope assertEquals(pi.getId(), variable.getActivityInstanceId()); + assertNull(variable.getTaskId()); testRule.assertProcessEnded(pi.getId()); } @@ -205,6 +211,7 @@ public void testSetVariableLocalOnTaskInsideParallelBranch() { HistoricVariableInstance variable = query.singleResult(); // the variable is in the user task scope assertEquals(taskExecution.getActivityInstanceId(), variable.getActivityInstanceId()); + assertEquals(task.getId(),variable.getTaskId()); taskService.complete(task.getId()); @@ -227,6 +234,7 @@ public void testSetVariableOnTaskInsideParallelBranch() { HistoricVariableInstance variable = query.singleResult(); // the variable is in the process instance scope assertEquals(pi.getId(), variable.getActivityInstanceId()); + assertEquals(task.getId(),variable.getTaskId()); taskService.complete(task.getId()); @@ -244,6 +252,7 @@ public void testSetVariableOnServiceTaskInsideParallelBranch() { HistoricVariableInstance variable = query.singleResult(); // the variable is in the process instance scope assertEquals(pi.getId(), variable.getActivityInstanceId()); + assertNull(variable.getTaskId()); testRule.assertProcessEnded(pi.getId()); } diff --git a/engine/src/test/java/org/camunda/bpm/engine/test/history/HistoricVariableInstanceTest.java b/engine/src/test/java/org/camunda/bpm/engine/test/history/HistoricVariableInstanceTest.java index e7305899f2e..ed0bb835e59 100644 --- a/engine/src/test/java/org/camunda/bpm/engine/test/history/HistoricVariableInstanceTest.java +++ b/engine/src/test/java/org/camunda/bpm/engine/test/history/HistoricVariableInstanceTest.java @@ -672,6 +672,24 @@ public void testBinaryFetchingEnabled() { taskService.deleteTask(newTask.getId(), true); } + @Test + public void testTaskIdInHistoricVariableInstance() { + + Task newTask = taskService.newTask(); + taskService.saveTask(newTask); + + String variableName = "varName"; + taskService.setVariable(newTask.getId(), variableName, "varValue"); + + HistoricVariableInstance variableInstance = historyService.createHistoricVariableInstanceQuery() + .variableName(variableName) + .singleResult(); + + assertEquals(newTask.getId(),variableInstance.getTaskId()); + + taskService.deleteTask(newTask.getId(), true); + } + @Test public void testBinaryFetchingDisabled() { @@ -798,6 +816,7 @@ public void testDisableCustomObjectDeserializationNativeQuery() { for (HistoricVariableInstance variableInstance : variableInstances) { assertNull(variableInstance.getErrorMessage()); + assertEquals(newTask.getId(),variableInstance.getTaskId()); ObjectValue typedValue = (ObjectValue) variableInstance.getTypedValue(); assertNotNull(typedValue); @@ -829,6 +848,7 @@ public void testErrorMessage() { .singleResult(); assertNull(variableInstance.getValue()); + assertEquals(newTask.getId(),variableInstance.getTaskId()); assertNotNull(variableInstance.getErrorMessage()); taskService.deleteTask(newTask.getId(), true); @@ -1315,6 +1335,7 @@ public void testTaskVariableUpdateOrder() { .createHistoricVariableInstanceQuery() .singleResult(); assertNotNull(variable); + assertEquals(taskId, variable.getTaskId()); String variableInstanceId = variable.getId(); @@ -1349,6 +1370,7 @@ public void testTaskVariableUpdateOrder() { .createHistoricVariableInstanceQuery() .singleResult(); assertNotNull(variable); + assertEquals(taskId, variable.getTaskId()); if (isFullHistoryEnabled()) { @@ -1557,6 +1579,7 @@ public void testSetSameVariableUpdateOrder() { .createHistoricVariableInstanceQuery() .singleResult(); assertNotNull(variable); + assertEquals(taskId,variable.getTaskId()); String variableInstanceId = variable.getId(); @@ -1626,6 +1649,8 @@ public void testProcessDefinitionProperty() { assertNotNull(instance.getProcessDefinitionKey()); assertEquals(key, instance.getProcessDefinitionKey()); + assertEquals(taskId,instance.getTaskId()); + assertNotNull(instance.getProcessDefinitionId()); assertEquals(processInstance.getProcessDefinitionId(), instance.getProcessDefinitionId()); @@ -1673,6 +1698,7 @@ public void testCaseDefinitionProperty() { // then (2) assertCaseVariable(key, caseInstance, instance); + assertEquals(taskId,instance.getTaskId()); // when (3) instance = historyService @@ -2312,6 +2338,7 @@ public void testSetDifferentStates() { createdCounter += 1; } else if (variable.getName().equals("bar")) { Assert.assertEquals(HistoricVariableInstance.STATE_DELETED, variable.getState()); + assertEquals(task.getId(),variable.getTaskId()); deletedCounter += 1; } } diff --git a/engine/src/test/java/org/camunda/bpm/engine/test/history/useroperationlog/UserOperationLogQueryTest.java b/engine/src/test/java/org/camunda/bpm/engine/test/history/useroperationlog/UserOperationLogQueryTest.java index 6db1e25ff76..aa2bafe6536 100644 --- a/engine/src/test/java/org/camunda/bpm/engine/test/history/useroperationlog/UserOperationLogQueryTest.java +++ b/engine/src/test/java/org/camunda/bpm/engine/test/history/useroperationlog/UserOperationLogQueryTest.java @@ -1409,7 +1409,7 @@ public void testQueryDeleteVariableHistoryOperationOnTaskOfRunningInstance() { historyService.deleteHistoricVariableInstance(variableInstanceId); // then - verifyHistoricVariableOperationAsserts(1, UserOperationLogEntry.OPERATION_TYPE_DELETE_HISTORY); + verifyHistoricVariableOperationAssertsWithTaskId(1, UserOperationLogEntry.OPERATION_TYPE_DELETE_HISTORY); verifySingleVariableOperationPropertyChange("name", "testVariable", UserOperationLogEntry.OPERATION_TYPE_DELETE_HISTORY); } @@ -1427,7 +1427,7 @@ public void testQueryDeleteVariableHistoryOperationOnTaskOfHistoricInstance() { historyService.deleteHistoricVariableInstance(variableInstanceId); // then - verifyHistoricVariableOperationAsserts(1, UserOperationLogEntry.OPERATION_TYPE_DELETE_HISTORY); + verifyHistoricVariableOperationAssertsWithTaskId(1, UserOperationLogEntry.OPERATION_TYPE_DELETE_HISTORY); verifySingleVariableOperationPropertyChange("name", "testVariable", UserOperationLogEntry.OPERATION_TYPE_DELETE_HISTORY); } @@ -1814,6 +1814,31 @@ private void verifyHistoricVariableOperationAsserts(int countAssertValue, String } } + private void verifyHistoricVariableOperationAssertsWithTaskId(int countAssertValue, String operationType) { + String deploymentId = repositoryService.createDeploymentQuery().singleResult().getId(); + UserOperationLogQuery logQuery = query().entityType(EntityTypes.VARIABLE).operationType(operationType); + assertEquals(countAssertValue, logQuery.count()); + + if(countAssertValue > 1) { + List logEntryList = logQuery.list(); + + for (UserOperationLogEntry logEntry : logEntryList) { + assertEquals(process.getProcessDefinitionId(), logEntry.getProcessDefinitionId()); + assertEquals(process.getProcessInstanceId(), logEntry.getProcessInstanceId()); + assertEquals(deploymentId, logEntry.getDeploymentId()); + assertNotNull(logEntry.getTaskId()); + assertEquals(UserOperationLogEntry.CATEGORY_OPERATOR, logEntry.getCategory()); + } + } else { + UserOperationLogEntry logEntry = logQuery.singleResult(); + assertEquals(process.getProcessDefinitionId(), logEntry.getProcessDefinitionId()); + assertEquals(process.getProcessInstanceId(), logEntry.getProcessInstanceId()); + assertEquals(deploymentId, logEntry.getDeploymentId()); + assertNotNull(logEntry.getTaskId()); + assertEquals(UserOperationLogEntry.CATEGORY_OPERATOR, logEntry.getCategory()); + } + } + private void verifySingleVariableOperationPropertyChange(String property, String newValue, String operationType) { UserOperationLogQuery logQuery = query().entityType(EntityTypes.VARIABLE).operationType(operationType); assertEquals(1, logQuery.count());