Java tutorial
/** * Copyright (C) 2015 BonitaSoft S.A. * BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble * This library is free software; you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Foundation * version 2.1 of the License. * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301, USA. */ package org.bonitasoft.engine.activity; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.apache.commons.io.IOUtils; import org.bonitasoft.engine.BPMRemoteTests; import org.bonitasoft.engine.TestWithTechnicalUser; import org.bonitasoft.engine.bpm.bar.BarResource; import org.bonitasoft.engine.bpm.bar.BusinessArchive; import org.bonitasoft.engine.bpm.bar.BusinessArchiveBuilder; import org.bonitasoft.engine.bpm.connector.ConnectorEvent; import org.bonitasoft.engine.bpm.data.DataInstance; import org.bonitasoft.engine.bpm.data.DataNotFoundException; import org.bonitasoft.engine.bpm.flownode.ActivityInstance; import org.bonitasoft.engine.bpm.flownode.CallActivityDefinition; import org.bonitasoft.engine.bpm.flownode.CallActivityInstance; import org.bonitasoft.engine.bpm.flownode.FlowNodeInstance; import org.bonitasoft.engine.bpm.flownode.FlowNodeType; import org.bonitasoft.engine.bpm.flownode.GatewayType; import org.bonitasoft.engine.bpm.flownode.HumanTaskInstance; import org.bonitasoft.engine.bpm.process.ArchivedProcessInstance; import org.bonitasoft.engine.bpm.process.ArchivedProcessInstancesSearchDescriptor; import org.bonitasoft.engine.bpm.process.DesignProcessDefinition; import org.bonitasoft.engine.bpm.process.InvalidProcessDefinitionException; import org.bonitasoft.engine.bpm.process.ProcessDefinition; import org.bonitasoft.engine.bpm.process.ProcessInstance; import org.bonitasoft.engine.bpm.process.ProcessInstanceCriterion; import org.bonitasoft.engine.bpm.process.ProcessInstanceNotFoundException; import org.bonitasoft.engine.bpm.process.SubProcessDefinition; import org.bonitasoft.engine.bpm.process.impl.CallActivityBuilder; import org.bonitasoft.engine.bpm.process.impl.EndEventDefinitionBuilder; import org.bonitasoft.engine.bpm.process.impl.IntermediateCatchEventDefinitionBuilder; import org.bonitasoft.engine.bpm.process.impl.ProcessDefinitionBuilder; import org.bonitasoft.engine.connectors.TestConnectorWithOutput; import org.bonitasoft.engine.exception.BonitaException; import org.bonitasoft.engine.exception.DeletionException; import org.bonitasoft.engine.exception.ProcessInstanceHierarchicalDeletionException; import org.bonitasoft.engine.expression.Expression; import org.bonitasoft.engine.expression.ExpressionBuilder; import org.bonitasoft.engine.expression.ExpressionConstants; import org.bonitasoft.engine.expression.ExpressionType; import org.bonitasoft.engine.expression.InvalidExpressionException; import org.bonitasoft.engine.identity.User; import org.bonitasoft.engine.io.IOUtil; import org.bonitasoft.engine.operation.LeftOperandBuilder; import org.bonitasoft.engine.operation.Operation; import org.bonitasoft.engine.operation.OperationBuilder; import org.bonitasoft.engine.operation.OperatorType; import org.bonitasoft.engine.search.Order; import org.bonitasoft.engine.search.SearchOptionsBuilder; import org.bonitasoft.engine.test.BuildTestUtil; import org.bonitasoft.engine.test.TestStates; import org.bonitasoft.engine.test.annotation.Cover; import org.bonitasoft.engine.test.annotation.Cover.BPMNConcept; import org.bonitasoft.engine.test.wait.WaitForFinalArchivedActivity; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * @author Elias Ricken de Medeiros * @author Celine Souchet */ @SuppressWarnings("javadoc") public class CallActivityIT extends TestWithTechnicalUser { private static final String CONNECTOR_OUTPUT_NAME = "output1"; private User cebolinha; private User cascao; @Override @Before public void before() throws Exception { super.before(); cebolinha = createUser("cebolinha", "bpm"); cascao = createUser("cascao", "bpm"); } @Override @After public void after() throws Exception { deleteUsers(cebolinha, cascao); super.after(); } private ProcessDefinition getSimpleProcess(final String ACTOR_NAME, final String processName, final String processVersion, final boolean terminateEnd) throws BonitaException { final Expression clientNumberExpr = new ExpressionBuilder().createConstantIntegerExpression(10); final Expression protocolNumberExpr = new ExpressionBuilder().createConstantIntegerExpression(305020); final ProcessDefinitionBuilder processDefBuilder = new ProcessDefinitionBuilder() .createNewInstance(processName, processVersion); processDefBuilder.addActor(ACTOR_NAME); processDefBuilder.addShortTextData("firstName", null); processDefBuilder.addShortTextData("lastName", null); processDefBuilder.addShortTextData("calledProcessData", null); processDefBuilder.addIntegerData("clientNumber", clientNumberExpr); processDefBuilder.addIntegerData("protocolNumber", protocolNumberExpr); processDefBuilder.addStartEvent("tStart"); processDefBuilder.addUserTask("tStep1", ACTOR_NAME); final EndEventDefinitionBuilder endEvent = processDefBuilder.addEndEvent("tEnd"); if (terminateEnd) { endEvent.addTerminateEventTrigger(); } processDefBuilder.addTransition("tStart", "tStep1"); processDefBuilder.addTransition("tStep1", "tEnd"); final ProcessDefinition targetProcessDefinition = deployAndEnableProcessWithActor(processDefBuilder.done(), ACTOR_NAME, cebolinha); return targetProcessDefinition; } private ProcessDefinition buildProcessWithCallActivity(final boolean addInputOperations, final boolean addOutputOperations, final String processName, final String targetProcessName, final int loopNb, final String strTargetVersion) throws BonitaException { final Expression targetProcessNameExpr = new ExpressionBuilder() .createConstantStringExpression(targetProcessName); Expression targetProcessVersionExpr = null; if (strTargetVersion != null) { targetProcessVersionExpr = new ExpressionBuilder().createConstantStringExpression(strTargetVersion); } final Expression expressionTrue = new ExpressionBuilder().createConstantBooleanExpression(true); final ProcessDefinitionBuilder processDefBuilder = new ProcessDefinitionBuilder() .createNewInstance(processName, PROCESS_VERSION); processDefBuilder.addShortTextData("fName", null); processDefBuilder.addShortTextData("lName", null); processDefBuilder.addIntegerData("cNumber", null); processDefBuilder.addIntegerData("pNumber", null); processDefBuilder.addActor(ACTOR_NAME); processDefBuilder.addStartEvent("start"); final CallActivityBuilder callActivityBuilder = processDefBuilder.addCallActivity("callActivity", targetProcessNameExpr, targetProcessVersionExpr); addDataInputOperationsIfNeed(addInputOperations, callActivityBuilder); callActivityBuilder.addShortTextData("callActivityData", new ExpressionBuilder().createConstantStringExpression("defaultValue")); if (loopNb > 0) { callActivityBuilder.addLoop(false, expressionTrue, new ExpressionBuilder().createConstantIntegerExpression(loopNb)); } addDataOutputOperationIfNeed(addOutputOperations, callActivityBuilder); processDefBuilder.addUserTask("step1", ACTOR_NAME); processDefBuilder.addEndEvent("end"); processDefBuilder.addTransition("start", "callActivity"); processDefBuilder.addTransition("callActivity", "step1"); processDefBuilder.addTransition("step1", "end"); return deployAndEnableProcessWithActor(processDefBuilder.done(), ACTOR_NAME, cascao); } private ProcessDefinition buildProcessWithCallActivity(final String processName, final String targetProcessName, final String strTargetVersion) throws BonitaException { return buildProcessWithCallActivity(false, false, processName, targetProcessName, 0, strTargetVersion); } private ProcessDefinition buildProcessWithCallActivity(final String processName, final String targetProcessName, int loopNb, final String strTargetVersion) throws BonitaException { return buildProcessWithCallActivity(false, false, processName, targetProcessName, loopNb, strTargetVersion); } private void addDataOutputOperationIfNeed(final boolean addOutputOperations, final CallActivityBuilder callActivityBuilder) throws InvalidExpressionException { if (addOutputOperations) { final Operation setClientNumber = BuildTestUtil.buildAssignOperation("cNumber", "clientNumber", ExpressionType.TYPE_VARIABLE, Integer.class.getName()); final Operation setProtocalNumber = BuildTestUtil.buildAssignOperation("pNumber", "protocolNumber", ExpressionType.TYPE_VARIABLE, Integer.class.getName()); callActivityBuilder.addDataOutputOperation(setClientNumber); callActivityBuilder.addDataOutputOperation(setProtocalNumber); } } private void addDataInputOperationsIfNeed(final boolean addInputOperations, final CallActivityBuilder callActivityBuilder) throws InvalidExpressionException { if (addInputOperations) { final Operation setFirstName = BuildTestUtil.buildAssignOperation("firstName", "fName", ExpressionType.TYPE_VARIABLE, String.class.getName()); final Operation setLastName = BuildTestUtil.buildAssignOperation("lastName", "lName", ExpressionType.TYPE_VARIABLE, String.class.getName()); final Operation mapFromCallActivity = BuildTestUtil.buildAssignOperation("calledProcessData", "callActivityData", ExpressionType.TYPE_VARIABLE, String.class.getName()); callActivityBuilder.addDataInputOperation(setFirstName); callActivityBuilder.addDataInputOperation(setLastName); callActivityBuilder.addDataInputOperation(mapFromCallActivity); } } /* * Most simple case : * No Inputs or Outputs for the callActivity * See executeCallAtivityUntilEndOfProcess for details. */ @Cover(classes = { CallActivityDefinition.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity" }, jira = "") @Test public void callActivity() throws Exception { executeCallAtivityUntilEndOfProcess(false, false, PROCESS_VERSION, false); } /* * Only Inputs for the callActivity * See executeCallAtivityUntilEndOfProcess for details. */ @Cover(classes = { CallActivityDefinition.class }, concept = BPMNConcept.ACTIVITIES, keywords = { "Call Activity" }, jira = "") @Test public void callActivityWithDataInputOperations() throws Exception { executeCallAtivityUntilEndOfProcess(true, false, PROCESS_VERSION, false); } /* * Only Outputs for the callActivity * See executeCallAtivityUntilEndOfProcess for details. */ @Cover(classes = { CallActivityDefinition.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity" }, jira = "") @Test public void callActivityWithDataOutputOperations() throws Exception { executeCallAtivityUntilEndOfProcess(false, true, PROCESS_VERSION, false); } /* * Only Outputs for the callActivity * See executeCallAtivityUntilEndOfProcess for details. */ @Cover(classes = { CallActivityDefinition.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity" }, jira = "") @Test public void callActivityWithDataOutputOperationsAndTerminateEnd() throws Exception { executeCallAtivityUntilEndOfProcess(false, true, PROCESS_VERSION, true); } /* * Only Outputs for the callActivity * See executeCallAtivityUntilEndOfProcess for details. */ @Cover(classes = { CallActivityDefinition.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity" }, jira = "") @Test public void callActivityWithDataInputAndOutputOperationsAndVersion2() throws Exception { executeCallAtivityUntilEndOfProcess(true, true, "2.0", false); } @Cover(classes = { CallActivityDefinition.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity", "Gateway", "Message" }, jira = "ENGINE-1713") @Test public void callActivityAndGatewayAndMessageAndIntermediateEvent() throws Exception { ProcessDefinition mainProcessDefinition = null; ProcessDefinition receiveProcessDefinition = null; ProcessDefinition sendProcessDefinition = null; try { final Expression processVersionExpr = new ExpressionBuilder() .createConstantStringExpression(PROCESS_VERSION); // Main process final ProcessDefinitionBuilder mainProcessDefinitionBuilder = new ProcessDefinitionBuilder() .createNewInstance("Main", PROCESS_VERSION); mainProcessDefinitionBuilder.addActor(ACTOR_NAME); mainProcessDefinitionBuilder.addStartEvent("MainStart").addEndEvent("MainEnd"); mainProcessDefinitionBuilder.addGateway("Gateway1", GatewayType.PARALLEL).addGateway("Gateway2", GatewayType.PARALLEL); // Send callActivity final Expression sendExpr = new ExpressionBuilder().createConstantStringExpression("Send"); mainProcessDefinitionBuilder.addCallActivity("Send", sendExpr, processVersionExpr); // Receive callActivity final Expression receiveExpr = new ExpressionBuilder().createConstantStringExpression("Receive"); mainProcessDefinitionBuilder.addCallActivity("Receive", receiveExpr, processVersionExpr); // Transitions mainProcessDefinitionBuilder.addTransition("MainStart", "Gateway1").addTransition("Gateway1", "Send") .addTransition("Gateway1", "Receive").addTransition("Send", "Gateway2") .addTransition("Receive", "Gateway2").addTransition("Gateway2", "MainEnd"); mainProcessDefinition = deployAndEnableProcessWithActor(mainProcessDefinitionBuilder.done(), ACTOR_NAME, cascao); // Receive process final ProcessDefinitionBuilder receiveProcessDefinitionBuilder = new ProcessDefinitionBuilder() .createNewInstance("Receive", PROCESS_VERSION); receiveProcessDefinitionBuilder.addActor(ACTOR_NAME); receiveProcessDefinitionBuilder.addStartEvent("ReceiveStart").addEndEvent("ReceiveEnd"); receiveProcessDefinitionBuilder.addUserTask("Read", ACTOR_NAME); final Operation operation = BuildTestUtil.buildAssignOperation("copymsg", "MSG", ExpressionType.TYPE_VARIABLE, String.class.getName()); final IntermediateCatchEventDefinitionBuilder intermediateCatchEvent = receiveProcessDefinitionBuilder .addIntermediateCatchEvent("ReceiveMsg"); intermediateCatchEvent.addMessageEventTrigger("ping").addOperation(operation); intermediateCatchEvent.addLongTextData("copymsg", null); // Transitions receiveProcessDefinitionBuilder.addTransition("ReceiveStart", "ReceiveMsg") .addTransition("ReceiveMsg", "Read").addTransition("Read", "ReceiveEnd"); receiveProcessDefinition = deployAndEnableProcessWithActor(receiveProcessDefinitionBuilder.done(), ACTOR_NAME, cascao); // Send process final ProcessDefinitionBuilder sendProcessDefinitionBuilder = new ProcessDefinitionBuilder() .createNewInstance("Send", PROCESS_VERSION); sendProcessDefinitionBuilder.addActor(ACTOR_NAME); sendProcessDefinitionBuilder.addStartEvent("SendStart"); final Expression msgData = new ExpressionBuilder().createConstantStringExpression("data"); sendProcessDefinitionBuilder.addLongTextData("msg", msgData); sendProcessDefinitionBuilder.addUserTask("Step1", ACTOR_NAME); final Expression targetProcess = new ExpressionBuilder().createConstantStringExpression("Receive"); final Expression targetFlowNode = new ExpressionBuilder().createConstantStringExpression("ReceiveMsg"); final Expression displayName = new ExpressionBuilder().createConstantStringExpression("MSG"); final Expression messageContent = new ExpressionBuilder().createDataExpression("msg", "java.lang.String"); sendProcessDefinitionBuilder.addEndEvent("SendMsgEnd") .addMessageEventTrigger("ping", targetProcess, targetFlowNode) .addMessageContentExpression(displayName, messageContent); // Transitions sendProcessDefinitionBuilder.addTransition("SendStart", "Step1").addTransition("Step1", "SendMsgEnd"); sendProcessDefinition = deployAndEnableProcessWithActor(sendProcessDefinitionBuilder.done(), ACTOR_NAME, cascao); assertThat(getProcessAPI().getNumberOfProcessInstances()).isEqualTo(0L); final ProcessInstance mainProcessInstance = getProcessAPI().startProcess(cascao.getId(), mainProcessDefinition.getId()); waitForUserTaskAndExecuteIt("Step1", cascao); final ActivityInstance read = waitForUserTaskAndGetIt("Read"); final DataInstance copyMsg = getProcessAPI().getProcessDataInstance("copymsg", read.getParentProcessInstanceId()); assertThat(copyMsg.getValue()).isEqualTo("data"); assignAndExecuteStep(read, cascao.getId()); waitForProcessToFinish(mainProcessInstance); } finally { disableAndDeleteProcess(mainProcessDefinition, receiveProcessDefinition, sendProcessDefinition); } } @Cover(classes = { CallActivityDefinition.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity", "Gateway", "Message", "ReceiveTask", "SendTask" }, jira = "ENGINE-1714") @Test public void callActivityAndGatewayAndMessageAndTask() throws Exception { ProcessDefinition mainProcessDefinition = null; ProcessDefinition receiveProcessDefinition = null; ProcessDefinition sendProcessDefinition = null; try { final Expression processVersionExpr = new ExpressionBuilder() .createConstantStringExpression(PROCESS_VERSION); // Main process final ProcessDefinitionBuilder mainProcessDefinitionBuilder = new ProcessDefinitionBuilder() .createNewInstance("Main", PROCESS_VERSION); mainProcessDefinitionBuilder.addActor(ACTOR_NAME); mainProcessDefinitionBuilder.addStartEvent("MainStart").addEndEvent("MainEnd"); mainProcessDefinitionBuilder.addGateway("Gateway1", GatewayType.PARALLEL).addGateway("Gateway2", GatewayType.PARALLEL); // Send callActivity final Expression sendExpr = new ExpressionBuilder().createConstantStringExpression("Send"); mainProcessDefinitionBuilder.addCallActivity("Send", sendExpr, processVersionExpr); // Receive callActivity final Expression receiveExpr = new ExpressionBuilder().createConstantStringExpression("Receive"); mainProcessDefinitionBuilder.addCallActivity("Receive", receiveExpr, processVersionExpr); // Transitions mainProcessDefinitionBuilder.addTransition("MainStart", "Gateway1").addTransition("Gateway1", "Send") .addTransition("Gateway1", "Receive").addTransition("Send", "Gateway2") .addTransition("Receive", "Gateway2").addTransition("Gateway2", "MainEnd"); mainProcessDefinition = deployAndEnableProcessWithActor(mainProcessDefinitionBuilder.done(), ACTOR_NAME, cascao); // Receive process final ProcessDefinitionBuilder receiveProcessDefinitionBuilder = new ProcessDefinitionBuilder() .createNewInstance("Receive", PROCESS_VERSION); receiveProcessDefinitionBuilder.addActor(ACTOR_NAME); receiveProcessDefinitionBuilder.addStartEvent("ReceiveStart").addEndEvent("ReceiveEnd"); receiveProcessDefinitionBuilder.addLongTextData("copymsg", null); receiveProcessDefinitionBuilder.addUserTask("Read", ACTOR_NAME); final Operation operation = BuildTestUtil.buildAssignOperation("copymsg", "MSG2", ExpressionType.TYPE_VARIABLE, String.class.getName()); receiveProcessDefinitionBuilder.addReceiveTask("ReceiveMsg", "ping2").addMessageOperation(operation); // Transitions receiveProcessDefinitionBuilder.addTransition("ReceiveStart", "ReceiveMsg") .addTransition("ReceiveMsg", "Read").addTransition("Read", "ReceiveEnd"); receiveProcessDefinition = deployAndEnableProcessWithActor(receiveProcessDefinitionBuilder.done(), ACTOR_NAME, cascao); // Send process final ProcessDefinitionBuilder sendProcessDefinitionBuilder = new ProcessDefinitionBuilder() .createNewInstance("Send", PROCESS_VERSION); sendProcessDefinitionBuilder.addActor(ACTOR_NAME); sendProcessDefinitionBuilder.addStartEvent("SendStart"); final Expression msgData = new ExpressionBuilder().createConstantStringExpression("data"); sendProcessDefinitionBuilder.addLongTextData("msg", msgData); sendProcessDefinitionBuilder.addUserTask("Step1", ACTOR_NAME); final Expression targetProcess = new ExpressionBuilder().createConstantStringExpression("Receive"); final Expression targetFlowNode = new ExpressionBuilder().createConstantStringExpression("ReceiveMsg"); final Expression displayName = new ExpressionBuilder().createConstantStringExpression("MSG2"); final Expression messageContent = new ExpressionBuilder().createDataExpression("msg", "java.lang.String"); sendProcessDefinitionBuilder.addSendTask("SendMsgEnd", "ping2", targetProcess) .setTargetFlowNode(targetFlowNode).addMessageContentExpression(displayName, messageContent); // Transitions sendProcessDefinitionBuilder.addTransition("SendStart", "Step1").addTransition("Step1", "SendMsgEnd"); sendProcessDefinition = deployAndEnableProcessWithActor(sendProcessDefinitionBuilder.done(), ACTOR_NAME, cascao); assertThat(getProcessAPI().getNumberOfProcessInstances()).isEqualTo(0L); final ProcessInstance mainProcessInstance = getProcessAPI().startProcess(cascao.getId(), mainProcessDefinition.getId()); waitForUserTaskAndExecuteIt("Step1", cascao); final ActivityInstance read = waitForUserTaskAndGetIt("Read"); final DataInstance copyMsg = getProcessAPI().getProcessDataInstance("copymsg", read.getParentProcessInstanceId()); assertThat(copyMsg.getValue()).isEqualTo("data"); assignAndExecuteStep(read, cascao.getId()); waitForProcessToFinish(mainProcessInstance); } finally { disableAndDeleteProcess(mainProcessDefinition, receiveProcessDefinition, sendProcessDefinition); } } /* * Create a call activity which map some data between child and parent. * Execute an operation using one of this data. * -> operation must be executed after the data mapping is executed */ @Cover(classes = { CallActivityDefinition.class }, concept = BPMNConcept.CALL_ACTIVITY, jira = "ENGINE-878", keywords = { "Data mapping with operations execution order" }) @Test public void callActivityWithDataOutputAndOperationAreExecutedInTheGoodOrder() throws Exception { final ProcessDefinition targetProcessDef = getSimpleProcess(ACTOR_NAME, "targetProcess", PROCESS_VERSION, false); final Expression targetProcessNameExpr = new ExpressionBuilder() .createConstantStringExpression("targetProcess"); final Expression targetProcessVersionExpr = new ExpressionBuilder() .createConstantStringExpression(PROCESS_VERSION); final ProcessDefinitionBuilder processDefBuilder = new ProcessDefinitionBuilder() .createNewInstance("processWithCallActivity", PROCESS_VERSION); processDefBuilder.addIntegerData("cNumber", new ExpressionBuilder().createConstantIntegerExpression(125)); processDefBuilder.addIntegerData("pNumber", null); processDefBuilder.addIntegerData("dataInitWithCNumber", new ExpressionBuilder().createConstantIntegerExpression(12)); processDefBuilder.addActor(ACTOR_NAME); processDefBuilder.addStartEvent("start"); final CallActivityBuilder callActivityBuilder = processDefBuilder.addCallActivity("callActivity", targetProcessNameExpr, targetProcessVersionExpr); addDataOutputOperationIfNeed(true, callActivityBuilder); callActivityBuilder.addOperation(new OperationBuilder().createSetDataOperation("dataInitWithCNumber", new ExpressionBuilder().createDataExpression("cNumber", Integer.class.getName()))); processDefBuilder.addUserTask("step1", ACTOR_NAME); processDefBuilder.addEndEvent("end"); processDefBuilder.addTransition("start", "callActivity"); processDefBuilder.addTransition("callActivity", "step1"); processDefBuilder.addTransition("step1", "end"); final ProcessDefinition callingProcessDef = deployAndEnableProcessWithActor(processDefBuilder.done(), ACTOR_NAME, cascao); final ProcessInstance callingProcessInstance = getProcessAPI().startProcess(callingProcessDef.getId()); // execute process until step1 waitForUserTaskAndExecuteIt(callingProcessInstance, "tStep1", cebolinha); waitForUserTask(callingProcessInstance, "step1"); /* * check the data have the value of the clientNumber of the called process * the set of data should be like this: * targetProcess:clientNumber(10) -> callingProcess:cNumber(was 125) * callingProcess:cNumber(10) -> callingProcess:dataInitWithCNumber(was 12) */ assertThat(getProcessAPI().getProcessDataInstance("dataInitWithCNumber", callingProcessInstance.getId()) .getValue()).isEqualTo(Integer.valueOf(10)); disableAndDeleteProcess(callingProcessDef, targetProcessDef); } /* * 1 parent process : callingProcess : startEvent(start) -> callActivity -> userTask(step1) -> endEvent(end). * 1 called process : targetProcess : startEvent(tStart) -> userTask(tStep1) -> endEvent(tEnd). * checks : No instances of a process exist, 2 process instances (callingProcess starts and set off targetProcess of call activity), * callingProcess stopped on the call activity, targetProcess is executing, callingProcess is the root process of targetProcess, * call activity called the callProcess, callingProcess continues and reaches user task, targetProcess is finished, the user task is * the one from the callingProcess, calling Process is finished. */ private void executeCallAtivityUntilEndOfProcess(final boolean addInputOperations, final boolean addOutputOperations, final String strTargetVersion, final boolean terminateEnd) throws Exception { final ProcessDefinition targetProcessDef1 = getSimpleProcess(ACTOR_NAME, "targetProcess", PROCESS_VERSION, terminateEnd); final ProcessDefinition targetProcessDef3 = getSimpleProcess(ACTOR_NAME, "targetProcess", "3.0", terminateEnd); final ProcessDefinition targetProcessDef2 = getSimpleProcess(ACTOR_NAME, "targetProcess", "2.0", terminateEnd); final ProcessDefinition callingProcessDef = buildProcessWithCallActivity(addInputOperations, addOutputOperations, "callingProcess", "targetProcess", 0, strTargetVersion); assertThat(getProcessAPI().getNumberOfProcessInstances()).isEqualTo(0L); final List<Operation> operations = getStartOperations(); final ProcessInstance callingProcessInstance = getProcessAPI().startProcess(callingProcessDef.getId(), operations, null); if (strTargetVersion != null && strTargetVersion.contentEquals("4.0")) { checkNbOfProcessInstances(2, ProcessInstanceCriterion.NAME_DESC); final List<ProcessInstance> processInstances = getProcessAPI().getProcessInstances(0, 10, ProcessInstanceCriterion.NAME_DESC); assertThat(processInstances).hasSize(1); waitForFlowNodeInFailedState(callingProcessInstance, "callActivity"); return; } checkNbOfProcessInstances(2, ProcessInstanceCriterion.NAME_DESC); final List<ProcessInstance> processInstances = getProcessAPI().getProcessInstances(0, 10, ProcessInstanceCriterion.NAME_DESC); assertThat(processInstances).hasSize(2); // two instances are expected calling and target processes final ProcessInstance targetPI = processInstances.get(0); // System.out.println("Version of the definition of targetProcess : " // + getProcessAPI().getProcessDefinition(targetPI.getProcessDefinitionId()).getVersion()); if (strTargetVersion == null || strTargetVersion.contentEquals("2.0")) { assertThat(targetPI.getProcessDefinitionId()).isEqualTo(targetProcessDef2.getId()); } else if (strTargetVersion.contentEquals(PROCESS_VERSION)) { assertThat(targetPI.getProcessDefinitionId()).isEqualTo(targetProcessDef1.getId()); } final FlowNodeInstance callActivityInstance = waitForFlowNodeInExecutingState(callingProcessInstance, "callActivity", true); assertThat(targetPI.getRootProcessInstanceId()).isEqualTo(callingProcessInstance.getId()); assertThat(targetPI.getCallerId()).isEqualTo(callActivityInstance.getId()); ActivityInstance activityInstance = waitForUserTaskAndGetIt(callingProcessInstance, "tStep1"); assertThat(activityInstance.getParentProcessInstanceId()).isEqualTo(targetPI.getId()); assertThat(activityInstance.getRootContainerId()).isEqualTo(callingProcessInstance.getId()); checkDataInputOperations(addInputOperations, targetPI); // execute step in the target process assignAndExecuteStep(activityInstance, cebolinha.getId()); activityInstance = waitForUserTaskAndGetIt(callingProcessInstance, "step1"); checkOutputOperations(addOutputOperations, callingProcessInstance); waitForProcessToFinish(targetPI); assertThat(activityInstance.getParentProcessInstanceId()).isEqualTo(callingProcessInstance.getId()); assignAndExecuteStep(activityInstance, cascao.getId()); waitForProcessToFinish(callingProcessInstance); disableAndDeleteProcess(callingProcessDef, targetProcessDef1, targetProcessDef2, targetProcessDef3); } private List<Operation> getStartOperations() throws InvalidExpressionException { final ArrayList<Operation> operations = new ArrayList<Operation>(2); operations.add(BuildTestUtil.buildAssignOperation("fName", "Fulano", ExpressionType.TYPE_CONSTANT, String.class.getName())); operations.add(BuildTestUtil.buildAssignOperation("lName", "de Tal", ExpressionType.TYPE_CONSTANT, String.class.getName())); return operations; } private void checkOutputOperations(final boolean addOutputOperations, final ProcessInstance callingProcessInstance) throws Exception { if (addOutputOperations) { final DataInstance clientNumberData = getProcessAPI().getProcessDataInstance("cNumber", callingProcessInstance.getId()); final DataInstance protocolNumberData = getProcessAPI().getProcessDataInstance("pNumber", callingProcessInstance.getId()); assertThat(clientNumberData.getValue()).isEqualTo(10); assertThat(protocolNumberData.getValue()).isEqualTo(305020); } } private void checkDataInputOperations(final boolean addInputOperations, final ProcessInstance targetPI) throws DataNotFoundException { if (addInputOperations) { final DataInstance firstNameData = getProcessAPI().getProcessDataInstance("firstName", targetPI.getId()); final DataInstance lastNameData = getProcessAPI().getProcessDataInstance("lastName", targetPI.getId()); final DataInstance calledProcessData = getProcessAPI().getProcessDataInstance("calledProcessData", targetPI.getId()); assertThat(firstNameData.getValue()).isEqualTo("Fulano"); assertThat(lastNameData.getValue()).isEqualTo("de Tal"); assertThat(calledProcessData.getValue()).isEqualTo("defaultValue"); } } private void variableMultiLevelCallActivity(final int nbLevel) throws Exception { final ProcessDefinition[] processDefLevels = new ProcessDefinition[nbLevel]; for (int i = 0; i < nbLevel - 1; i++) { processDefLevels[i] = buildProcessWithCallActivity("processLevel" + i, "processLevel" + (i + 1), PROCESS_VERSION); } processDefLevels[nbLevel - 1] = getSimpleProcess(ACTOR_NAME, "processLevel" + (nbLevel - 1), PROCESS_VERSION, false); final List<Operation> operations = getStartOperations(); assertThat(getProcessAPI().getNumberOfProcessInstances()).isEqualTo(0L); final ProcessInstance[] procInstLevels = new ProcessInstance[nbLevel]; procInstLevels[0] = getProcessAPI().startProcess(processDefLevels[0].getId(), operations, null); checkNbOfProcessInstances(nbLevel, ProcessInstanceCriterion.NAME_DESC); final List<ProcessInstance> processInstances = getProcessAPI().getProcessInstances(0, nbLevel, ProcessInstanceCriterion.NAME_ASC); // if nbLevel>10 use assertThat(processInstances).hasSize(nbLevel); for (int i = 0; i < nbLevel; i++) { procInstLevels[i] = processInstances.get(i); assertThat(procInstLevels[i].getProcessDefinitionId()).as("Level of process : " + i) .isEqualTo(processDefLevels[i].getId()); } waitForUserTaskAndExecuteIt(procInstLevels[0], "tStep1", cebolinha); waitForProcessToFinish(procInstLevels[nbLevel - 1]); for (int i = nbLevel - 2; i >= 0; i--) { waitForUserTaskAndExecuteIt(procInstLevels[0], "step1", cascao); waitForProcessToFinish(procInstLevels[i]); } disableAndDeleteProcess(processDefLevels); } /* * Tested until 200, works ! */ @Cover(classes = { CallActivityDefinition.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity" }, jira = "") @Test public void multiLevelCallActivity() throws Exception { variableMultiLevelCallActivity(10); } @Cover(classes = { CallActivityDefinition.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity" }, jira = "") @Test public void callUndeployedProcess() throws Exception { final ProcessDefinition processDef = buildProcessWithCallActivity("callingProcess", "unDeployedProcess", PROCESS_VERSION); assertThat(getProcessAPI().getNumberOfProcessInstances()).isEqualTo(0L); final ProcessInstance processInstance = getProcessAPI().startProcess(processDef.getId()); final List<ProcessInstance> processInstances = getProcessAPI().getProcessInstances(0, 10, ProcessInstanceCriterion.NAME_DESC); assertThat(processInstances).hasSize(1); final ActivityInstance waitForTaskToFail = waitForTaskToFail(processInstance); assertThat(waitForTaskToFail.getState()).isEqualTo(TestStates.FAILED.getStateName()); disableAndDeleteProcess(processDef); } private void callActivityInALoop(final int nbLoop) throws Exception { final ProcessDefinition targetProcessDef = getSimpleProcess(ACTOR_NAME, "targetProcess", PROCESS_VERSION, false); final ProcessDefinition callingProcessDef = buildProcessWithCallActivity("callingProcess", "targetProcess", nbLoop, PROCESS_VERSION); assertThat(getProcessAPI().getNumberOfProcessInstances()).isEqualTo(0); final ProcessInstance callingProcessInstance = getProcessAPI().startProcess(callingProcessDef.getId(), null, null); waitForFlowNodeInExecutingState(callingProcessInstance, "callActivity", true); for (int i = 0; i < nbLoop; i++) { long tStep1 = waitForUserTask("tStep1"); FlowNodeInstance flowNodeInstance = getProcessAPI().getFlowNodeInstance(tStep1); assignAndExecuteStep(tStep1, cebolinha); waitForProcessToFinish(flowNodeInstance.getParentProcessInstanceId()); } waitForUserTaskAndExecuteIt(callingProcessInstance, "step1", cascao); waitForProcessToFinish(callingProcessInstance); disableAndDeleteProcess(callingProcessDef, targetProcessDef); } /* * Tested until 200, works ! * Don't use 0 as argument though. */ @Cover(classes = CallActivityDefinition.class, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity", "Loop" }, jira = "") @Test public void callActivityInALoop() throws Exception { callActivityInALoop(10); } private ProcessInstance getTargetProcessInstance(final ProcessDefinition targetProcessDef) throws Exception { final List<ProcessInstance> processInstances = checkNbOfProcessInstances(2, ProcessInstanceCriterion.NAME_DESC).getResult(); assertThat(processInstances).hasSize(2);// two instances are expected calling and target processes final ProcessInstance targetPI = processInstances.get(0); assertThat(targetPI.getProcessDefinitionId()).isEqualTo(targetProcessDef.getId()); return targetPI; } @Cover(classes = CallActivityInstance.class, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Archiving" }, jira = "") @Test public void getArchivedCallActivityInstance() throws Exception { final ProcessDefinition targetProcessDef = getSimpleProcess(ACTOR_NAME, "targetProcess", PROCESS_VERSION, false); final ProcessDefinition callingProcessDef = buildProcessWithCallActivity("callingProcess", "targetProcess", PROCESS_VERSION); assertThat(getProcessAPI().getNumberOfProcessInstances()).isEqualTo(0L); final ProcessInstance callingProcessInstance = getProcessAPI().startProcess(callingProcessDef.getId()); final ProcessInstance targetPI = getTargetProcessInstance(targetProcessDef); final FlowNodeInstance callActivityInstance = waitForFlowNodeInExecutingState(callingProcessInstance, "callActivity", true); waitForUserTaskAndExecuteIt(callingProcessInstance, "tStep1", cebolinha); // first loop execution waitForProcessToFinish(targetPI); final WaitForFinalArchivedActivity waitForFinalArchivedActivity = waitForFinalArchivedActivity( "callActivity", callingProcessInstance); assertThat(waitForFinalArchivedActivity.getResult().getType()).isEqualTo(FlowNodeType.CALL_ACTIVITY); final List<ArchivedProcessInstance> archivedProcessInstanceList = getProcessAPI() .getArchivedProcessInstances(targetPI.getId(), 0, 20); final ArchivedProcessInstance firstProcessInstanceArchive = archivedProcessInstanceList.get(0); assertThat(firstProcessInstanceArchive.getRootProcessInstanceId()) .isEqualTo(callingProcessInstance.getId()); assertThat(firstProcessInstanceArchive.getCallerId()).isEqualTo(callActivityInstance.getId()); disableAndDeleteProcess(callingProcessDef, targetProcessDef); } @Cover(classes = { CallActivityDefinition.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity", "Process Version" }, jira = "") @Test public void callActivityUsingLastestVersion() throws Exception { executeCallAtivityUntilEndOfProcess(false, false, null, false); } @Cover(classes = { CallActivityDefinition.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity", "Process Version" }, jira = "") @Test public void callActivityUsingUndeployedVersion() throws Exception { final ProcessDefinition callingProcessDef = buildProcessWithCallActivity("callingProcess", "targetProcess", "unexisting_version_4.0"); final ProcessInstance callingProcessInstance = getProcessAPI().startProcess(callingProcessDef.getId()); final ActivityInstance failedTask = waitForTaskToFail(callingProcessInstance); assertThat(failedTask.getName()).isEqualTo("callActivity"); disableAndDeleteProcess(callingProcessDef); } @Cover(classes = { CallActivityDefinition.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity", "Undeployed target" }, jira = "BS-10502") @Test public void callActivityUsingUndeployedProcess() throws Exception { final ProcessDefinition callingProcessDef = buildProcessWithCallActivity("callingProcess", "targetProcess", null); final ProcessInstance callingProcessInstance = getProcessAPI().startProcess(callingProcessDef.getId()); final ActivityInstance failedTask = waitForTaskToFail(callingProcessInstance); assertThat(failedTask.getName()).isEqualTo("callActivity"); disableAndDeleteProcess(callingProcessDef); } @Cover(classes = { CallActivityDefinition.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity", "Delete" }, jira = "ENGINE-1132") @Test public void deleteProcessInstanceThatIsCalledByCallActivity() throws Exception { final ProcessDefinition targetProcessDef1 = getSimpleProcess(ACTOR_NAME, "targetProcess", PROCESS_VERSION, false); final ProcessDefinition callingProcessDef = buildProcessWithCallActivity("callingProcess", "targetProcess", PROCESS_VERSION); assertThat(getProcessAPI().getNumberOfProcessInstances()).isEqualTo(0L); final List<Operation> operations = getStartOperations(); final ProcessInstance callingProcessInstance = getProcessAPI().startProcess(callingProcessDef.getId(), operations, null); final ActivityInstance tStep1 = waitForUserTaskAndGetIt(callingProcessInstance, "tStep1"); try { getProcessAPI().deleteProcessInstance(tStep1.getParentProcessInstanceId()); fail("Should not be able to delete process instance that is called by an other process"); } catch (final ProcessInstanceHierarchicalDeletionException e) { getProcessAPI().deleteProcessInstance(e.getProcessInstanceId()); // should work now try { getProcessAPI().getProcessInstance(tStep1.getParentProcessInstanceId()); fail("process should be deleted"); } catch (final ProcessInstanceNotFoundException e1) { // ok } } finally { disableAndDeleteProcess(callingProcessDef, targetProcessDef1); } } @Cover(classes = { CallActivityDefinition.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity", "Delete" }, jira = "ENGINE-1132") @Test(expected = DeletionException.class) public void deleteProcessDefinitionWithProcessInstanceThatIsCalledByCallActivity() throws Exception { final ProcessDefinition targetProcessDef1 = getSimpleProcess(ACTOR_NAME, "targetProcess", PROCESS_VERSION, false); final ProcessDefinition callingProcessDef = buildProcessWithCallActivity("callingProcess", "targetProcess", PROCESS_VERSION); assertThat(getProcessAPI().getNumberOfProcessInstances()).isEqualTo(0L); final List<Operation> operations = getStartOperations(); final ProcessInstance callingProcessInstance = getProcessAPI().startProcess(callingProcessDef.getId(), operations, null); waitForUserTask(callingProcessInstance, "tStep1"); getProcessAPI().disableProcess(targetProcessDef1.getId()); try { deleteProcess(targetProcessDef1); fail("Should not be able to delete process instance that is called by an other process"); } finally { disableAndDeleteProcess(callingProcessDef); deleteProcess(targetProcessDef1); } } @Cover(classes = CallActivityDefinition.class, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity", "Dependencies" }, jira = "") @Test public void callActivityWithDependencies() throws Exception { ProcessDefinition targetProcessDef = null; ProcessDefinition callingProcessDef = null; try { targetProcessDef = getSimpleProcess(ACTOR_NAME, "targetProcess", PROCESS_VERSION, false); final Expression targetProcessNameExpr = new ExpressionBuilder() .createConstantStringExpression("targetProcess"); final Expression vExpression = new ExpressionBuilder().createDataExpression("v", String.class.getName()); final List<Expression> dependencies = new ArrayList<Expression>(1); dependencies.add(vExpression); final Expression targetProcessVersionExpr = new ExpressionBuilder() .createGroovyScriptExpression("version", "v", String.class.getName(), dependencies); final ProcessDefinitionBuilder processDefBuilder = new ProcessDefinitionBuilder() .createNewInstance("callingProcess", PROCESS_VERSION); processDefBuilder.addShortTextData("v", new ExpressionBuilder().createConstantStringExpression(PROCESS_VERSION)); processDefBuilder.addShortTextData("lName", null); processDefBuilder.addIntegerData("cNumber", null); processDefBuilder.addIntegerData("pNumber", null); processDefBuilder.addActor(ACTOR_NAME); processDefBuilder.addStartEvent("start"); processDefBuilder.addCallActivity("callActivity", targetProcessNameExpr, targetProcessVersionExpr); processDefBuilder.addUserTask("step1", ACTOR_NAME); processDefBuilder.addEndEvent("end"); processDefBuilder.addTransition("start", "callActivity"); processDefBuilder.addTransition("callActivity", "step1"); processDefBuilder.addTransition("step1", "end"); callingProcessDef = deployAndEnableProcessWithActor(processDefBuilder.done(), ACTOR_NAME, cascao); assertThat(getProcessAPI().getNumberOfProcessInstances()).isEqualTo(0L); final ProcessInstance callingProcessInstance = getProcessAPI().startProcess(callingProcessDef.getId(), null, null); checkNbOfProcessInstances(2, ProcessInstanceCriterion.NAME_DESC); final List<ProcessInstance> processInstances = getProcessAPI().getProcessInstances(0, 10, ProcessInstanceCriterion.NAME_DESC); assertThat(processInstances).hasSize(2); // two instances are expected calling and target process final ProcessInstance targetPI = processInstances.get(0); assertThat(targetProcessDef.getId()).isEqualTo(targetPI.getProcessDefinitionId()); assertThat(targetProcessDef.getVersion()).isEqualTo(PROCESS_VERSION); final FlowNodeInstance callActivityInstance = waitForFlowNodeInExecutingState(callingProcessInstance, "callActivity", true); assertThat(targetPI.getRootProcessInstanceId()).isEqualTo(callingProcessInstance.getId()); assertThat(targetPI.getCallerId()).isEqualTo(callActivityInstance.getId()); final HumanTaskInstance tStep1 = waitForUserTaskAndGetIt(callingProcessInstance, "tStep1"); assertThat(tStep1.getParentProcessInstanceId()).isEqualTo(targetPI.getId()); assertThat(tStep1.getRootContainerId()).isEqualTo(callingProcessInstance.getId()); // execute step in the target process assignAndExecuteStep(tStep1, cebolinha.getId()); final HumanTaskInstance step1 = waitForUserTaskAndGetIt(callingProcessInstance, "step1"); waitForProcessToFinish(targetPI); assertThat(step1.getParentProcessInstanceId()).isEqualTo(callingProcessInstance.getId()); assignAndExecuteStep(step1, cascao.getId()); waitForProcessToFinish(callingProcessInstance); } finally { disableAndDeleteProcess(callingProcessDef, targetProcessDef); } } @Cover(classes = { CallActivityInstance.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity" }, jira = "") @Test public void callActivityCheckAttributes() throws Exception { ProcessDefinition targetProcessDef = null; ProcessDefinition callingProcessDef = null; try { targetProcessDef = getSimpleProcess(ACTOR_NAME, "targetProcess", PROCESS_VERSION, false); final Expression targetProcessNameExpr = new ExpressionBuilder() .createConstantStringExpression("targetProcess"); final Expression targetProcessVersionExpr = new ExpressionBuilder() .createConstantStringExpression(PROCESS_VERSION); final ProcessDefinitionBuilder processDefBuilder = new ProcessDefinitionBuilder() .createNewInstance("callingProcess", PROCESS_VERSION); processDefBuilder.addShortTextData("lName", null); processDefBuilder.addIntegerData("cNumber", null); processDefBuilder.addIntegerData("pNumber", null); processDefBuilder.addActor(ACTOR_NAME); processDefBuilder.addStartEvent("start"); processDefBuilder.addCallActivity("callActivity", targetProcessNameExpr, targetProcessVersionExpr) .addDisplayName( new ExpressionBuilder().createConstantStringExpression("callActivityDisplayName")) .addDescription("callActivityDescription").addDisplayDescription(new ExpressionBuilder() .createConstantStringExpression("callActivityDisplayDescription")); processDefBuilder.addUserTask("step1", ACTOR_NAME); processDefBuilder.addEndEvent("end"); processDefBuilder.addTransition("start", "callActivity"); processDefBuilder.addTransition("callActivity", "step1"); processDefBuilder.addTransition("step1", "end"); callingProcessDef = deployAndEnableProcessWithActor(processDefBuilder.done(), ACTOR_NAME, cascao); assertThat(getProcessAPI().getNumberOfProcessInstances()).isEqualTo(0L); final ProcessInstance callingProcessInstance = getProcessAPI().startProcess(callingProcessDef.getId(), null, null); checkNbOfProcessInstances(2, ProcessInstanceCriterion.NAME_DESC); final List<ProcessInstance> processInstances = getProcessAPI().getProcessInstances(0, 10, ProcessInstanceCriterion.NAME_DESC); assertThat(processInstances).hasSize(2); // two instances are expected calling and target process final ProcessInstance targetPI = processInstances.get(0); final FlowNodeInstance callActivityInstance = waitForFlowNodeInExecutingState(callingProcessInstance, "callActivity", true); assertThat(targetPI.getRootProcessInstanceId()).isEqualTo(callingProcessInstance.getId()); assertThat(targetPI.getCallerId()).isEqualTo(callActivityInstance.getId()); assertThat(callActivityInstance.getDisplayName()).isEqualTo("callActivityDisplayName"); assertThat(callActivityInstance.getDescription()).isEqualTo("callActivityDescription"); assertThat(callActivityInstance.getDisplayDescription()).isEqualTo("callActivityDisplayDescription"); final HumanTaskInstance tStep1 = waitForUserTaskAndGetIt(callingProcessInstance, "tStep1"); assertThat(tStep1.getParentProcessInstanceId()).isEqualTo(targetPI.getId()); assertThat(tStep1.getRootContainerId()).isEqualTo(callingProcessInstance.getId()); // execute step in the target process assignAndExecuteStep(tStep1, cebolinha.getId()); final HumanTaskInstance step1 = waitForUserTaskAndGetIt(callingProcessInstance, "step1"); waitForProcessToFinish(targetPI); assertThat(step1.getParentProcessInstanceId()).isEqualTo(callingProcessInstance.getId()); assignAndExecuteStep(step1, cascao.getId()); waitForProcessToFinish(callingProcessInstance); } finally { disableAndDeleteProcess(callingProcessDef, targetProcessDef); } } @Cover(classes = { ProcessDefinitionBuilder.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity", "Expression" }, jira = "") @Test(expected = InvalidProcessDefinitionException.class) public void callActivityTargetProcessExprIsNull() throws Exception { final Expression targetProcessNameExpr = null; final Expression targetProcessVersionExpr = new ExpressionBuilder() .createConstantStringExpression(PROCESS_VERSION); final ProcessDefinitionBuilder processDefBuilder = new ProcessDefinitionBuilder() .createNewInstance("callingProcess", PROCESS_VERSION); processDefBuilder.addShortTextData("lName", null); processDefBuilder.addIntegerData("cNumber", null); processDefBuilder.addIntegerData("pNumber", null); processDefBuilder.addActor(ACTOR_NAME); processDefBuilder.addStartEvent("start"); processDefBuilder.addCallActivity("callActivity", targetProcessNameExpr, targetProcessVersionExpr); processDefBuilder.addUserTask("step1", ACTOR_NAME); processDefBuilder.addEndEvent("end"); processDefBuilder.addTransition("start", "callActivity"); processDefBuilder.addTransition("callActivity", "step1"); processDefBuilder.addTransition("step1", "end"); deployAndEnableProcessWithActor(processDefBuilder.done(), ACTOR_NAME, cascao); } @Cover(classes = { CallActivityInstance.class, HumanTaskInstance.class, ArchivedProcessInstance.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity", "Human Task", "Search", "Archived Process Instance" }, jira = "ENGINE-922") @Test public void callActivityTargetProcessWithJustHumanTask() throws Exception { ProcessDefinition targetProcessDefinition = null; ProcessDefinition callingProcessDefinition = null; try { // Build target process final ProcessDefinitionBuilder targetProcessDefBuilder = new ProcessDefinitionBuilder() .createNewInstance("targetProcess", PROCESS_VERSION); targetProcessDefBuilder.addActor(ACTOR_NAME); targetProcessDefBuilder.addStartEvent("tStart"); targetProcessDefBuilder.addUserTask("tStep1", ACTOR_NAME); targetProcessDefBuilder.addEndEvent("tEnd"); targetProcessDefBuilder.addTransition("tStart", "tStep1"); targetProcessDefBuilder.addTransition("tStep1", "tEnd"); targetProcessDefinition = deployAndEnableProcessWithActor(targetProcessDefBuilder.done(), ACTOR_NAME, cebolinha); // Build and start calling process final Expression targetProcessNameExpr = new ExpressionBuilder() .createConstantStringExpression("targetProcess"); final Expression targetProcessVersionExpr = new ExpressionBuilder() .createConstantStringExpression(PROCESS_VERSION); final ProcessDefinitionBuilder processDefBuilder = new ProcessDefinitionBuilder() .createNewInstance("callingProcess", PROCESS_VERSION); processDefBuilder.addActor(ACTOR_NAME); processDefBuilder.addStartEvent("start"); processDefBuilder.addCallActivity("callActivity", targetProcessNameExpr, targetProcessVersionExpr) .addDisplayName( new ExpressionBuilder().createConstantStringExpression("callActivityDisplayName")) .addDescription("callActivityDescription").addDisplayDescription(new ExpressionBuilder() .createConstantStringExpression("callActivityDisplayDescription")); processDefBuilder.addEndEvent("end"); processDefBuilder.addTransition("start", "callActivity"); processDefBuilder.addTransition("callActivity", "end"); callingProcessDefinition = deployAndEnableProcessWithActor(processDefBuilder.done(), ACTOR_NAME, cascao); final ProcessInstance callingProcessInstance = getProcessAPI() .startProcess(callingProcessDefinition.getId()); // Execute step in the target process waitForUserTaskAndExecuteIt(callingProcessInstance, "tStep1", cebolinha); waitForProcessToFinish(callingProcessInstance); // Search archived process assertThat(getProcessAPI().getNumberOfArchivedProcessInstances()).isEqualTo(1L); final SearchOptionsBuilder searchOptions = new SearchOptionsBuilder(0, 10); searchOptions.sort(ArchivedProcessInstancesSearchDescriptor.NAME, Order.ASC); final List<ArchivedProcessInstance> archivedProcessInstances = getProcessAPI() .searchArchivedProcessInstances(searchOptions.done()).getResult(); assertThat(archivedProcessInstances).hasSize(1); assertThat(archivedProcessInstances.get(0).getSourceObjectId()) .isEqualTo(callingProcessInstance.getId()); } finally { disableAndDeleteProcess(callingProcessDefinition, targetProcessDefinition); } } @Test @Cover(classes = { SubProcessDefinition.class }, concept = BPMNConcept.EVENT_SUBPROCESS, keywords = { "event sub-process", "container hierarchy" }, jira = "ENGINE-1899") public void getProcessDefinitionIdFromActivityInstanceId() throws Exception { // check that real root process definition is retrieved (taken from parent process instance) // Build target process final ProcessDefinitionBuilder targetProcessDefBuilder = new ProcessDefinitionBuilder() .createNewInstance("targetProcess", PROCESS_VERSION); targetProcessDefBuilder.addActor(ACTOR_NAME); targetProcessDefBuilder.addStartEvent("tStart"); targetProcessDefBuilder.addUserTask("tStep1", ACTOR_NAME); targetProcessDefBuilder.addEndEvent("tEnd"); targetProcessDefBuilder.addTransition("tStart", "tStep1"); targetProcessDefBuilder.addTransition("tStep1", "tEnd"); final ProcessDefinition targetProcessDefinition = deployAndEnableProcessWithActor( targetProcessDefBuilder.done(), ACTOR_NAME, cebolinha); // Build and start calling process final Expression targetProcessNameExpr = new ExpressionBuilder() .createConstantStringExpression("targetProcess"); final Expression targetProcessVersionExpr = new ExpressionBuilder() .createConstantStringExpression(PROCESS_VERSION); final ProcessDefinitionBuilder processDefBuilder = new ProcessDefinitionBuilder() .createNewInstance("callingProcess", PROCESS_VERSION); processDefBuilder.addActor(ACTOR_NAME); processDefBuilder.addStartEvent("start"); processDefBuilder.addCallActivity("callActivity", targetProcessNameExpr, targetProcessVersionExpr) .addDisplayName(new ExpressionBuilder().createConstantStringExpression("callActivityDisplayName")) .addDescription("callActivityDescription").addDisplayDescription( new ExpressionBuilder().createConstantStringExpression("callActivityDisplayDescription")); processDefBuilder.addEndEvent("end"); processDefBuilder.addTransition("start", "callActivity"); processDefBuilder.addTransition("callActivity", "end"); final ProcessDefinition callingProcessDefinition = deployAndEnableProcessWithActor(processDefBuilder.done(), ACTOR_NAME, cascao); final ProcessInstance callingProcessInstance = getProcessAPI() .startProcess(callingProcessDefinition.getId()); final long tStep1Id = waitForUserTask(callingProcessInstance.getId(), "tStep1"); final long processDefinitionId = getProcessAPI().getProcessDefinitionIdFromActivityInstanceId(tStep1Id); assertThat(processDefinitionId).isEqualTo(targetProcessDefinition.getId()); disableAndDeleteProcess(callingProcessDefinition, targetProcessDefinition); } @Cover(classes = { CallActivityInstance.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity", "Engine constant" }, jira = "ENGINE-1009") @Test public void callActivityWithTaskUsingEngineExpressions() throws Exception { ProcessDefinition targetProcessDefinition = null; ProcessDefinition callingProcessDefinition = null; try { // Build target process final ProcessDefinitionBuilder targetProcessDefBuilder = new ProcessDefinitionBuilder() .createNewInstance("targetProcess", PROCESS_VERSION); targetProcessDefBuilder.addActor(ACTOR_NAME); targetProcessDefBuilder.addStartEvent("tStart"); targetProcessDefBuilder.addUserTask("tStep1", ACTOR_NAME).addData("rootProcId", Long.class.getName(), new ExpressionBuilder().createEngineConstant(ExpressionConstants.ROOT_PROCESS_INSTANCE_ID)); targetProcessDefBuilder.addEndEvent("tEnd"); targetProcessDefBuilder.addTransition("tStart", "tStep1"); targetProcessDefBuilder.addTransition("tStep1", "tEnd"); targetProcessDefinition = deployAndEnableProcessWithActor(targetProcessDefBuilder.done(), ACTOR_NAME, cebolinha); // Build and start calling process final Expression targetProcessNameExpr = new ExpressionBuilder() .createConstantStringExpression("targetProcess"); final Expression targetProcessVersionExpr = new ExpressionBuilder() .createConstantStringExpression(PROCESS_VERSION); final ProcessDefinitionBuilder processDefBuilder = new ProcessDefinitionBuilder() .createNewInstance("callingProcess", PROCESS_VERSION); processDefBuilder.addActor(ACTOR_NAME); processDefBuilder.addStartEvent("start"); processDefBuilder.addCallActivity("callActivity", targetProcessNameExpr, targetProcessVersionExpr); processDefBuilder.addEndEvent("end"); processDefBuilder.addTransition("start", "callActivity"); processDefBuilder.addTransition("callActivity", "end"); callingProcessDefinition = deployAndEnableProcessWithActor(processDefBuilder.done(), ACTOR_NAME, cascao); final ProcessInstance callingProcessInstance = getProcessAPI() .startProcess(callingProcessDefinition.getId()); final long tStep1Id = waitForUserTask(callingProcessInstance, "tStep1"); assertThat(getProcessAPI().getActivityDataInstance("rootProcId", tStep1Id).getValue()) .isEqualTo(callingProcessInstance.getId()); } finally { disableAndDeleteProcess(callingProcessDefinition, targetProcessDefinition); } } @Cover(classes = { CallActivityInstance.class }, concept = BPMNConcept.CALL_ACTIVITY, keywords = { "Call Activity", "Connector", "Data mapping" }, jira = "ENGINE-1243") @Test public void callActivityWithDataMappingAndConnectors() throws Exception { ProcessDefinition targetProcessDefinition = null; ProcessDefinition callingProcessDefinition = null; try { // Build target process final ProcessDefinitionBuilder targetProcessDefBuilder = new ProcessDefinitionBuilder() .createNewInstance("targetProcess", PROCESS_VERSION); targetProcessDefBuilder.addActor(ACTOR_NAME); targetProcessDefBuilder.addData("subProcessData", String.class.getName(), new ExpressionBuilder().createConstantStringExpression("subDefault")); targetProcessDefBuilder.addAutomaticTask("tStep1") .addOperation(new OperationBuilder().createSetDataOperation("subProcessData", new ExpressionBuilder().createConstantStringExpression("subModified"))); targetProcessDefinition = deployAndEnableProcessWithActor(targetProcessDefBuilder.done(), ACTOR_NAME, cebolinha); // Build and start calling process final Expression targetProcessNameExpr = new ExpressionBuilder() .createConstantStringExpression("targetProcess"); final Expression targetProcessVersionExpr = new ExpressionBuilder() .createConstantStringExpression(PROCESS_VERSION); final ProcessDefinitionBuilder processDefBuilder = new ProcessDefinitionBuilder() .createNewInstance("callingProcess", PROCESS_VERSION); processDefBuilder.addActor(ACTOR_NAME); processDefBuilder.addData("parentProcessData", String.class.getName(), new ExpressionBuilder().createConstantStringExpression("parentDefault")); processDefBuilder.addData("valueOnCallOnEnter", String.class.getName(), new ExpressionBuilder().createConstantStringExpression("none")); processDefBuilder.addData("valueOnCallOnFinish", String.class.getName(), new ExpressionBuilder().createConstantStringExpression("none")); final CallActivityBuilder callActivityBuilder = processDefBuilder.addCallActivity("callActivity", targetProcessNameExpr, targetProcessVersionExpr); callActivityBuilder .addConnector("onEnterConnector", "org.bonitasoft.connector.testConnectorWithOutput", PROCESS_VERSION, ConnectorEvent.ON_ENTER) .addInput("input1", new ExpressionBuilder().createDataExpression("parentProcessData", String.class.getName())) .addOutput(new LeftOperandBuilder().createNewInstance().setName("valueOnCallOnEnter").done(), OperatorType.ASSIGNMENT, "=", "", new ExpressionBuilder() .createInputExpression(CONNECTOR_OUTPUT_NAME, String.class.getName())); callActivityBuilder .addConnector("onFinishConnector", "org.bonitasoft.connector.testConnectorWithOutput", PROCESS_VERSION, ConnectorEvent.ON_FINISH) .addInput("input1", new ExpressionBuilder().createDataExpression("parentProcessData", String.class.getName())) .addOutput(new LeftOperandBuilder().createNewInstance().setName("valueOnCallOnFinish").done(), OperatorType.ASSIGNMENT, "=", "", new ExpressionBuilder() .createInputExpression(CONNECTOR_OUTPUT_NAME, String.class.getName())); callActivityBuilder.addDataOutputOperation(new OperationBuilder().createSetDataOperation( "parentProcessData", new ExpressionBuilder().createDataExpression("subProcessData", String.class.getName()))); processDefBuilder.addUserTask("end", ACTOR_NAME); processDefBuilder.addTransition("callActivity", "end"); final BusinessArchiveBuilder bizArchive = new BusinessArchiveBuilder(); bizArchive.createNewBusinessArchive(); bizArchive.setProcessDefinition(processDefBuilder.done()); bizArchive.addConnectorImplementation(new BarResource("TestConnectorWithOutput.impl", IOUtils.toByteArray(BPMRemoteTests.class.getResourceAsStream( "/org/bonitasoft/engine/connectors/TestConnectorWithOutput.impl")))); bizArchive.addClasspathResource(new BarResource("TestConnectorWithOutput.jar", IOUtil.generateJar(TestConnectorWithOutput.class))); callingProcessDefinition = deployAndEnableProcessWithActor(bizArchive.done(), ACTOR_NAME, cascao); final ProcessInstance callingProcessInstance = getProcessAPI() .startProcess(callingProcessDefinition.getId()); final long endId = waitForUserTask(callingProcessInstance, "end"); assertThat(getProcessAPI().getActivityDataInstance("valueOnCallOnEnter", endId).getValue()) .isEqualTo("parentDefault"); assertThat(getProcessAPI().getActivityDataInstance("valueOnCallOnFinish", endId).getValue()) .isEqualTo("subModified"); } finally { disableAndDeleteProcess(callingProcessDefinition, targetProcessDefinition); } } @Test public void transfert_a_custom_data_from_a_parent_process_to_a_child_and_vice_versa() throws Exception { final ExpressionBuilder expressionBuilder = new ExpressionBuilder(); final ProcessDefinitionBuilder builder = new ProcessDefinitionBuilder().createNewInstance("child", "1.0"); builder.addActor(ACTOR_NAME); builder.addData("data1", "org.bonitasoft.complextypes.MyType", null); builder.addUserTask("childTask", ACTOR_NAME) .addOperation(new OperationBuilder().createJavaMethodOperation("data1", "setName", String.class.getName(), expressionBuilder.createConstantStringExpression("World"))); final BusinessArchive childBA = buildBusinessArchive(builder.done()); builder.createNewInstance("parent", "1.0"); builder.addActor(ACTOR_NAME); builder.addData("data1", "org.bonitasoft.complextypes.MyType", expressionBuilder.createGroovyScriptExpression("initMyType", "import org.bonitasoft.complextypes.MyType; new MyType()", "org.bonitasoft.complextypes.MyType")); builder.addShortTextData("name", null); final CallActivityBuilder callActivityBuilder = builder.addCallActivity("caTask", expressionBuilder.createConstantStringExpression("child"), expressionBuilder.createConstantStringExpression("1.0")); callActivityBuilder.addDataInputOperation(BuildTestUtil.buildAssignOperation("data1", "data1", ExpressionType.TYPE_VARIABLE, "org.bonitasoft.complextypes.MyType")); callActivityBuilder.addDataOutputOperation(BuildTestUtil.buildAssignOperation("data1", "data1", ExpressionType.TYPE_VARIABLE, "org.bonitasoft.complextypes.MyType")); final Expression initIndex = expressionBuilder.createGroovyScriptExpression("initIndex", "data1.getName()", String.class.getName(), expressionBuilder.createDataExpression("data1", "org.bonitasoft.complextypes.MyType")); builder.addAutomaticTask("setData") .addOperation(new OperationBuilder().createSetDataOperation("name", initIndex)); builder.addUserTask("parentTask", ACTOR_NAME); builder.addTransition("caTask", "setData"); builder.addTransition("setData", "parentTask"); final BusinessArchive parentBA = buildBusinessArchive(builder.done()); final ProcessDefinition childProcDefinition = deployAndEnableProcessWithActor(childBA, ACTOR_NAME, cascao); final ProcessDefinition parentProcDefinition = deployAndEnableProcessWithActor(parentBA, ACTOR_NAME, cascao); final ProcessInstance instance = getProcessAPI().startProcess(parentProcDefinition.getId()); waitForUserTaskAndExecuteIt("childTask", cascao); waitForUserTask("parentTask"); final DataInstance dataInstance = getProcessAPI().getProcessDataInstance("name", instance.getId()); assertThat(dataInstance.getValue()).isEqualTo("World"); disableAndDeleteProcess(parentProcDefinition, childProcDefinition); } private BusinessArchive buildBusinessArchive(final DesignProcessDefinition process) throws Exception { InputStream inputStream = null; try { inputStream = this.getClass().getResourceAsStream("/org.bonitasoft.complextypes.jar-bak"); final byte[] content = IOUtils.toByteArray(inputStream); final BarResource resource = new BarResource("org.bonitasoft.complextypes.jar", content); final BusinessArchiveBuilder baBuilder = new BusinessArchiveBuilder(); baBuilder.createNewBusinessArchive().setProcessDefinition(process).addClasspathResource(resource); return baBuilder.done(); } finally { if (inputStream != null) { inputStream.close(); } } } }