public SagaBuilder end() { saga = saga.endEvent("End-" + name); return this; }
@Test public void testMapEqualUnsupportedAsyncBeforeActivities() { BpmnModelInstance testModel = modify(ProcessModels.UNSUPPORTED_ACTIVITIES) .flowNodeBuilder("startEvent").camundaAsyncBefore() .moveToNode("decisionTask").camundaAsyncBefore() .moveToNode("throwEvent").camundaAsyncAfter() .moveToNode("serviceTask").camundaAsyncBefore() .moveToNode("sendTask").camundaAsyncBefore() .moveToNode("scriptTask").camundaAsyncBefore() .moveToNode("endEvent").camundaAsyncBefore() .done(); assertGeneratedMigrationPlan(testModel, testModel) .hasInstructions( migrate("startEvent").to("startEvent"), migrate("decisionTask").to("decisionTask"), migrate("throwEvent").to("throwEvent"), migrate("serviceTask").to("serviceTask"), migrate("sendTask").to("sendTask"), migrate("scriptTask").to("scriptTask"), migrate("endEvent").to("endEvent") ); }
/** * Sets the camunda failedJobRetryTimeCycle attribute for the build flow node. * * @param retryTimeCycle * the retry time cycle value to set * @return the builder object */ public B camundaFailedJobRetryTimeCycle(String retryTimeCycle) { CamundaFailedJobRetryTimeCycle failedJobRetryTimeCycle = createInstance(CamundaFailedJobRetryTimeCycle.class); failedJobRetryTimeCycle.setTextContent(retryTimeCycle); addExtensionElement(failedJobRetryTimeCycle); return myself; }
protected <T extends FlowNode> T createTarget(Class<T> typeClass, String identifier) { T target = createSibling(typeClass, identifier); BpmnShape targetBpmnShape = createBpmnShape(target); setCoordinates(targetBpmnShape); connectTarget(target); resizeSubProcess(targetBpmnShape); return target; }
protected void connectTarget(FlowNode target) { // check if compensation was started if (isBoundaryEventWithStartedCompensation()) { // the target activity should be marked for compensation if (target instanceof Activity) { ((Activity) target).setForCompensation(true); } // connect the target via association instead of sequence flow connectTargetWithAssociation(target); } else if (isCompensationHandler()) { // cannot connect to a compensation handler throw new BpmnModelException("Only single compensation handler allowed. Call compensationDone() to continue main flow."); } else { // connect as sequence flow by default connectTargetWithSequenceFlow(target); } }
public void testConcurrentExecution() { deploymentForTenant("tenant1", Bpmn.createExecutableProcess(PROCESS_DEFINITION_KEY) .startEvent() .parallelGateway("fork") .serviceTask() .camundaClass(AssertingJavaDelegate.class.getName()) .parallelGateway("join") .endEvent() .moveToNode("fork") .serviceTask() .camundaClass(AssertingJavaDelegate.class.getName()) .connectTo("join") .done()); AssertingJavaDelegate.addAsserts(hasTenantId("tenant1")); startProcessInstance(PROCESS_DEFINITION_KEY); }
public static BpmnModelInstance prepareCompensationEventProcess() { return Bpmn.createExecutableProcess(PROCESS_ID) .startEvent() .subProcess("subProcess") .embeddedSubProcess() .startEvent() .endEvent() .subProcessDone() .intermediateThrowEvent(FAILING_EVENT) .camundaAsyncBefore(true) .camundaFailedJobRetryTimeCycle(SCHEDULE) .compensateEventDefinition() .compensateEventDefinitionDone() .serviceTask() .camundaClass(FailingDelegate.class.getName()) .endEvent() .done(); }
@Test public void testSkipListenerInvocationF() { // given DelegateEvent.clearEvents(); ProcessDefinition processDefinition = testRule.deployAndGetDefinition(modify(instance) .activityBuilder("user2") .camundaExecutionListenerClass(ExecutionListener.EVENTNAME_START, DelegateExecutionListener.class.getName()) .done()); ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId()); Batch batch = runtimeService .createModification(processDefinition.getId()) .cancelAllForActivity("user2") .processInstanceIds(Arrays.asList(processInstance.getId())) .skipCustomListeners() .executeAsync(); helper.executeSeedJob(batch); // when helper.executeJobs(batch); // then assertEquals(0, DelegateEvent.getEvents().size()); }
/** just for visualization, needed on blog post / slide **/ private void createComplexFlow() { engine.getRepositoryService().createDeployment() // .addModelInstance("order.bpmn", Bpmn.createProcess("order").executable() // .startEvent() .serviceTask().name("A") .parallelGateway("fork1") .serviceTask().name("B") .parallelGateway("join2") .moveToNode("fork1") .serviceTask().name("C") .parallelGateway("fork2") .serviceTask().name("D") .parallelGateway("join1") .moveToNode("fork2") .serviceTask().name("E") .connectTo("join1") .connectTo("join2") .endEvent() .done() ).deploy(); } private void createCompensationFlow() {
.serviceTask("car").name("Reserve car").camundaClass(ReserveCarAdapter.class) .boundaryEvent().compensateEventDefinition().compensateEventDefinitionDone() .compensationStart().serviceTask("CancelCar").camundaClass(CancelCarAdapter.class).compensationDone() .serviceTask("hotel").name("Book hotel").camundaClass(BookHotelAdapter.class) .boundaryEvent().compensateEventDefinition().compensateEventDefinitionDone() .compensationStart().serviceTask("CancelHotel").camundaClass(CancelHotelAdapter.class).compensationDone() .serviceTask("flight").name("Book flight").camundaClass(BookFlightAdapter.class) .boundaryEvent().compensateEventDefinition().compensateEventDefinitionDone() .compensationStart().serviceTask("CancelFlight").camundaClass(CancelFlightAdapter.class).compensationDone() .endEvent(); .startEvent().error("java.lang.Throwable") .intermediateThrowEvent().compensateEventDefinition().compensateEventDefinitionDone() .endEvent();
.compensateEventDefinition() .compensateEventDefinitionDone() .moveToActivity("serviceTask1") .serviceTask("serviceTask2") .camundaClass(IncreaseCurrentTimeServiceTask.class.getName()) .compensateEventDefinition() .compensateEventDefinitionDone() .moveToActivity("serviceTask2") .intermediateThrowEvent("compensationEvent") .compensateEventDefinition() .waitForCompletion(true) .compensateEventDefinitionDone() .endEvent() .done();
public void testPropagateTenantIdToConcurrentExecution() { deploymentForTenant(TENANT_ID, Bpmn.createExecutableProcess(PROCESS_DEFINITION_KEY) .startEvent() .parallelGateway("fork") .userTask() .parallelGateway("join") .endEvent() .moveToNode("fork") .userTask() .connectTo("join") .done()); startProcessInstance(PROCESS_DEFINITION_KEY); List<Execution> executions = runtimeService.createExecutionQuery().list(); assertThat(executions.size(), is(3)); assertThat(executions.get(0).getTenantId(), is(TENANT_ID)); // inherit the tenant id from process instance assertThat(executions.get(1).getTenantId(), is(TENANT_ID)); assertThat(executions.get(2).getTenantId(), is(TENANT_ID)); }
@Test public void testCannotMigrateWhenNotAllTransitionInstancesAreMapped() { // given BpmnModelInstance model = ModifiableBpmnModelInstance.modify(ProcessModels.PARALLEL_GATEWAY_PROCESS) .activityBuilder("userTask1") .camundaAsyncBefore() .moveToActivity("userTask2") .camundaAsyncBefore() .done(); ProcessDefinition sourceProcessDefinition = testHelper.deployAndGetDefinition(model); ProcessDefinition targetProcessDefinition = testHelper.deployAndGetDefinition(model); MigrationPlan migrationPlan = rule.getRuntimeService().createMigrationPlan(sourceProcessDefinition.getId(), targetProcessDefinition.getId()) .mapActivities("userTask1", "userTask1") .build(); // when try { testHelper.createProcessInstanceAndMigrate(migrationPlan); Assert.fail("should not succeed because the userTask2 instance is not mapped"); } catch (MigratingProcessInstanceValidationException e) { assertThat(e.getValidationReport()) .hasTransitionInstanceFailures("userTask2", "There is no migration instruction for this instance's activity"); } }
@Test public void testMapEqualUnsupportedAsyncAfterActivities() { BpmnModelInstance testModel = modify(ProcessModels.UNSUPPORTED_ACTIVITIES) .flowNodeBuilder("startEvent").camundaAsyncAfter() .moveToNode("decisionTask").camundaAsyncAfter() .moveToNode("throwEvent").camundaAsyncAfter() .moveToNode("serviceTask").camundaAsyncAfter() .moveToNode("sendTask").camundaAsyncAfter() .moveToNode("scriptTask").camundaAsyncAfter() .moveToNode("endEvent").camundaAsyncAfter() .done(); assertGeneratedMigrationPlan(testModel, testModel) .hasInstructions( migrate("startEvent").to("startEvent"), migrate("decisionTask").to("decisionTask"), migrate("throwEvent").to("throwEvent"), migrate("serviceTask").to("serviceTask"), migrate("sendTask").to("sendTask"), migrate("scriptTask").to("scriptTask"), migrate("endEvent").to("endEvent") ); }
@SuppressWarnings("rawtypes") public SagaBuilder compensationActivity(String name, Class adapterClass) { if (!(saga instanceof AbstractActivityBuilder)) { throw new RuntimeException("Compensation activity can only be specified right after activity"); } String id = "Activity-" + name.replace(" ", "-") + "-compensation"; // risky thing ;-) ((AbstractActivityBuilder)saga) .boundaryEvent() .compensateEventDefinition() .compensateEventDefinitionDone() .compensationStart() .serviceTask(id).name(name).camundaClass(adapterClass.getName()) .compensationDone(); return this; }
@Test public void testMigrateAsyncAfterCompensateEventSubProcessStartEvent() { // given BpmnModelInstance model = modify(EventSubProcessModels.COMPENSATE_EVENT_SUBPROCESS_PROCESS) .flowNodeBuilder("eventSubProcessStart") .camundaAsyncAfter() .done(); ProcessDefinition sourceProcessDefinition = testHelper.deployAndGetDefinition(model); ProcessDefinition targetProcessDefinition = testHelper.deployAndGetDefinition(model); MigrationPlan migrationPlan = rule.getRuntimeService() .createMigrationPlan(sourceProcessDefinition.getId(), targetProcessDefinition.getId()) .mapActivities("subProcess", "subProcess") .mapActivities("eventSubProcess", "eventSubProcess") .mapActivities("eventSubProcessStart", "eventSubProcessStart") .build(); ProcessInstance processInstance = rule.getRuntimeService().createProcessInstanceById(sourceProcessDefinition.getId()) .startBeforeActivity("eventSubProcess") .execute(); // when testHelper.migrateProcessInstance(migrationPlan, processInstance); // then testHelper.assertJobMigrated("eventSubProcessStart", "eventSubProcessStart", AsyncContinuationJobHandler.TYPE); }
@SuppressWarnings("rawtypes") public B camundaExecutionListenerClass(String eventName, Class listenerClass) { return camundaExecutionListenerClass(eventName, listenerClass.getName()); }
@SuppressWarnings("rawtypes") public AbstractFlowNodeBuilder connectTo(String identifier) { ModelElementInstance target = modelInstance.getModelElementById(identifier); if (target == null) { throw new BpmnModelException("Unable to connect " + element.getId() + " to element " + identifier + " cause it not exists."); } else if (!(target instanceof FlowNode)) { throw new BpmnModelException("Unable to connect " + element.getId() + " to element " + identifier + " cause its not a flow node."); } else { FlowNode targetNode = (FlowNode) target; connectTarget(targetNode); return targetNode.builder(); } }
protected <T extends FlowNode> T createTarget(Class<T> typeClass, String identifier) { T target = createSibling(typeClass, identifier); BpmnShape targetBpmnShape = createBpmnShape(target); setCoordinates(targetBpmnShape); connectTarget(target); resizeSubProcess(targetBpmnShape); return target; }