Creating a Quarkus Workflow Project

As a developer, you can use SonataFlow and create a Hello World application, which includes the following procedures:

Also, you can directly access an example application by cloning serverless-workflow-examples/serverless-workflow-hello-world from the GitHub repository.

This document describes how to create a workflow application that serves a hello_world endpoint. The workflow contains the following two states:

  • Inject Hello World: Injects a Hello World message into the response

  • Inject Mantra: Injects a Mantra message into the response

hello world workflow
Figure 1. Example Hello World workflow
Prerequisites

For more information about the tooling and the required dependencies, see Getting familiar with SonataFlow tooling.

Bootstrapping a project

To create your workflow service, first you need to bootstrap a project.

Procedure
  1. In a command terminal, use one of the following commands to create a project:

    • Quarkus CLI

    • Apache Maven

    • Knative workflow CLI

    Create a project using Quarkus CLI
    quarkus create app \
        -x=kogito-quarkus-serverless-workflow \
        -x=quarkus-resteasy-jackson \
        -x=quarkus-smallrye-openapi \
        --no-code \
        org.acme:serverless-workflow-hello-world:1.0.0-SNAPSHOT

    The previous command creates a Maven Quarkus project in the serverless-workflow-hello-world directory containing the required dependencies, including:

    • kogito-quarkus-serverless-workflow: Adds support for workflows.

    • quarkus-resteasy-jackson: Adds support for RESTEasy, which is required by the generated REST resources that are used to start the flow process using an HTTP request.

    • quarkus-smallrye-openapi: Adds support for Swagger documentation when you run the application in development mode.

    • --no-code: Prevents workflow example code from being generated.

    The SwaggerUI is available at http://localhost:8080/q/swagger-ui/ when you run the application.

    Create a project using Apache Maven
    mvn io.quarkus.platform:quarkus-maven-plugin:2.16.9.Final:create \
        -DprojectGroupId=org.acme \
        -DprojectArtifactId=serverless-workflow-hello-world \
        -Dextensions="kogito-quarkus-serverless-workflow,quarkus-resteasy-jackson,quarkus-smallrye-openapi" \
        -DnoCode
    cd serverless-workflow-hello-world

    In the previous command, org.acme, serverless-workflow-hello-world, and 1.0.0-SNAPSHOT is group ID, artifact ID, and version of your project respectively. -DnoCode prevents the generation of workflow example code.

    Create a project using Knative workflow CLI
    kn workflow create \
      --name serverless-workflow-hello-world \
      --extension quarkus-jsonp,quarkus-smallrye-openapi \
      --quarkus-platform-group-id=io.quarkus.platform \
      --quarkus-version=2.16.9.Final

    For more information about Knative workflow CLI, see SonataFlow plug-in for Knative CLI.

Creating a workflow

After bootstrapping a project, you need to create a workflow. In the following procedure, a workflow named Hello World Workflow is created.

Procedure
  1. Create a file named hello.sw.json in the src/main/resources directory with the following content:

    Example content for hello.sw.json file
    {
      "id": "hello_world", (1)
      "version": "1.0",
      "specVersion": "0.8",
      "name": "Hello World Workflow",
      "description": "JSON based hello world workflow",
      "start": "Inject Hello World", (3)
      "states": [ (2)
        {
          "name": "Inject Hello World",
          "type": "inject", (4)
          "data": { (5)
            "greeting": "Hello World"
          },
          "transition": "Inject Mantra" (6)
        },
        {
          "name": "Inject Mantra",
          "type": "inject",
          "data": {
            "mantra": "Serverless Workflow is awesome!" (7)
          },
          "end": true (8)
        }
      ]
    }

    In the previous example:

    1 id field is the unique identifier of the workflow. SonataFlow generates the REST endpoints based on this unique identifier.
    2 states defines the states of the workflow. In the Hello World example, the workflow contains two states, such as Inject Hello World and Inject Mantra.
    3 start field defines the state in which the workflow starts.
    4 type defines the type of the state. In the previous example, the state is inject. The inject state can be used to inject static data into state data input.
    5 data defines the data that is injected into the state. In the previous example, greeting is injected with the Hello World value.
    6 transition field defines the next state that is reached after the current state is completed.
    7 Injects a mantra with the value Serverless Workflow is awesome! into the workflow data.
    8 end field defines that the current state is the end of the workflow. When the workflow reaches the end state, the workflow stops and the REST endpoint returns the workflow data, such as:
    Example workflow data
    {
      "greeting": "Hello World",
      "mantra": "Serverless Workflow is awesome!"
    }

    The workflow definition follows the CNCF Serverless Workflow specification. For more information, see CNCF Serverless Workflow specification.

