0

I'm trying to loop over an array of data and calling A Rest endpoint for each item in this array, using a serverless-workflow script running on Kogito & Quarkus.

I've modified the following project getting-started-with-serverless-workflow to include a foreach state that calls the Rest endpoint. The resulting workflow is:

{
  "id": "greeting",
  "version": "1.0",
  "specVersion": "0.8",
  "name": "Greeting workflow",
  "description": "JSON based greeting workflow",
  "start": "Loop",
  "functions": [
    {
      "name": "getGreetingFunction",
      "operation": "openapi.yml#getGreeting"
    }
  ],
  "states": [    
    {
      "name": "Loop",
      "type": "foreach",
      "inputCollection": ".languages",
      "iterationParam": "item",
      "outputCollection": ".greetings",
      "actions": [
        {
          "name": "getGreeting",
          "functionRef": {
            "refName": "getGreetingFunction",
            "arguments": {
                  "name": "${ .name }",
                  "language": "${ .item }"
              }
          }
        }
      ],      
      "end": true
    }
  ]
}

I'm calling this workflow with the following command :

curl -X POST -H 'Content-Type:application/json' -H 'Accept:application/json' -d '{"workflowdata" : {"name": "Helber", "language": ["Spanish","English"]}}' http://localhost:8080/greeting

There are two things that are not working and I don't understand why they aren't, based on the serverless-workflow specification:

  1. "${ .item }" is always null ( same with the syntax ".item" ), which of course generates errors as an output

  2. When replacing "${ .item }" with a fixed value, the output is this:

    { "id": "a20dfd1d-d6bd-41c6-b45f-be1ed9eb962c", "workflowdata": { "name": "Helber", "language": [ "Spanish", "English", "Spanish" ], "greeting": "Greetings from Serverless Workflow, Helber!", "greetings": [] } }

Why isn't the outputCollection of the foreach state .greetings, populated with the results from the two calls ?

Edit: I should have added that those messages always show up when executing the workflow:

2022-09-02 17:15:55,227 WARN  [org.kog.wor.res.RestWorkItemHandler] (executor-thread-0) Cannot find definition for variable Loop_5
2022-09-02 17:15:55,296 ERROR [org.jbp.wor.ins.imp.NodeInstanceImpl] (executor-thread-0) Could not find variable Loop_5
2022-09-02 17:15:55,296 ERROR [org.jbp.wor.ins.imp.NodeInstanceImpl] (executor-thread-0) Using process-level scope
2022-09-02 17:15:55,298 INFO  [org.kie.kog.exp.jq.JqExpressionHandler] (executor-thread-0) Using default scope

Thanks for your help !

Cyril C.
  • 112
  • 8

2 Answers2

2

This is bug. It will be corrected with https://github.com/kiegroup/kogito-runtimes/pull/2465

  • JIRA was fixed and it will be available in Kogito 1.28.0. See also https://github.com/serverlessworkflow/specification/issues/682. For now we will be supporting . prefix for accessing the iterationParam within an expression in a ForEachLoop state, but I consider $ prefix more appropiated – Francisco Javier Tirado Sarti Sep 16 '22 at 10:26
1

UPDATE: it seems like for rest operations, the iterationParam is returning null inside the action loop. See https://issues.redhat.com/browse/KOGITO-7924

Kogito supports the CNCF Serverless Workflow specification version 0.8 at this time. Then, please, when looking at the specification docs, try to use the 0.8 branch. Might be a difference between the implementation and the latest spec.

That said, I tried your workflow using the sysout custom function for simplicity:

{
    "id": "greeting",
    "version": "1.0",
    "specVersion": "0.8",
    "name": "Greeting workflow",
    "description": "JSON based greeting workflow",
    "start": "Loop",
    "functions": [
      {
        "name": "getGreetingFunction",
        "type": "custom",
        "operation": "sysout"
      }
    ],
    "states": [    
      {
        "name": "Loop",
        "type": "foreach",
        "inputCollection": ".languages",
        "iterationParam": "item",
        "outputCollection": ".greetings",
        "actions": [
          {
            "name": "getGreeting",
            "functionRef": {
              "refName": "getGreetingFunction",
              "arguments": {
                    "message": "${ .name + .item }"
                }
            }
          }
        ],      
        "end": true
      }
    ]
  }

