Migration Guide: 0.15.x to 0.16.0
Quarkus Flow 0.16.0 includes several breaking changes:
-
Client routing: HTTP and gRPC task-level routing keys use a new unified format.
-
Runner security:
quarkus.flow.runner.security.typeis now a required property. -
Shell execution:
run.shelltasks require an explicit command allowlist. -
Symlinks: Workflow file scanning now skips symbolic links by default.
-
Micrometer metrics: Metrics are now auto-enabled when Micrometer is on the classpath.
-
DSL:
FuncForTaskBuilder.collection()now requiresSerializableFunction. == Why the change?
In 0.15.1, HTTP, gRPC, and OIDC each had different configuration shapes:
-
HTTP used nested maps (
workflow.<name>.task.<taskName>.name), supporting only 2 levels (task, then workflow). -
gRPC used flat composite keys with colons as task separators (
<namespace>:<name>:<version>:<taskName>), supporting 3 levels. -
OIDC had its own naming convention, separate from both.
This inconsistency made configuration confusing and prevented simple name-only keys for gRPC.
0.16.0 introduces a unified ClientNamingConvention and ClientConfigCascade shared by all three protocols, with a consistent .task. separator and support for namespace-aware, version-aware routing at all levels.
Resolution cascade
All protocols now resolve client names using the same 6-level progressive specificity cascade. The first match wins:
| Priority | Level | Key format |
|---|---|---|
1 |
Task (full) |
|
2 |
Task (medium) |
|
3 |
Task (short) |
|
4 |
Workflow (full) |
|
5 |
Workflow (medium) |
|
6 |
Workflow (short) |
|
If no task name is provided, priorities 1-3 are skipped.
What changed
HTTP client routing
| Before (0.15.1) | After (0.16.0) |
|---|---|
Nested map: |
Flat composite key: |
Workflow-level only by name |
Workflow-level by name, namespace:name, or namespace:name:version |
2-level resolution (task, then workflow) |
6-level resolution cascade |
Step-by-step migration
1. Update HTTP task-level routing properties
Workflow-level HTTP properties using only the workflow name are unchanged:
# No change needed
quarkus.flow.http.client.workflow.orders.name=secureA
Task-level HTTP properties must change from nested format to flat composite key format:
# Before (0.15.1) — nested task sub-key
quarkus.flow.http.client.workflow.orders.task.payment.name=secureB
# After (0.16.0) — flat composite key with .task. separator
quarkus.flow.http.client.workflow."orders.task.payment".name=secureB
2. Update gRPC task-level routing properties
Workflow-level gRPC properties are unchanged:
# No change needed
quarkus.flow.grpc.client."org.acme:grpcGreeting:0.0.1".name=my-channel
quarkus.flow.grpc.client."org.acme:grpcGreeting".name=my-channel
Task-level gRPC properties must replace the trailing colon with .task.:
# Before (0.15.1) — colon task separator
quarkus.flow.grpc.client."org.acme:grpcGreeting:0.0.1:greet".name=my-channel
# After (0.16.0) — .task. separator
quarkus.flow.grpc.client."org.acme:grpcGreeting:0.0.1.task.greet".name=my-channel
New capabilities
Name-only keys (short keys)
Both HTTP and gRPC now accept simple name-only keys. This covers the common case where there is no namespace or version ambiguity:
# Works for both HTTP and gRPC
quarkus.flow.http.client.workflow.orders.name=secureA
quarkus.flow.grpc.client.orders.name=my-channel
Namespace and version-aware routing
When multiple namespaces define workflows with the same name, use a more specific key:
# Medium — namespace:name
quarkus.flow.http.client.workflow."acme:orders".name=secureA
# Full — namespace:name:version
quarkus.flow.http.client.workflow."acme:orders:1.0.0".name=secureA
The same applies to gRPC and OIDC.
Runner security type is now required
In 0.15.x, quarkus.flow.runner.security.type defaulted to none.
In 0.16.0, this property has no default — you must set it explicitly.
This ensures that security is a deliberate configuration choice, not an implicit default that could be accidentally deployed to production.
# Choose one:
quarkus.flow.runner.security.type=none
quarkus.flow.runner.security.type=api-key
quarkus.flow.runner.security.type=oidc
Without this property, the application fails at startup with:
SRCFG00014: The config property quarkus.flow.runner.security.type is required
This only affects applications using the quarkus-flow-runner extension.
|
Shell execution requires an allowlist
run.shell tasks now require an explicit command allowlist.
An empty list (the default) disables all shell execution.
If your workflows invoke shell commands, add the allowed executables:
quarkus.flow.run.shell.allowed-commands=curl,jq,grep
Without this, run.shell tasks fail at runtime.
Micrometer metrics auto-enabled
In 0.15.x, Micrometer metrics required quarkus.flow.metrics.enabled=true to activate.
In 0.16.0, metrics are enabled automatically when Micrometer is on the classpath.
To disable:
quarkus.flow.metrics.enabled=false
DSL: collection() requires SerializableFunction
FuncForTaskBuilder.collection() now accepts SerializableFunction<T, Collection<V>> instead of Function<T, Collection<V>>.
Lambda expressions passed to .collection() work without changes — Java lambdas implement Serializable when the target interface extends it.
If you pass a method reference or an explicit Function<> variable, update the type:
// Before (0.15.x)
Function<MyInput, Collection<Item>> fn = MyInput::getItems;
builder.collection(fn); // compile error in 0.16.0
// After (0.16.0)
SerializableFunction<MyInput, Collection<Item>> fn = MyInput::getItems;
builder.collection(fn);
Symlinks skipped by default when scanning workflow files
Workflow file scanning now skips symbolic links by default. This prevents duplicate workflow detection failures on Kubernetes, where ConfigMap volume mounts use internal symlinks.
If your workflows are intentionally provided via symbolic links outside of Kubernetes:
# Runner (runtime)
quarkus.flow.runner.source.follow-symlinks=true
# Core (build-time)
quarkus.flow.definitions.follow-symlinks=true
New features
OpenTelemetry tracing
New quarkus-flow-opentelemetry extension provides distributed tracing for workflow execution.
See OpenTelemetry for setup instructions.
File watcher for runtime workflow loading
The runner can now poll for new workflow files at runtime without requiring a pod restart:
# Build-time (requires rebuild)
quarkus.flow.runner.source.watch.enabled=true
# Runtime
quarkus.flow.runner.source.watch.interval=5s