Getting started with Quarkus Flow

This tutorial shows the shortest path to run a Quarkus Flow workflow inside your Quarkus application, using Quarkus-native ergonomics (CDI, build-time discovery, dev mode).

1. Prerequisites

  • Java 17 or newer with JAVA_HOME configured.

  • Maven 3.8+.

  • A Quarkus project. You can generate one with:

    mvn io.quarkus:quarkus-maven-plugin:create

2. Add the dependency

Add the Quarkus Flow extension to your application.

Maven
<dependency>
  <groupId>io.quarkiverse.flow</groupId>
  <artifactId>quarkus-flow</artifactId>
  <version>0.3.0</version>
</dependency>

3. Define a minimal workflow

Create a Flow subclass. At build time, Quarkus Flow discovers it and makes it injectable as a CDI bean.

The example below defines a simple workflow that sets a JSON message into the workflow context.

package org.acme;

import static io.serverlessworkflow.fluent.func.dsl.FuncDSL.set;

import jakarta.enterprise.context.ApplicationScoped;

import io.quarkiverse.flow.Flow;
import io.serverlessworkflow.api.types.Workflow;
import io.serverlessworkflow.fluent.func.FuncWorkflowBuilder;

@ApplicationScoped
public class HelloWorkflow extends Flow {
    @Override
    public Workflow descriptor() {
        return FuncWorkflowBuilder.workflow("hello")
                // jq expression to set our context to the JSON object `message`
                .tasks(set("{ message: \"hello world!\" }"))
                .build();
    }
}

4. Expose the workflow via HTTP

There are two ergonomic options depending on how much control you want over the injection point.

Inject the HelloWorkflow bean directly and use the convenience methods on Flow to start a new instance.

package org.acme;

import java.util.Map;
import java.util.concurrent.CompletionStage;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

import org.jboss.resteasy.reactive.ResponseStatus;

@Path("/hello")
@ApplicationScoped
public class HelloResource {

    @Inject
    HelloWorkflow hello; // inject the Flow subclass

    @GET
    @ResponseStatus(200)
    public CompletionStage<Message> hello() {
        return hello
                .startInstance(Map.of()) // convenience on Flow
                .thenApply(w -> w.as(Message.class).orElseThrow());
    }
}

4.2. Inject the compiled definition (advanced)

If you need the compiled WorkflowDefinition, you can inject it by FQCN instead. This is useful when you want to work at a more generic level (for example, selecting workflows dynamically).

import io.smallrye.common.annotation.Identifier;
import io.serverlessworkflow.impl.WorkflowDefinition;

@Inject
@Identifier("org.acme.HelloWorkflow") // FQCN of the workflow class
WorkflowDefinition helloDef;

5. Run the application

Start Quarkus in dev mode:

./mvnw quarkus:dev

Then invoke the HTTP endpoint you exposed (for example, if HelloResource is mapped to /hello):

curl http://localhost:8080/hello

You should see a JSON response with the message produced by the workflow.

6. What’s next?