This function will output the result to your console.

2022-09-02 16:59:03,283 INFO  [org.kie.kog.ser.wor.dev.DevModeServerlessWorkflowLogger] (executor-thread-0) Triggered node 'Start' for process 'greeting' (02056b12-1ad4-46f9-8627-7dfab0bd6ee0)
2022-09-02 16:59:03,287 INFO  [org.kie.kog.ser.wor.dev.DevModeServerlessWorkflowLogger] (executor-thread-0) Triggered node 'ForEach' for process 'greeting' (02056b12-1ad4-46f9-8627-7dfab0bd6ee0)
2022-09-02 16:59:03,299 INFO  [org.kie.kog.ser.wor.dev.DevModeServerlessWorkflowLogger] (executor-thread-0) Triggered node 'getGreetingFunction' for process 'greeting' (02056b12-1ad4-46f9-8627-7dfab0bd6ee0)
ZaniniEnglish
2022-09-02 16:59:03,309 INFO  [org.kie.kog.ser.wor.dev.DevModeServerlessWorkflowLogger] (executor-thread-0) Triggered node 'getGreetingFunction' for process 'greeting' (02056b12-1ad4-46f9-8627-7dfab0bd6ee0)
ZaniniSpanish
2022-09-02 16:59:03,311 INFO  [org.kie.kog.ser.wor.dev.DevModeServerlessWorkflowLogger] (executor-thread-0) Triggered node 'getGreetingFunction' for process 'greeting' (02056b12-1ad4-46f9-8627-7dfab0bd6ee0)
ZaniniPortuguese
2022-09-02 16:59:03,315 INFO  [org.kie.kog.ser.wor.dev.DevModeServerlessWorkflowLogger] (executor-thread-0) Triggered node 'End' for process 'greeting' (02056b12-1ad4-46f9-8627-7dfab0bd6ee0)
2022-09-02 16:59:03,317 INFO  [org.kie.kog.qua.pro.dev.DevModeWorkflowLogger] (executor-thread-0) Workflow 'greeting' (02056b12-1ad4-46f9-8627-7dfab0bd6ee0) completed

My data input is:

{
  "workflowdata": {
     "name": "Zanini",
     "languages": ["English", "Spanish", "Portuguese"]
  }
}

Note that the inputCollection attribute is languages, not language like you used; maybe a typo? That refers to a collection in your model.

outputCollection will be populated if the actions return a value. In this case, the function won't return anything, hence an empty collection at the end of the execution:

{
  "id": "02056b12-1ad4-46f9-8627-7dfab0bd6ee0",
  "workflowdata": {
    "name": "Zanini",
    "languages": [
      "English",
      "Spanish",
      "Portuguese"
    ],
    "greetings": []
  }
}

That helps?

Ricardo Zanini
  • 1,041
  • 7
  • 12
  • Thanks for your answer Ricardo ! Prior to asking my question, I was able to run wrokflows like yours and obtain the same results. However, my problems happen as soon as I try to include a REST call as an action in the Foreach state ( ".item" not being resolved correctly & result not being added to the output collection ). Do you know if it is supported by the latest version of Kogito ? – Cyril C. Sep 05 '22 at 14:03
  • Yes, it's working. I just tested this workflow with the latest version! – Ricardo Zanini Sep 05 '22 at 18:14
  • I'm quite sure yours works, it does on my setup as well ;) Would you be so kind as to try and test it with a dummy call to any Rest endpoint inside the foreach state ? – Cyril C. Sep 07 '22 at 15:23
  • 1
    Hi! Weirdly enough, indeed is not working for rest operations. I've opened a JIRA: https://issues.redhat.com/browse/KOGITO-7924 – Ricardo Zanini Sep 13 '22 at 19:55
  • Thanks a lot Ricardo, I'll keep a close eye on this issue :) ! – Cyril C. Sep 14 '22 at 07:47