@Parameters(name = "from {0} to {2}") public static Object[][] parameters() { return new Object[][] { {"{}", mapping(b -> {}), "{}"}, {"{'x': 1, 'y': 2}", mapping(b -> {}), "{'x': 1, 'y': 2}"}, {"{'x': {'y': 2}}", mapping(b -> {}), "{'x': {'y': 2}}"}, {"{'x': 1}", mapping(b -> b.zeebeInput("$.x", "$.y")), "{'y': 1}"}, { "{'x': 1}", mapping(b -> b.zeebeInput("$.x", "$.y").zeebeInput("$.x", "$.z")), "{'y': 1, 'z': 1}" }, {"{'x': {'y': 2}}", mapping(b -> b.zeebeInput("$.x.y", "$.y")), "{'y': 2}"}, }; }
@Parameters(name = "from {0} to {2}") public static Object[][] parameters() { return new Object[][] { {"{}", mapping(b -> {}), "{}"}, {"{'x': 1, 'y': 2}", mapping(b -> {}), "{'x': 1, 'y': 2}"}, {"{'x': {'y': 2}}", mapping(b -> {}), "{'x': {'y': 2}}"}, {"{'x': 1}", mapping(b -> b.zeebeInput("$.x", "$.y")), "{'y': 1}"}, { "{'x': 1}", mapping(b -> b.zeebeInput("$.x", "$.y").zeebeInput("$.x", "$.z")), "{'y': 1, 'z': 1}" }, {"{'x': {'y': 2}}", mapping(b -> b.zeebeInput("$.x.y", "$.y")), "{'y': 2}"}, }; }
private void addInputOutputMappingToTask(YamlTask task, ServiceTaskBuilder serviceTaskBuilder) { final String outputBehaviorString = task.getOutputBehavior(); final ZeebeOutputBehavior outputBehavior; try { outputBehavior = ZeebeOutputBehavior.valueOf(outputBehaviorString.toLowerCase()); } catch (IllegalArgumentException e) { throw new RuntimeException( String.format( "Expected output behavior to be one of %s, but actual output behavior was '%s'", outputBehaviorString, Arrays.toString(ZeebeOutputBehavior.values()))); } serviceTaskBuilder.zeebeOutputBehavior(outputBehavior); for (YamlMapping inputMapping : task.getInputs()) { serviceTaskBuilder.zeebeInput(inputMapping.getSource(), inputMapping.getTarget()); } for (YamlMapping outputMapping : task.getOutputs()) { serviceTaskBuilder.zeebeOutput(outputMapping.getSource(), outputMapping.getTarget()); } } }
private void addInputOutputMappingToTask(YamlTask task, ServiceTaskBuilder serviceTaskBuilder) { final String outputBehaviorString = task.getOutputBehavior(); final ZeebeOutputBehavior outputBehavior; try { outputBehavior = ZeebeOutputBehavior.valueOf(outputBehaviorString.toLowerCase()); } catch (IllegalArgumentException e) { throw new RuntimeException( String.format( "Expected output behavior to be one of %s, but actual output behavior was '%s'", outputBehaviorString, Arrays.toString(ZeebeOutputBehavior.values()))); } serviceTaskBuilder.zeebeOutputBehavior(outputBehavior); for (YamlMapping inputMapping : task.getInputs()) { serviceTaskBuilder.zeebeInput(inputMapping.getSource(), inputMapping.getTarget()); } for (YamlMapping outputMapping : task.getOutputs()) { serviceTaskBuilder.zeebeOutput(outputMapping.getSource(), outputMapping.getTarget()); } } }
@Test public void shouldCreateIncidentForNonMatchingAndMatchingValueOnInputMapping() { // given testClient.deploy( Bpmn.createExecutableProcess("process") .startEvent() .serviceTask( "service", t -> t.zeebeTaskType("external") .zeebeInput("$.notExisting", "$.nullVal") .zeebeInput(NODE_STRING_PATH, "$.existing")) .endEvent() .done()); // when testClient.createWorkflowInstance("process", MSGPACK_PAYLOAD); final Record incidentEvent = testClient.receiveFirstIncidentEvent(IncidentIntent.CREATED); // then incident is created assertThat(incidentEvent.getKey()).isGreaterThan(0); assertIncidentRecordValue( ErrorType.IO_MAPPING_ERROR.name(), "No data found for query $.notExisting.", "service", incidentEvent); }
@Test public void shouldCreateIncidentForNonMatchingAndMatchingValueOnInputMapping() { // given testClient.deploy( Bpmn.createExecutableProcess("process") .startEvent() .serviceTask( "service", t -> t.zeebeTaskType("external") .zeebeInput("$.notExisting", "$.nullVal") .zeebeInput(NODE_STRING_PATH, "$.existing")) .endEvent() .done()); // when testClient.createWorkflowInstance("process", MSGPACK_PAYLOAD); final Record<WorkflowInstanceRecordValue> failureEvent = testClient.receiveElementInState("service", WorkflowInstanceIntent.ELEMENT_ACTIVATING); final Record<IncidentRecordValue> incidentEvent = testClient.receiveFirstIncidentEvent(IncidentIntent.CREATED); // then incident is created assertThat(incidentEvent.getKey()).isGreaterThan(0); assertThat(incidentEvent.getValue().getVariableScopeKey()).isEqualTo(failureEvent.getKey()); assertIncidentRecordValue( ErrorType.IO_MAPPING_ERROR.name(), "No data found for query $.notExisting.", "service", incidentEvent); }
@Test public void shouldCreateIncidentForInvalidResultOnInputMapping() { // given testClient.deploy( Bpmn.createExecutableProcess("process") .startEvent() .serviceTask( "failingTask", t -> t.zeebeTaskType("external").zeebeInput("$.string", "$")) .done()); // when testClient.createWorkflowInstance("process", MSGPACK_PAYLOAD); // then incident is created final Record<IncidentRecordValue> incidentEvent = testClient.receiveFirstIncidentEvent(IncidentIntent.CREATED); assertThat(incidentEvent.getKey()).isGreaterThan(0); assertIncidentContainErrorDetails(incidentEvent); }
@Test public void shouldCreateIncidentForInvalidResultOnInputMapping() { // given testClient.deploy( Bpmn.createExecutableProcess("process") .startEvent() .serviceTask( "failingTask", t -> t.zeebeTaskType("external").zeebeInput("$.string", "$")) .done()); // when testClient.createWorkflowInstance("process", MSGPACK_PAYLOAD); // then incident is created final Record<IncidentRecordValue> incidentEvent = testClient.receiveFirstIncidentEvent(IncidentIntent.CREATED); assertThat(incidentEvent.getKey()).isGreaterThan(0); assertIncidentContainErrorDetails(incidentEvent); }
@Test public void shouldCreateIncidentForInAndOutputMappingAndNoTaskCompletePayload() { // given testClient.deploy( Bpmn.createExecutableProcess("process") .startEvent() .serviceTask( "failingTask", t -> t.zeebeTaskType("external") .zeebeInput("$.jsonObject", "$") .zeebeOutput("$.foo", "$")) .done()); testClient.createWorkflowInstance("process", MSGPACK_PAYLOAD); // when testClient.completeJobOfType("external"); // then incident is created final Record incidentEvent = testClient.receiveFirstIncidentEvent(IncidentIntent.CREATED); assertThat(incidentEvent.getKey()).isGreaterThan(0); assertIncidentContainErrorDetails(incidentEvent, "No data found for query $.foo."); }
@Test public void shouldCreateIncidentForInAndOutputMappingAndNoTaskCompletePayload() { // given testClient.deploy( Bpmn.createExecutableProcess("process") .startEvent() .serviceTask( "failingTask", t -> t.zeebeTaskType("external") .zeebeInput("$.jsonObject", "$") .zeebeOutput("$.foo", "$")) .done()); testClient.createWorkflowInstance("process", MSGPACK_PAYLOAD); // when testClient.completeJobOfType("external"); // then incident is created final Record incidentEvent = testClient.receiveFirstIncidentEvent(IncidentIntent.CREATED); assertThat(incidentEvent.getKey()).isGreaterThan(0); assertIncidentContainErrorDetails(incidentEvent, "No data found for query $.foo."); }
@Test public void shouldUseScopeToExtractCorrelationKeys() { // given final String processId = "shouldHaveScopeKeyIfBoundaryEvent"; final BpmnModelInstance workflow = Bpmn.createExecutableProcess(processId) .startEvent() .serviceTask("task", c -> c.zeebeTaskType("type").zeebeInput("$.bar", "$.foo")) .boundaryEvent( "event", b -> b.message(m -> m.zeebeCorrelationKey("$.foo").name("message"))) .endEvent() .moveToActivity("task") .endEvent() .done(); testClient.deploy(workflow); // when testClient.createWorkflowInstance( processId, MsgPackUtil.asMsgPack(m -> m.put("foo", 1).put("bar", 2))); testClient.publishMessage("message", "1"); // then // if correlation key was extracted from the task, then foo in the task scope would be 2 and // no event occurred would be published assertThat(testClient.receiveElementInState("task", WorkflowInstanceIntent.EVENT_OCCURRED)) .isNotNull(); }
@Test public void shouldCreateIncidentForInvalidResultOnOutputMapping() { // given testClient.deploy( Bpmn.createExecutableProcess("process") .startEvent() .serviceTask( "failingTask", t -> t.zeebeTaskType("external") .zeebeInput("$.jsonObject", "$") .zeebeOutput("$.testAttr", "$")) .done()); testClient.createWorkflowInstance("process", MSGPACK_PAYLOAD); // when testClient.completeJobOfType( "external", MsgPackUtil.asMsgPackReturnArray("{'testAttr':'test'}")); testClient.receiveFirstWorkflowInstanceEvent(WorkflowInstanceIntent.ELEMENT_ACTIVATED); // then incident is created final Record incidentEvent = testClient.receiveFirstIncidentEvent(IncidentIntent.CREATED); assertThat(incidentEvent.getKey()).isGreaterThan(0); assertIncidentContainErrorDetails(incidentEvent); }
@Test public void shouldCreateIncidentForInvalidResultOnOutputMapping() { // given testClient.deploy( Bpmn.createExecutableProcess("process") .startEvent() .serviceTask( "failingTask", t -> t.zeebeTaskType("external") .zeebeInput("$.jsonObject", "$") .zeebeOutput("$.testAttr", "$")) .done()); testClient.createWorkflowInstance("process", MSGPACK_PAYLOAD); // when testClient.completeJobOfType( "external", MsgPackUtil.asMsgPackReturnArray("{'testAttr':'test'}")); testClient.receiveFirstWorkflowInstanceEvent(WorkflowInstanceIntent.ELEMENT_ACTIVATED); // then incident is created final Record incidentEvent = testClient.receiveFirstIncidentEvent(IncidentIntent.CREATED); assertThat(incidentEvent.getKey()).isGreaterThan(0); assertIncidentContainErrorDetails(incidentEvent); }
t -> t.zeebeTaskType("external") .zeebeInput("$.jsonObject", "$") .zeebeOutput("$.foo", "$")) .done());
t -> t.zeebeTaskType("external") .zeebeInput("$.jsonObject", "$") .zeebeOutput("$.foo", "$")) .done());
Bpmn.createExecutableProcess("process") .startEvent() .serviceTask("service", t -> t.zeebeTaskType("external").zeebeInput("$.string", "$")) .done());
Bpmn.createExecutableProcess("process") .startEvent() .serviceTask("service", t -> t.zeebeTaskType("external").zeebeInput("$.string", "$")) .done());
@Test public void shouldUseScopePayloadWhenApplyingOutputMappings() { // given final BpmnModelInstance workflow = Bpmn.createExecutableProcess(PROCESS_ID) .startEvent() .serviceTask("task", b -> b.zeebeTaskType("type").zeebeInput("$.oof", "$.baz")) .boundaryEvent("timer") .cancelActivity(true) .timerWithDuration("PT1S") .zeebeOutputBehavior(ZeebeOutputBehavior.merge) .endEvent("endTimer") .moveToActivity("task") .endEvent() .done(); testClient.deploy(workflow); testClient.createWorkflowInstance(PROCESS_ID, "{\"foo\": 1, \"oof\": 2}"); // when testClient.receiveTimerRecord("timer", TimerIntent.CREATED); brokerRule.getClock().addTime(Duration.ofMinutes(1)); awaitProcessCompleted(); // then final Record<WorkflowInstanceRecordValue> boundaryTriggered = testClient.receiveElementInState("timer", WorkflowInstanceIntent.EVENT_TRIGGERED); assertThat(boundaryTriggered.getValue().getPayloadAsMap()) .contains(entry("foo", 1), entry("oof", 2)); }
@Test public void shouldUseScopePayloadWhenApplyingOutputMappings() { // given final BpmnModelInstance workflow = Bpmn.createExecutableProcess(PROCESS_ID) .startEvent() .serviceTask("task", b -> b.zeebeTaskType("type").zeebeInput("$.oof", "$.baz")) .boundaryEvent("timer") .cancelActivity(true) .timerWithDuration("PT1S") .zeebeOutputBehavior(ZeebeOutputBehavior.merge) .endEvent("endTimer") .moveToActivity("task") .endEvent() .done(); testClient.deploy(workflow); testClient.createWorkflowInstance(PROCESS_ID, "{\"foo\": 1, \"oof\": 2}"); // when testClient.receiveTimerRecord("timer", TimerIntent.CREATED); brokerRule.getClock().addTime(Duration.ofMinutes(1)); awaitProcessCompleted(); // then final Record<WorkflowInstanceRecordValue> boundaryTriggered = testClient.receiveElementInState("timer", WorkflowInstanceIntent.ELEMENT_COMPLETED); assertThat(boundaryTriggered.getValue().getPayloadAsMap()) .contains(entry("foo", 1), entry("oof", 2)); }
t -> t.zeebeTaskType("external") .zeebeInput("$.jsonObject", "$") .zeebeOutput("$.testAttr", "$")) .done());