diff --git a/core/deployment/pom.xml b/core/deployment/pom.xml
index 72b88fa..0967f36 100644
--- a/core/deployment/pom.xml
+++ b/core/deployment/pom.xml
@@ -20,6 +20,15 @@
quarkus-flow
${project.version}
+
+
+ io.quarkus
+ quarkus-rest-client-jackson-deployment
+
+
+ io.quarkiverse.jackson-jq
+ quarkus-jackson-jq-deployment
+
io.serverlessworkflow
serverlessworkflow-fluent-spec
diff --git a/core/deployment/src/main/java/io/quarkiverse/flow/deployment/DiscoveredFlowBuildItem.java b/core/deployment/src/main/java/io/quarkiverse/flow/deployment/DiscoveredFlowBuildItem.java
index 7363166..4535100 100644
--- a/core/deployment/src/main/java/io/quarkiverse/flow/deployment/DiscoveredFlowBuildItem.java
+++ b/core/deployment/src/main/java/io/quarkiverse/flow/deployment/DiscoveredFlowBuildItem.java
@@ -13,6 +13,7 @@ public DiscoveredFlowBuildItem(MethodInfo method, String workflowName) {
method.declaringClass().name().toString(),
method.name(),
workflowName,
+ method.parameterTypes().stream().map(t -> t.name().toString()).toArray(String[]::new),
method.isStaticInitializer());
}
diff --git a/core/deployment/src/main/java/io/quarkiverse/flow/deployment/FlowNativeProcessor.java b/core/deployment/src/main/java/io/quarkiverse/flow/deployment/FlowNativeProcessor.java
index 5a2ea2a..614d27d 100644
--- a/core/deployment/src/main/java/io/quarkiverse/flow/deployment/FlowNativeProcessor.java
+++ b/core/deployment/src/main/java/io/quarkiverse/flow/deployment/FlowNativeProcessor.java
@@ -1,26 +1,58 @@
package io.quarkiverse.flow.deployment;
+import com.github.f4b6a3.ulid.UlidCreator;
+import com.github.f4b6a3.ulid.UlidFactory;
+
+import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem;
+import io.serverlessworkflow.impl.events.EventConsumer;
+import io.serverlessworkflow.impl.events.EventPublisher;
+import io.serverlessworkflow.impl.events.InMemoryEvents;
+import io.serverlessworkflow.impl.executors.DefaultTaskExecutorFactory;
+import io.serverlessworkflow.impl.executors.TaskExecutorFactory;
+import io.serverlessworkflow.impl.expressions.ExpressionFactory;
+import io.serverlessworkflow.impl.expressions.jq.JQExpressionFactory;
+import io.serverlessworkflow.impl.jackson.schema.JsonSchemaValidatorFactory;
+import io.serverlessworkflow.impl.schema.SchemaValidatorFactory;
-/**
- * see Native-image build fails due to UlidCreator static
- * initialization (Random in image heap)
- */
final class FlowNativeProcessor {
- @BuildStep
- RuntimeInitializedClassBuildItem ulidCreatorHolder() {
- return new RuntimeInitializedClassBuildItem("com.github.f4b6a3.ulid.UlidCreator$MonotonicFactoryHolder");
- }
+ /**
+ * see Native-image build fails due to UlidCreator
+ * static
+ * initialization (Random in image heap)
+ */
@BuildStep
- RuntimeInitializedClassBuildItem ulidCreator() {
- return new RuntimeInitializedClassBuildItem("com.github.f4b6a3.ulid.UlidCreator");
+ void runtimeInitUlid(BuildProducer producer) {
+ producer.produce(new RuntimeInitializedClassBuildItem(
+ "com.github.f4b6a3.ulid.UlidCreator$MonotonicFactoryHolder"));
+ producer.produce(new RuntimeInitializedClassBuildItem(
+ com.github.f4b6a3.ulid.UlidCreator.class.getName()));
+ producer.produce(new RuntimeInitializedClassBuildItem(
+ com.github.f4b6a3.ulid.UlidFactory.class.getName()));
}
+ /**
+ * Registers the CNCF Java SDK default providers for native compilation.
+ */
@BuildStep
- RuntimeInitializedClassBuildItem ulidFactory() {
- return new RuntimeInitializedClassBuildItem("com.github.f4b6a3.ulid.UlidFactory");
+ void registerSDKServiceProviders(BuildProducer sp) {
+
+ // TODO: make all of them @DefaultBeans so users can easily replace
+ // TODO: these providers must be compatible with Quarkus Ecosystem
+
+ sp.produce(new ServiceProviderBuildItem(ExpressionFactory.class.getName(),
+ JQExpressionFactory.class.getName()));
+ sp.produce(new ServiceProviderBuildItem(TaskExecutorFactory.class.getName(),
+ DefaultTaskExecutorFactory.class.getName()));
+ sp.produce(new ServiceProviderBuildItem(SchemaValidatorFactory.class.getName(),
+ JsonSchemaValidatorFactory.class.getName()));
+ sp.produce(new ServiceProviderBuildItem(EventConsumer.class.getName(),
+ InMemoryEvents.class.getName()));
+ sp.produce(new ServiceProviderBuildItem(EventPublisher.class.getName(),
+ InMemoryEvents.class.getName()));
}
}
diff --git a/core/deployment/src/main/java/io/quarkiverse/flow/deployment/FlowProcessor.java b/core/deployment/src/main/java/io/quarkiverse/flow/deployment/FlowProcessor.java
index 08af9ef..a159399 100644
--- a/core/deployment/src/main/java/io/quarkiverse/flow/deployment/FlowProcessor.java
+++ b/core/deployment/src/main/java/io/quarkiverse/flow/deployment/FlowProcessor.java
@@ -11,10 +11,7 @@
import io.quarkiverse.flow.FlowDefinition;
import io.quarkiverse.flow.FlowDescriptor;
-import io.quarkiverse.flow.producers.DefaultExpressionFactoryProducer;
-import io.quarkiverse.flow.producers.DefaultSchemaValidatorFactoryProducer;
-import io.quarkiverse.flow.producers.DefaultTaskExecutorFactoryProducer;
-import io.quarkiverse.flow.producers.InMemoryEventsBean;
+import io.quarkiverse.flow.providers.QuarkusJQExpressionFactory;
import io.quarkiverse.flow.recorders.FlowRecorder;
import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
@@ -26,7 +23,7 @@
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.ShutdownContextBuildItem;
-import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ReflectiveMethodBuildItem;
import io.serverlessworkflow.impl.WorkflowApplication;
import io.serverlessworkflow.impl.WorkflowDefinition;
@@ -69,9 +66,9 @@ void collectFlowDescriptors(CombinedIndexBuildItem index, BuildProducer discovered,
BuildProducer keep,
- BuildProducer reflective) {
+ BuildProducer reflective) {
- var owners = discovered.stream()
+ List owners = discovered.stream()
.map(d -> d.workflow.className)
.distinct()
.toList();
@@ -79,14 +76,8 @@ void keepAndReflectFlowDescriptors(
// Keep producers from being removed
keep.produce(UnremovableBeanBuildItem.beanClassNames(owners.toArray(String[]::new)));
- // Make all declared methods on the owner classes available at runtime
- for (String cn : owners) {
- reflective.produce(
- ReflectiveClassBuildItem.builder(cn)
- .methods(true) // keep methods (needed for MethodHandles / reflection)
- .fields(false) // not needed here
- .constructors(false)
- .build());
+ for (DiscoveredFlowBuildItem d : discovered) {
+ reflective.produce(new ReflectiveMethodBuildItem(d.workflow.className, d.workflow.methodName, d.workflow.params));
}
}
@@ -104,10 +95,7 @@ AdditionalBeanBuildItem coreBeans() {
@BuildStep
AdditionalBeanBuildItem registerRuntimeDefaults() {
return AdditionalBeanBuildItem.builder()
- .addBeanClass(InMemoryEventsBean.class)
- .addBeanClass(DefaultExpressionFactoryProducer.class)
- .addBeanClass(DefaultSchemaValidatorFactoryProducer.class)
- .addBeanClass(DefaultTaskExecutorFactoryProducer.class)
+ .addBeanClass(QuarkusJQExpressionFactory.class)
.setUnremovable()
.build();
}
diff --git a/core/pom.xml b/core/pom.xml
index 1aedcab..5820d18 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -16,20 +16,4 @@
runtime
deployment
-
-
-
- io.serverlessworkflow
- serverlessworkflow-impl-core
-
-
- io.serverlessworkflow
- serverlessworkflow-impl-http
-
-
- io.serverlessworkflow
- serverlessworkflow-impl-jackson
-
-
-
diff --git a/core/runtime/pom.xml b/core/runtime/pom.xml
index e5d11d1..5ad9acd 100644
--- a/core/runtime/pom.xml
+++ b/core/runtime/pom.xml
@@ -11,15 +11,40 @@
Quarkus Flow :: Core :: Runtime
+
- io.quarkus
- quarkus-arc
+ io.serverlessworkflow
+ serverlessworkflow-impl-core
+
+
+ io.serverlessworkflow
+ serverlessworkflow-impl-http
+
+
+ io.serverlessworkflow
+ serverlessworkflow-impl-jackson
io.serverlessworkflow
serverlessworkflow-fluent-spec
${io.serverlessworkflow.version}
+
+
+
+ io.quarkus
+ quarkus-arc
+
+
+ io.quarkiverse.jackson-jq
+ quarkus-jackson-jq
+
+
+
+ io.quarkus
+ quarkus-rest-client-jackson
+
+
diff --git a/core/runtime/src/main/java/io/quarkiverse/flow/producers/DefaultExpressionFactoryProducer.java b/core/runtime/src/main/java/io/quarkiverse/flow/producers/DefaultExpressionFactoryProducer.java
deleted file mode 100644
index e244ccd..0000000
--- a/core/runtime/src/main/java/io/quarkiverse/flow/producers/DefaultExpressionFactoryProducer.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package io.quarkiverse.flow.producers;
-
-import jakarta.enterprise.inject.Produces;
-import jakarta.inject.Singleton;
-
-import io.quarkus.arc.DefaultBean;
-import io.serverlessworkflow.impl.expressions.ExpressionFactory;
-import io.serverlessworkflow.impl.expressions.jq.JQExpressionFactory;
-
-public class DefaultExpressionFactoryProducer {
- @Produces
- @Singleton
- @DefaultBean
- ExpressionFactory expressionFactory() {
- return new JQExpressionFactory();
- }
-}
diff --git a/core/runtime/src/main/java/io/quarkiverse/flow/producers/DefaultSchemaValidatorFactoryProducer.java b/core/runtime/src/main/java/io/quarkiverse/flow/producers/DefaultSchemaValidatorFactoryProducer.java
deleted file mode 100644
index 4d475ea..0000000
--- a/core/runtime/src/main/java/io/quarkiverse/flow/producers/DefaultSchemaValidatorFactoryProducer.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package io.quarkiverse.flow.producers;
-
-import jakarta.enterprise.inject.Produces;
-import jakarta.inject.Singleton;
-
-import io.quarkus.arc.DefaultBean;
-import io.serverlessworkflow.impl.jackson.schema.JsonSchemaValidatorFactory;
-import io.serverlessworkflow.impl.schema.SchemaValidatorFactory;
-
-public class DefaultSchemaValidatorFactoryProducer {
-
- @Produces
- @Singleton
- @DefaultBean
- SchemaValidatorFactory schemaValidatorFactory() {
- return new JsonSchemaValidatorFactory();
- }
-
-}
diff --git a/core/runtime/src/main/java/io/quarkiverse/flow/producers/DefaultTaskExecutorFactoryProducer.java b/core/runtime/src/main/java/io/quarkiverse/flow/producers/DefaultTaskExecutorFactoryProducer.java
deleted file mode 100644
index ce91cae..0000000
--- a/core/runtime/src/main/java/io/quarkiverse/flow/producers/DefaultTaskExecutorFactoryProducer.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package io.quarkiverse.flow.producers;
-
-import jakarta.enterprise.inject.Produces;
-import jakarta.inject.Singleton;
-
-import io.quarkus.arc.DefaultBean;
-import io.serverlessworkflow.impl.executors.DefaultTaskExecutorFactory;
-import io.serverlessworkflow.impl.executors.TaskExecutorFactory;
-
-public class DefaultTaskExecutorFactoryProducer {
-
- @Produces
- @Singleton
- @DefaultBean
- TaskExecutorFactory taskExecutorFactory() {
- return DefaultTaskExecutorFactory.get();
- }
-
-}
diff --git a/core/runtime/src/main/java/io/quarkiverse/flow/producers/InMemoryEventsBean.java b/core/runtime/src/main/java/io/quarkiverse/flow/producers/InMemoryEventsBean.java
deleted file mode 100644
index 9fabd33..0000000
--- a/core/runtime/src/main/java/io/quarkiverse/flow/producers/InMemoryEventsBean.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package io.quarkiverse.flow.producers;
-
-import jakarta.enterprise.inject.Produces;
-import jakarta.inject.Singleton;
-
-import io.quarkus.arc.DefaultBean;
-import io.serverlessworkflow.impl.events.EventConsumer;
-import io.serverlessworkflow.impl.events.EventPublisher;
-import io.serverlessworkflow.impl.events.InMemoryEvents;
-
-public class InMemoryEventsBean {
-
- @Produces
- @Singleton
- @DefaultBean
- InMemoryEvents inMemoryEvents() {
- return new InMemoryEvents();
- }
-
- @SuppressWarnings("rawtypes")
- @Produces
- @Singleton
- @DefaultBean
- EventConsumer eventConsumer(InMemoryEvents delegate) {
- return delegate;
- }
-
- @Produces
- @Singleton
- @DefaultBean
- EventPublisher eventPublisher(InMemoryEvents delegate) {
- return delegate;
- }
-
-}
diff --git a/core/runtime/src/main/java/io/quarkiverse/flow/providers/QuarkusJQExpressionFactory.java b/core/runtime/src/main/java/io/quarkiverse/flow/providers/QuarkusJQExpressionFactory.java
new file mode 100644
index 0000000..09e4981
--- /dev/null
+++ b/core/runtime/src/main/java/io/quarkiverse/flow/providers/QuarkusJQExpressionFactory.java
@@ -0,0 +1,34 @@
+package io.quarkiverse.flow.providers;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+
+import io.quarkus.arc.DefaultBean;
+import io.serverlessworkflow.impl.expressions.ExpressionUtils;
+import io.serverlessworkflow.impl.expressions.ObjectExpression;
+import io.serverlessworkflow.impl.expressions.jq.JQExpression;
+import io.serverlessworkflow.impl.expressions.jq.JQExpressionFactory;
+import net.thisptr.jackson.jq.Scope;
+import net.thisptr.jackson.jq.Versions;
+import net.thisptr.jackson.jq.exception.JsonQueryException;
+
+@ApplicationScoped
+@DefaultBean
+public class QuarkusJQExpressionFactory extends JQExpressionFactory {
+
+ @Inject
+ Scope scope; // provided by quarkus-jackson-jq
+
+ public QuarkusJQExpressionFactory() {
+ }
+
+ @Override
+ public ObjectExpression buildExpression(String expression) {
+ try {
+ return new JQExpression(() -> scope, ExpressionUtils.trimExpr(expression), Versions.JQ_1_6);
+ } catch (JsonQueryException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+}
diff --git a/core/runtime/src/main/java/io/quarkiverse/flow/recorders/DiscoveredFlow.java b/core/runtime/src/main/java/io/quarkiverse/flow/recorders/DiscoveredFlow.java
index 26a94a3..64dff44 100644
--- a/core/runtime/src/main/java/io/quarkiverse/flow/recorders/DiscoveredFlow.java
+++ b/core/runtime/src/main/java/io/quarkiverse/flow/recorders/DiscoveredFlow.java
@@ -9,13 +9,15 @@ public final class DiscoveredFlow {
public final String className;
public final String methodName;
public final String workflowName;
+ public final String[] params;
public final boolean isStatic;
@RecordableConstructor
- public DiscoveredFlow(String className, String methodName, String workflowName, boolean isStatic) {
+ public DiscoveredFlow(String className, String methodName, String workflowName, String[] params, boolean isStatic) {
this.className = className;
this.methodName = methodName;
this.isStatic = isStatic;
this.workflowName = workflowName;
+ this.params = params;
}
}
diff --git a/core/runtime/src/main/java/io/quarkiverse/flow/recorders/FlowRecorder.java b/core/runtime/src/main/java/io/quarkiverse/flow/recorders/FlowRecorder.java
index 7da9a78..4fef3ac 100644
--- a/core/runtime/src/main/java/io/quarkiverse/flow/recorders/FlowRecorder.java
+++ b/core/runtime/src/main/java/io/quarkiverse/flow/recorders/FlowRecorder.java
@@ -12,11 +12,7 @@
import io.serverlessworkflow.api.types.Workflow;
import io.serverlessworkflow.impl.WorkflowApplication;
import io.serverlessworkflow.impl.WorkflowDefinition;
-import io.serverlessworkflow.impl.events.EventConsumer;
-import io.serverlessworkflow.impl.events.EventPublisher;
-import io.serverlessworkflow.impl.executors.TaskExecutorFactory;
import io.serverlessworkflow.impl.expressions.ExpressionFactory;
-import io.serverlessworkflow.impl.schema.SchemaValidatorFactory;
// TODO: produce definitions from workflows in the YAML format within the current classpath
@@ -34,12 +30,7 @@ public Supplier workflowAppSupplier(ShutdownContext shutdow
return () -> {
final ArcContainer container = Arc.container();
final WorkflowApplication.Builder builder = WorkflowApplication.builder();
- builder.withEventConsumer(container.instance(EventConsumer.class).get())
- .withExpressionFactory(container.instance(ExpressionFactory.class).get())
- .withSchemaValidatorFactory(container.instance(SchemaValidatorFactory.class).get())
- .withTaskExecutorFactory(container.instance(TaskExecutorFactory.class).get());
- for (var p : container.select(EventPublisher.class))
- builder.withEventPublisher(p);
+ builder.withExpressionFactory(container.instance(ExpressionFactory.class).get());
final WorkflowApplication app = builder.build();
shutdownContext.addShutdownTask(app::close);
@@ -57,7 +48,7 @@ public Supplier workflowDefinitionSupplier(DiscoveredFlow d)
final Object target = d.isStatic ? null : Arc.container().instance(owner).get();
- final MethodHandles.Lookup lookup = MethodHandles.lookup();
+ final MethodHandles.Lookup lookup = MethodHandles.publicLookup();
final MethodType mt = MethodType.methodType(Workflow.class);
final MethodHandle mh = d.isStatic ? lookup.findStatic(owner, d.methodName, mt)
: lookup.findVirtual(owner, d.methodName, mt);
diff --git a/pom.xml b/pom.xml
index d8b5892..7bc9e4f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,7 +31,7 @@
UTF-8
3.28.1
7.2.0.Final
- 2.4.0
+ 2.4.0
@@ -63,6 +63,16 @@
serverlessworkflow-impl-jackson
${io.serverlessworkflow.version}
+
+ io.quarkiverse.jackson-jq
+ quarkus-jackson-jq
+ ${io.quarkiverse.jackson-jq.version}
+
+
+ io.quarkiverse.jackson-jq
+ quarkus-jackson-jq-deployment
+ ${io.quarkiverse.jackson-jq.version}
+