Define workflows from YAML files
Quarkus Flow recommends the Java DSL as the primary way to define workflows because it provides type safety, refactoring support, and excellent IDE integration.
However, Quarkus Flow fully supports loading CNCF Serverless Workflow 1.0.0 definitions written in YAML or JSON. This is ideal for teams that already maintain specification files or need to share definitions across different runtime environments.
This guide shows you how to load a YAML workflow into your Quarkus application and expose it as a standard Flow CDI bean that you can inject and execute.
Prerequisites
-
A Quarkus application with Quarkus Flow set up.
-
Basic familiarity with YAML and the Serverless Workflow Specification.
1. Create the workflow specification file
By default, Quarkus Flow scans the src/main/flow directory (relative to your Maven module root) for workflow specification files at build time.
Create the directory and add your CNCF 1.0.0 workflow:
document:
dsl: '1.0.0'
namespace: company
name: echo-name
version: '0.1.0'
do:
- setEcho:
set:
message: '${ "echo: " + .name }'
This definition:
-
Declares the workflow metadata in the
documentsection (DSL version, namespace, name, version). -
Defines a single
settask that writes amessagefield into the global workflow data based on the input.name.
|
You can customize the discovery directory by setting the It accepts an absolute path or a path relative to the Maven module root. All |
2. Inject the Flow bean
During the Quarkus build, the engine parses your YAML files and generates WorkflowDefinition and Flow CDI beans for them.
Quarkus Flow uses the document.namespace and document.name fields from your YAML file to create a unique identifier for the bean. It generates two formats you can use:
-
Fully Qualified Class Name (Recommended):
namespace.name(e.g., if your YAML hasnamespace: org.acmeandname: EchoWorkflow, the identifier isorg.acme.EchoWorkflow). -
Regular:
namespace:name(e.g.,org.acme:EchoWorkflow).
Create a JAX-RS resource that injects and runs the workflow using the generated identifier:
package org.acme;
import java.util.Map;
import java.util.Objects;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;
import io.quarkiverse.flow.Flow;
import io.smallrye.common.annotation.Identifier;
import io.smallrye.mutiny.Uni;
@Path("/echo")
public class EchoResource {
@Inject
@Identifier("company.EchoName") (1)
Flow flow;
@GET
public Uni<String> echo(@QueryParam("name") String name) {
final String finalName = Objects.requireNonNullElse(name, "(Duke)");
return flow.startInstance(Map.of("name", finalName))
.onItem()
.transform(wf -> wf.asText().orElseThrow());
}
}
| 1 | Use the @Identifier annotation with the Fully Qualified Class Name derived from your YAML file. |
|
The |
|
You can define a global namespace prefix for the identifiers using the |
2.1 Reactive Execution and Error Handling
The EchoResource example uses the recommended non-blocking style for Quarkus REST endpoints (returning a Uni<String>).
A typical execution flow looks like this:
-
flow.startInstance(…)executes the workflow non-blocking and returns aUni<WorkflowInstance>. -
.map(WorkflowInstance::output)extracts just the final JSON payload.
Because it is non-blocking, if the YAML workflow encounters an error (e.g., an HTTP task fails), the WorkflowException propagates cleanly to the HTTP layer. Quarkus Flow automatically translates it into an RFC 7807 Problem Details HTTP response.
(For a deeper discussion on error mapping and the pitfalls of blocking .join() calls, see HTTP Errors and Exception Mapping).
3. Run and live-reload
Start your Quarkus application in development mode:
./mvnw quarkus:dev
Call your new REST endpoint:
curl "http://localhost:8080/echo?name=John"
# Expected JSON response:
# {"message":"echo: John"}
The best part: Because Quarkus Flow integrates seamlessly with Quarkus dev mode, any changes you make to the YAML file in src/main/flow will be picked up and live-reloaded immediately. You do not need to restart your application when tweaking YAML tasks!
See also
-
Serverless Workflow Spec mapping and concepts — a quick orientation to the 1.0.0 specification components.
-
Data flow and context management — understand how data mutates across YAML tasks.
-
Test and debug workflows — learn how to write unit tests for your injected
Flowbeans.