diff --git a/jbpm-human-task/jbpm-human-task-core/src/main/java/org/jbpm/services/task/commands/CompleteTaskCommand.java b/jbpm-human-task/jbpm-human-task-core/src/main/java/org/jbpm/services/task/commands/CompleteTaskCommand.java index 3d202d6ac7..4459bdd94a 100644 --- a/jbpm-human-task/jbpm-human-task-core/src/main/java/org/jbpm/services/task/commands/CompleteTaskCommand.java +++ b/jbpm-human-task/jbpm-human-task-core/src/main/java/org/jbpm/services/task/commands/CompleteTaskCommand.java @@ -44,6 +44,8 @@ public class CompleteTaskCommand extends UserGroupCallbackTaskCommand { private static final long serialVersionUID = 412409697422083299L; + + public static final String TASK_OUT_VARS_CONTEXT_KEY = "beforeTaskExecutedOutputVariables"; @XmlJavaTypeAdapter(JaxbMapAdapter.class) @XmlElement @@ -76,6 +78,12 @@ public Void execute(Context cntxt ) { if (task == null) { throw new PermissionDeniedException("Task '" + taskId + "' not found"); } + + if (task.getTaskData().getTaskOutputVariables() != null ) { + Map taskOutputVariablesContext= new HashMap<>(); + taskOutputVariablesContext.putAll(task.getTaskData().getTaskOutputVariables()); + context.getContextData().put(TASK_OUT_VARS_CONTEXT_KEY, taskOutputVariablesContext); + } context.loadTaskVariables(task); diff --git a/jbpm-human-task/jbpm-human-task-core/src/main/java/org/jbpm/services/task/commands/TaskContext.java b/jbpm-human-task/jbpm-human-task-core/src/main/java/org/jbpm/services/task/commands/TaskContext.java index b2776fe914..ecd943c1c7 100644 --- a/jbpm-human-task/jbpm-human-task-core/src/main/java/org/jbpm/services/task/commands/TaskContext.java +++ b/jbpm-human-task/jbpm-human-task-core/src/main/java/org/jbpm/services/task/commands/TaskContext.java @@ -15,6 +15,7 @@ */ package org.jbpm.services.task.commands; +import java.util.HashMap; import java.util.Map; import org.jbpm.services.task.events.TaskEventSupport; @@ -64,6 +65,8 @@ public class TaskContext implements org.kie.internal.task.api.TaskContext, Reque private org.kie.internal.task.api.TaskContext delegate; private String userId; + + private Map contextData; public TaskContext() { } @@ -239,4 +242,11 @@ public String getUserId() { public void setUserId(String userId) { this.userId = userId; } + + public Map getContextData() { + if (contextData == null) { + contextData = new HashMap<>(); + } + return contextData; + } } diff --git a/jbpm-human-task/jbpm-human-task-jpa/src/main/java/org/jbpm/services/task/persistence/TaskTransactionInterceptor.java b/jbpm-human-task/jbpm-human-task-jpa/src/main/java/org/jbpm/services/task/persistence/TaskTransactionInterceptor.java index d68372a474..545f6365a0 100644 --- a/jbpm-human-task/jbpm-human-task-jpa/src/main/java/org/jbpm/services/task/persistence/TaskTransactionInterceptor.java +++ b/jbpm-human-task/jbpm-human-task-jpa/src/main/java/org/jbpm/services/task/persistence/TaskTransactionInterceptor.java @@ -246,6 +246,11 @@ public String getUserId() { public void setUserId(String userId) { this.userId = userId; } + + @Override + public Map getContextData() { + throw new UnsupportedOperationException( "org.jbpm.services.task.persistence.TaskTransactionInterceptor.TransactionContext.getApplicationContext -> TODO" ); + } } public void initTransactionManager(Environment env) { diff --git a/jbpm-test-coverage/src/test/java/org/jbpm/test/functional/task/TaskCompletedListenersTest.java b/jbpm-test-coverage/src/test/java/org/jbpm/test/functional/task/TaskCompletedListenersTest.java new file mode 100644 index 0000000000..d434561765 --- /dev/null +++ b/jbpm-test-coverage/src/test/java/org/jbpm/test/functional/task/TaskCompletedListenersTest.java @@ -0,0 +1,165 @@ +/* + * Copyright 2017 Red Hat, Inc. and/or its affiliates. + * + * 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.jbpm.test.functional.task; + +import org.apache.commons.lang3.mutable.MutableInt; +import org.jbpm.services.task.commands.CompleteTaskCommand; +import org.jbpm.services.task.events.DefaultTaskEventListener; +import org.jbpm.test.JbpmTestCase; +import org.junit.Test; +import org.kie.api.runtime.KieSession; +import org.kie.api.runtime.manager.RuntimeEngine; +import org.kie.api.runtime.process.ProcessInstance; +import org.kie.api.task.TaskEvent; +import org.kie.api.task.TaskLifeCycleEventListener; +import org.kie.api.task.TaskService; +import org.kie.internal.task.api.TaskContext; + +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Test listeners tied to adding assignments - RHPAM-4442 + */ +public class TaskCompletedListenersTest extends JbpmTestCase { + + private KieSession ksession; + private TaskService ts; + + + Map formerVars; + Map actualVars; + + + MutableInt triggeredBeforeTaskCompletedListenerCounter; + + + private static final String PROCESS = "org/jbpm/test/functional/task/HumanTask-simple-with-outputvars.bpmn2"; + private static final String PROCESS_ID = "org.jbpm.test.functional.task.HumanTask_simple_with_outputvars"; + + + private void init() { + createRuntimeManager(PROCESS); + RuntimeEngine runtimeEngine = getRuntimeEngine(); + ksession = runtimeEngine.getKieSession(); + ts = runtimeEngine.getTaskService(); + } +// +// @After +// public void clenaup() { +// if (ksession != null) { +// ksession.dispose(); +// } +// disposeRuntimeManager(); +// } + + @Test + public void testBeforeCompletedListenersRegression() { + DefaultTaskEventListener listener = new DefaultTaskEventListener() { + @Override + public void beforeTaskCompletedEvent(TaskEvent event) { + + putAllNullSafe(actualVars, event.getTask().getTaskData().getTaskOutputVariables()); + triggeredBeforeTaskCompletedListenerCounter.increment(); + + logger.debug("taskOutputVariables: " + event.getTask().getTaskData().getTaskOutputVariables()); + } + }; + + triggeredBeforeTaskCompletedListenerCounter = new MutableInt(0); + + actualVars = new HashMap<>(); + + addTaskEventListener(listener); + + init(); + + ProcessInstance pi = ksession.startProcess(PROCESS_ID); + long pid = pi.getId(); + + assertProcessInstanceActive(pi.getId(), ksession); + assertNodeTriggered(pi.getId(), "Start", "Task"); + + Map outputParams = new HashMap<>(); + outputParams.put("Output", "RHPAM-4446"); + for (long taskId : ts.getTasksByProcessInstanceId(pid)) { + ts.start(taskId, "john"); + ts.complete(taskId, "john", outputParams); + } + + assertThat(triggeredBeforeTaskCompletedListenerCounter.getValue()).isEqualTo(1); + assertThat(actualVars).hasSize(1); + assertThat(actualVars).containsKey("Output"); + } + + @Test + public void testBeforeCompletedListener() { + triggeredBeforeTaskCompletedListenerCounter = new MutableInt(0); + + formerVars = new HashMap<>(); + actualVars = new HashMap<>(); + + DefaultTaskEventListener listener = new DefaultTaskEventListener() { + @Override + public void beforeTaskCompletedEvent(TaskEvent event) { + + putAllNullSafe(actualVars, event.getTask().getTaskData().getTaskOutputVariables()); + Map contextData = event.getTaskContext().getContextData(); + Map taskOutputVarsCtx = (Map) contextData.get(CompleteTaskCommand.TASK_OUT_VARS_CONTEXT_KEY); + putAllNullSafe(formerVars, taskOutputVarsCtx); + triggeredBeforeTaskCompletedListenerCounter.increment(); + + logger.debug("taskOutputVariables: " + event.getTask().getTaskData().getTaskOutputVariables()); + logger.debug("before completed TaskOutputVariables: " + event.getTask().getTaskData().getTaskOutputVariables()); + } + }; + + addTaskEventListener(listener); + + init(); + + ProcessInstance pi = ksession.startProcess(PROCESS_ID); + long pid = pi.getId(); + + assertProcessInstanceActive(pi.getId(), ksession); + assertNodeTriggered(pi.getId(), "Start", "Task"); + + Map outputParams = new HashMap<>(); + outputParams.put("Output", "RHPAM-4446"); + for (long taskId : ts.getTasksByProcessInstanceId(pid)) { + ts.start(taskId, "john"); + ts.complete(taskId, "john", outputParams); + } + + assertThat(triggeredBeforeTaskCompletedListenerCounter.getValue()).isEqualTo(1); + assertThat(formerVars).hasSize(0); + assertThat(formerVars).doesNotContainKey("Output"); + + assertThat(actualVars).hasSize(1); + assertThat(actualVars).containsKey("Output"); + + } + + private void putAllNullSafe(Map target, Map source) { + if ((source == null || target == null)) { + return; + } + target.putAll(source); + } +} diff --git a/jbpm-test-coverage/src/test/resources/org/jbpm/test/functional/task/HumanTask-simple-with-outputvars.bpmn2 b/jbpm-test-coverage/src/test/resources/org/jbpm/test/functional/task/HumanTask-simple-with-outputvars.bpmn2 new file mode 100644 index 0000000000..e92e787c05 --- /dev/null +++ b/jbpm-test-coverage/src/test/resources/org/jbpm/test/functional/task/HumanTask-simple-with-outputvars.bpmn2 @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + _CD6217FC-9A99-41DD-BB7C-3E7D686C94BB + + + + + + + + _0AC41881-638D-4232-A208-1365BFEC14E9 + _CD6217FC-9A99-41DD-BB7C-3E7D686C94BB + + + + + + + _93BBB96D-DD25-40BC-8A7A-16B1548A0402_TaskNameInputX + _93BBB96D-DD25-40BC-8A7A-16B1548A0402_origOutputNameInputX + _93BBB96D-DD25-40BC-8A7A-16B1548A0402_SkippableInputX + + + _93BBB96D-DD25-40BC-8A7A-16B1548A0402_originalOutputNameOutputX + + + + _93BBB96D-DD25-40BC-8A7A-16B1548A0402_TaskNameInputX + + + + + + + originalOutput + _93BBB96D-DD25-40BC-8A7A-16B1548A0402_origOutputNameInputX + + + _93BBB96D-DD25-40BC-8A7A-16B1548A0402_SkippableInputX + + + + + + + _93BBB96D-DD25-40BC-8A7A-16B1548A0402_originalOutputNameOutputX + originalOutput + + + + john + + + + + + + + + + _0AC41881-638D-4232-A208-1365BFEC14E9 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + _rV5_YNiqEDuJ-N6lPK_Veg + _rV5_YNiqEDuJ-N6lPK_Veg + + \ No newline at end of file