Building your workflow application

  1. To verify that project is created, compile the project using the following command:

    • Quarkus CLI

    • Apache Maven

    • Knative workflow CLI

    Compile your project using Quarkus CLI
    quarkus build
    Compile your project using Apache Maven
    mvn clean package
    Build your project and generate a local image called dev.local/serverless-workflow-hello-world:latest
    kn workflow build --image dev.local/serverless-workflow-hello-world --verbose

    The --verbose flag is used to display the output of the build command. This flag is optional.

    For more information about Knative workflow CLI, see SonataFlow plug-in for Knative CLI.

Running your workflow application

After creating a workflow, you can run your workflow application.

Procedure
  1. Enter the following command to run your workflow application:

    • Quarkus CLI

    • Apache Maven

    Run your workflow application using Quarkus CLI
    quarkus dev
    Run your workflow application using Apache Maven
    mvn clean quarkus:dev

    Knative workflow CLI:

    Currently, Knative workflow CLI doesn’t support yet running workflows locally. You can either:

    Run your workflow application using Apache Maven
    mvn clean quarkus:dev
    Run your workflow application using Quarkus CLI
    quarkus dev

    For more information about Knative workflow CLI, see SonataFlow plug-in for Knative CLI.

    Also, to deploy and run your workflow application, see Deploying workflow application on Minikube

    Example response
    [INFO] ------< org.acme:serverless-workflow-hello-world >-------
    [INFO] Building serverless-workflow-hello-world 1.0.0-SNAPSHOT
    [INFO] --------------------------------[ jar ]---------------------------------
    [INFO]
    [INFO] --- quarkus-maven-plugin:2.16.9.Final:dev (default-cli) @ serverless-workflow-hello-world ---
    [INFO] Invoking org.apache.maven.plugins:maven-resources-plugin:2.6:resources) @ serverless-workflow-hello-world
    [INFO] Using 'UTF-8' encoding to copy filtered resources.
    [INFO] Copying 3 resources
    ...more output...
    __  ____  __  _____   ___  __ ____  ______
     --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
     -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
    --\___\_\____/_/ |_/_/|_/_/|_|\____/___/
    2022-05-25 14:38:09,741 INFO  [org.kie.kog.add.qua.mes.com.QuarkusKogitoExtensionInitializer] (Quarkus Main Thread) Registered Kogito CloudEvent extension
    2022-05-25 14:38:09,840 INFO  [io.quarkus] (Quarkus Main Thread) serverless-workflow-hello-world 1.0.0-SNAPSHOT on JVM (powered by Quarkus 2.16.9.Final) started in 6.470s. Listening on: http://localhost:8080
    2022-05-25 14:38:09,843 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
    2022-05-25 14:38:09,843 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cache, cdi, jackson-jq, kogito-addon-messaging-extension, kogito-processes, kogito-serverless-workflow, reactive-routes, rest-client, rest-client-jackson, resteasy, resteasy-jackson, smallrye-context-propagation, smallrye-openapi, smallrye-reactive-messaging, smallrye-reactive-messaging-http, swagger-ui, vertx]
    2022-05-25 14:38:12,877 INFO  [org.kie.kog.qua.pro.dev.DataIndexInMemoryContainer] (docker-java-stream--938264210) STDOUT: __  ____  __  _____   ___  __ ____  ______
    2022-05-25 14:38:12,878 INFO  [org.kie.kog.qua.pro.dev.DataIndexInMemoryContainer] (docker-java-stream--938264210) STDOUT:  --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
    2022-05-25 14:38:12,879 INFO  [org.kie.kog.qua.pro.dev.DataIndexInMemoryContainer] (docker-java-stream--938264210) STDOUT:  -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
    2022-05-25 14:38:12,879 INFO  [org.kie.kog.qua.pro.dev.DataIndexInMemoryContainer] (docker-java-stream--938264210) STDOUT: --\___\_\____/_/ |_/_/|_/_/|_|\____/___/
    2022-05-25 14:38:12,879 INFO  [org.kie.kog.qua.pro.dev.DataIndexInMemoryContainer] (docker-java-stream--938264210) STDOUT: 2022-05-25 17:38:09,692 INFO  [io.zon.tes.db.pos.emb.EmbeddedPostgres] (main) Detected a Linux x86_64 system
    2022-05-25 14:38:12,880 INFO  [org.kie.kog.qua.pro.dev.DataIndexInMemoryContainer] (docker-java-stream--938264210) STDOUT: 2022-05-25 17:38:09,705 INFO  [io.zon.tes.db.pos.emb.DefaultPostgresBinaryResolver] (main) Detected distribution: 'Red Hat Enterprise Linux'
    ...more output...
    2022-05-25 14:38:12,889 INFO  [org.kie.kog.qua.pro.dev.DataIndexInMemoryContainer] (docker-java-stream--938264210) STDOUT: 2022-05-25 17:38:12,332 INFO  [io.zon.tes.db.pos.emb.EmbeddedPostgres] (postgres:pid(90)) 2022-05-25 17:38:12.332 UTC [99] LOG:  incomplete startup packet
    2022-05-25 14:38:12,890 INFO  [org.kie.kog.qua.pro.dev.DataIndexInMemoryContainer] (docker-java-stream--938264210) STDOUT: 2022-05-25 17:38:12,405 INFO  [io.zon.tes.db.pos.emb.EmbeddedPostgres] (main) 5df1ed6e-7a15-4091-bcfb-e293aa293bfe postmaster startup finished in 00:00:00.180
    2022-05-25 14:38:12,890 INFO  [org.kie.kog.qua.pro.dev.DataIndexInMemoryContainer] (docker-java-stream--938264210) STDOUT: 2022-05-25 17:38:12,405 INFO  [org.kie.kog.per.inm.pos.run.InmemoryPostgreSQLRecorder] (main) Embedded Postgres started at port "44729" with database "postgres", user "postgres" and password "postgres"
    2022-05-25 14:38:12,890 INFO  [org.kie.kog.qua.pro.dev.DataIndexInMemoryContainer] (docker-java-stream--938264210) STDOUT: 2022-05-25 17:38:12,636 WARN  [io.qua.run.con.ConfigRecorder] (main) Build time property cannot be changed at runtime:
    2022-05-25 14:38:13,375 INFO  [org.kie.kog.qua.pro.dev.DataIndexInMemoryContainer] (docker-java-stream--938264210) STDOUT: 2022-05-25 17:38:13,105 INFO  [org.kie.kog.per.pro.ProtobufService] (main) Registering Kogito ProtoBuffer file: kogito-index.proto
    2022-05-25 14:38:13,377 INFO  [org.kie.kog.qua.pro.dev.DataIndexInMemoryContainer] (docker-java-stream--938264210) STDOUT: 2022-05-25 17:38:13,132 INFO  [org.kie.kog.per.pro.ProtobufService] (main) Registering Kogito ProtoBuffer file: kogito-types.proto
    2022-05-25 14:38:13,378 INFO  [org.kie.kog.qua.pro.dev.DataIndexInMemoryContainer] (docker-java-stream--938264210) STDOUT: 2022-05-25 17:38:13,181 INFO  [io.quarkus] (main) data-index-service-inmemory 1.22.0.Final on JVM (powered by Quarkus 2.9.0.Final) started in 4.691s. Listening on: http://0.0.0.0:8080
    2022-05-25 14:38:13,379 INFO  [org.kie.kog.qua.pro.dev.DataIndexInMemoryContainer] (docker-java-stream--938264210) STDOUT: 2022-05-25 17:38:13,182 INFO  [io.quarkus] (main) Profile prod activated.
    2022-05-25 14:38:13,380 INFO  [org.kie.kog.qua.pro.dev.DataIndexInMemoryContainer] (docker-java-stream--938264210) STDOUT: 2022-05-25 17:38:13,182 INFO  [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, hibernate-orm-panache, inmemory-postgres, jdbc-postgresql, narayana-jta, oidc, reactive-routes, rest-client-reactive, rest-client-reactive-jackson, security, smallrye-context-propagation, smallrye-graphql-client, smallrye-health, smallrye-metrics, smallrye-reactive-messaging, smallrye-reactive-messaging-http, vertx, vertx-graphql]
  2. Once your workflow application is started, you can send a request for the provided endpoint:

    Example request
    curl -X POST -H 'Content-Type:application/json' http://localhost:8080/hello_world
    Example response
    {"id":"efb59bfa-ad9c-4062-a6d2-2d9184dd4b3d","workflowdata":{"greeting":"Hello World","mantra":"Serverless Workflow is awesome!"}}
  3. When running in development mode (using Quarkus CLI or Apache Maven), you can update your workflow with a new mantra value without restarting the application.

    Update your workflow
    {
      "name": "Inject Mantra",
      "type": "inject",
      "data": {
        "mantra": "Serverless Workflow is amazing!" (1)
      },
      "end": true
    }
    1 New mantra value
    Example request
    curl -X POST -H 'Content-Type:application/json' http://localhost:8080/hello_world
    Example response
    {"id":"efb59bfa-ad9c-4062-a6d2-2d9184dd4b3d","workflowdata":{"greeting":"Hello World","mantra":"Serverless Workflow is amazing!"}}

    Note that the mantra value is updated without restarting the application, because SonataFlow leverages the Quarkus live coding feature.

  4. To stop the application, press CTRL+C.

Testing your workflow application

To test your workflow application, you can follow the instructions in the Testing your workflow application using REST Assured.

Found an issue?

If you find an issue or any misleading information, please feel free to report it here. We really appreciate it!