Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions core/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@
<artifactId>quarkus-flow</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Required by Native compilation for serverlessworkflow-core-http module -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client-jackson-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkiverse.jackson-jq</groupId>
<artifactId>quarkus-jackson-jq-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-fluent-spec</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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 <a href="https://github.com/serverlessworkflow/sdk-java/issues/812">Native-image build fails due to UlidCreator static
* initialization (Random in image heap)</a>
*/
final class FlowNativeProcessor {
@BuildStep
RuntimeInitializedClassBuildItem ulidCreatorHolder() {
return new RuntimeInitializedClassBuildItem("com.github.f4b6a3.ulid.UlidCreator$MonotonicFactoryHolder");
}

/**
* see <a href="https://github.com/serverlessworkflow/sdk-java/issues/812">Native-image build fails due to UlidCreator
* static
* initialization (Random in image heap)</a>
*/
@BuildStep
RuntimeInitializedClassBuildItem ulidCreator() {
return new RuntimeInitializedClassBuildItem("com.github.f4b6a3.ulid.UlidCreator");
void runtimeInitUlid(BuildProducer<RuntimeInitializedClassBuildItem> 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<ServiceProviderBuildItem> 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()));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -69,24 +66,18 @@ void collectFlowDescriptors(CombinedIndexBuildItem index, BuildProducer<Discover
void keepAndReflectFlowDescriptors(
List<DiscoveredFlowBuildItem> discovered,
BuildProducer<UnremovableBeanBuildItem> keep,
BuildProducer<ReflectiveClassBuildItem> reflective) {
BuildProducer<ReflectiveMethodBuildItem> reflective) {

var owners = discovered.stream()
List<String> owners = discovered.stream()
.map(d -> d.workflow.className)
.distinct()
.toList();

// 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));
}
}

Expand All @@ -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();
}
Expand Down
16 changes: 0 additions & 16 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,4 @@
<module>runtime</module>
<module>deployment</module>
</modules>

<dependencies>
<dependency>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-impl-core</artifactId>
</dependency>
<dependency>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-impl-http</artifactId>
</dependency>
<dependency>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-impl-jackson</artifactId>
</dependency>
</dependencies>

</project>
29 changes: 27 additions & 2 deletions core/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,40 @@
<name>Quarkus Flow :: Core :: Runtime</name>

<dependencies>
<!-- CNCF Java SDK -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-impl-core</artifactId>
</dependency>
<dependency>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-impl-http</artifactId>
</dependency>
<dependency>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-impl-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-fluent-spec</artifactId>
<version>${io.serverlessworkflow.version}</version>
</dependency>

<!-- Quarkus -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkiverse.jackson-jq</groupId>
<artifactId>quarkus-jackson-jq</artifactId>
</dependency>
<!-- Required by serverlessworkflow-core-http HttpExecutor service module -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client-jackson</artifactId>
</dependency>

</dependencies>

<build>
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Loading
Loading