diff --git a/experimental/lambda/pom.xml b/experimental/lambda/pom.xml
new file mode 100644
index 00000000..72e4c0b2
--- /dev/null
+++ b/experimental/lambda/pom.xml
@@ -0,0 +1,45 @@
+
+ 4.0.0
+
+ io.serverlessworkflow
+ serverlessworkflow-experimental
+ 8.0.0-SNAPSHOT
+
+ serverlessworkflow-experimental-lambda
+ ServelessWorkflow:: Experimental:: lambda
+
+
+ io.serverlessworkflow
+ serverlessworkflow-experimental-types
+
+
+ io.serverlessworkflow
+ serverlessworkflow-impl-core
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ test
+
+
+ org.assertj
+ assertj-core
+ test
+
+
+ ch.qos.logback
+ logback-classic
+ test
+
+
+
\ No newline at end of file
diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/JavaCallExecutor.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/JavaCallExecutor.java
new file mode 100644
index 00000000..8d166986
--- /dev/null
+++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/JavaCallExecutor.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.executors;
+
+import io.serverlessworkflow.api.types.CallJava;
+import io.serverlessworkflow.api.types.TaskBase;
+import io.serverlessworkflow.impl.TaskContext;
+import io.serverlessworkflow.impl.WorkflowApplication;
+import io.serverlessworkflow.impl.WorkflowContext;
+import io.serverlessworkflow.impl.WorkflowModel;
+import io.serverlessworkflow.impl.WorkflowModelFactory;
+import io.serverlessworkflow.impl.resources.ResourceLoader;
+import java.util.concurrent.CompletableFuture;
+
+public class JavaCallExecutor implements CallableTask {
+
+ @Override
+ public void init(CallJava task, WorkflowApplication application, ResourceLoader loader) {}
+
+ @Override
+ public CompletableFuture apply(
+ WorkflowContext workflowContext, TaskContext taskContext, WorkflowModel input) {
+ WorkflowModelFactory modelFactory = workflowContext.definition().application().modelFactory();
+ if (taskContext.task() instanceof CallJava.CallJavaFunction function) {
+ return CompletableFuture.completedFuture(
+ modelFactory.fromAny(function.function().apply(input.asJavaObject())));
+ } else if (taskContext.task() instanceof CallJava.CallJavaLoopFunction function) {
+ return CompletableFuture.completedFuture(
+ modelFactory.fromAny(
+ function
+ .function()
+ .apply(
+ input.asJavaObject(),
+ safeObject(taskContext.variables().get(function.varName())))));
+ } else if (taskContext.task() instanceof CallJava.CallJavaLoopFunctionIndex function) {
+ return CompletableFuture.completedFuture(
+ modelFactory.fromAny(
+ function
+ .function()
+ .apply(
+ input.asJavaObject(),
+ safeObject(taskContext.variables().get(function.varName())),
+ (Integer) safeObject(taskContext.variables().get(function.indexName())))));
+ } else if (taskContext.task() instanceof CallJava.CallJavaConsumer consumer) {
+ consumer.consumer().accept(input.asJavaObject());
+ }
+ return CompletableFuture.completedFuture(input);
+ }
+
+ @Override
+ public boolean accept(Class extends TaskBase> clazz) {
+ return CallJava.class.isAssignableFrom(clazz);
+ }
+
+ static Object safeObject(Object obj) {
+ return obj instanceof WorkflowModel model ? model.asJavaObject() : obj;
+ }
+}
diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/JavaForExecutorBuilder.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/JavaForExecutorBuilder.java
new file mode 100644
index 00000000..faa1942c
--- /dev/null
+++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/JavaForExecutorBuilder.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.serverlessworkflow.impl.executors;
+
+import static io.serverlessworkflow.impl.executors.JavaCallExecutor.safeObject;
+
+import io.serverlessworkflow.api.types.ForTask;
+import io.serverlessworkflow.api.types.ForTaskFunction;
+import io.serverlessworkflow.api.types.Workflow;
+import io.serverlessworkflow.impl.WorkflowApplication;
+import io.serverlessworkflow.impl.WorkflowFilter;
+import io.serverlessworkflow.impl.WorkflowPosition;
+import io.serverlessworkflow.impl.WorkflowUtils;
+import io.serverlessworkflow.impl.executors.ForExecutor.ForExecutorBuilder;
+import io.serverlessworkflow.impl.expressions.LoopPredicateIndex;
+import io.serverlessworkflow.impl.resources.ResourceLoader;
+import java.util.Optional;
+
+public class JavaForExecutorBuilder extends ForExecutorBuilder {
+
+ protected JavaForExecutorBuilder(
+ WorkflowPosition position,
+ ForTask task,
+ Workflow workflow,
+ WorkflowApplication application,
+ ResourceLoader resourceLoader) {
+ super(position, task, workflow, application, resourceLoader);
+ if (task instanceof ForTaskFunction taskFunctions) {}
+ }
+
+ protected Optional buildWhileFilter() {
+ if (task instanceof ForTaskFunction taskFunctions) {
+ LoopPredicateIndex whilePred = taskFunctions.getWhilePredicate();
+ String varName = task.getFor().getEach();
+ String indexName = task.getFor().getAt();
+ if (whilePred != null) {
+ return Optional.of(
+ (w, t, n) -> {
+ Object item = safeObject(t.variables().get(varName));
+ return application
+ .modelFactory()
+ .from(
+ item == null
+ || whilePred.test(
+ n.asJavaObject(),
+ item,
+ (Integer) safeObject(t.variables().get(indexName))));
+ });
+ }
+ }
+ return super.buildWhileFilter();
+ }
+
+ protected WorkflowFilter buildCollectionFilter() {
+ return task instanceof ForTaskFunction taskFunctions
+ ? WorkflowUtils.buildWorkflowFilter(application, null, taskFunctions.getCollection())
+ : super.buildCollectionFilter();
+ }
+}
diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/JavaSwitchExecutorBuilder.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/JavaSwitchExecutorBuilder.java
new file mode 100644
index 00000000..3b42825d
--- /dev/null
+++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/JavaSwitchExecutorBuilder.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.serverlessworkflow.impl.executors;
+
+import io.serverlessworkflow.api.types.SwitchCase;
+import io.serverlessworkflow.api.types.SwitchCaseFunction;
+import io.serverlessworkflow.api.types.SwitchTask;
+import io.serverlessworkflow.api.types.Workflow;
+import io.serverlessworkflow.impl.WorkflowApplication;
+import io.serverlessworkflow.impl.WorkflowFilter;
+import io.serverlessworkflow.impl.WorkflowPosition;
+import io.serverlessworkflow.impl.WorkflowUtils;
+import io.serverlessworkflow.impl.executors.SwitchExecutor.SwitchExecutorBuilder;
+import io.serverlessworkflow.impl.resources.ResourceLoader;
+import java.util.Optional;
+
+public class JavaSwitchExecutorBuilder extends SwitchExecutorBuilder {
+
+ protected JavaSwitchExecutorBuilder(
+ WorkflowPosition position,
+ SwitchTask task,
+ Workflow workflow,
+ WorkflowApplication application,
+ ResourceLoader resourceLoader) {
+ super(position, task, workflow, application, resourceLoader);
+ }
+
+ @Override
+ protected Optional buildFilter(SwitchCase switchCase) {
+ return switchCase instanceof SwitchCaseFunction function
+ ? Optional.of(WorkflowUtils.buildWorkflowFilter(application, null, function.predicate()))
+ : super.buildFilter(switchCase);
+ }
+}
diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/JavaTaskExecutorFactory.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/JavaTaskExecutorFactory.java
new file mode 100644
index 00000000..26177287
--- /dev/null
+++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/JavaTaskExecutorFactory.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.executors;
+
+import io.serverlessworkflow.api.types.Task;
+import io.serverlessworkflow.api.types.TaskBase;
+import io.serverlessworkflow.api.types.Workflow;
+import io.serverlessworkflow.impl.WorkflowApplication;
+import io.serverlessworkflow.impl.WorkflowPosition;
+import io.serverlessworkflow.impl.resources.ResourceLoader;
+
+public class JavaTaskExecutorFactory extends DefaultTaskExecutorFactory {
+
+ public TaskExecutorBuilder extends TaskBase> getTaskExecutor(
+ WorkflowPosition position,
+ Task task,
+ Workflow workflow,
+ WorkflowApplication application,
+ ResourceLoader resourceLoader) {
+ if (task.getForTask() != null) {
+ return new JavaForExecutorBuilder(
+ position, task.getForTask(), workflow, application, resourceLoader);
+ } else if (task.getSwitchTask() != null) {
+ return new JavaSwitchExecutorBuilder(
+ position, task.getSwitchTask(), workflow, application, resourceLoader);
+ } else {
+ return super.getTaskExecutor(position, task, workflow, application, resourceLoader);
+ }
+ }
+}
diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/JavaExpressionFactory.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/JavaExpressionFactory.java
new file mode 100644
index 00000000..a6e89ae8
--- /dev/null
+++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/JavaExpressionFactory.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.expressions;
+
+import io.serverlessworkflow.impl.TaskContext;
+import io.serverlessworkflow.impl.WorkflowContext;
+import io.serverlessworkflow.impl.WorkflowFilter;
+import io.serverlessworkflow.impl.WorkflowModel;
+import io.serverlessworkflow.impl.WorkflowModelFactory;
+import java.util.function.BiFunction;
+import java.util.function.BiPredicate;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+public class JavaExpressionFactory implements ExpressionFactory {
+
+ private final WorkflowModelFactory modelFactory = new JavaModelFactory();
+ private final Expression dummyExpression =
+ new Expression() {
+ @Override
+ public WorkflowModel eval(
+ WorkflowContext workflowContext, TaskContext context, WorkflowModel model) {
+ return model;
+ }
+ };
+
+ @Override
+ public Expression buildExpression(String expression) {
+ return dummyExpression;
+ }
+
+ @Override
+ public WorkflowFilter buildFilter(String expr, Object value) {
+ if (value instanceof Function func) {
+ return (w, t, n) -> modelFactory.fromAny(func.apply(n.asJavaObject()));
+ } else if (value instanceof Predicate pred) {
+ return (w, t, n) -> modelFactory.from(pred.test(n.asJavaObject()));
+ } else if (value instanceof BiPredicate pred) {
+ return (w, t, n) -> modelFactory.from(pred.test(w, t));
+ } else if (value instanceof BiFunction func) {
+ return (w, t, n) -> modelFactory.fromAny(func.apply(w, t));
+ } else if (value instanceof WorkflowFilter filter) {
+ return filter;
+ } else {
+ return (w, t, n) -> modelFactory.fromAny(value);
+ }
+ }
+
+ @Override
+ public WorkflowModelFactory modelFactory() {
+ return modelFactory;
+ }
+}
diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/JavaModel.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/JavaModel.java
new file mode 100644
index 00000000..0e4b4df1
--- /dev/null
+++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/JavaModel.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.expressions;
+
+import io.cloudevents.CloudEventData;
+import io.serverlessworkflow.impl.WorkflowModel;
+import java.time.OffsetDateTime;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.BiConsumer;
+
+public class JavaModel implements WorkflowModel {
+
+ private Object object;
+
+ static final JavaModel TrueModel = new JavaModel(Boolean.TRUE);
+ static final JavaModel FalseModel = new JavaModel(Boolean.FALSE);
+ static final JavaModel NullModel = new JavaModel(null);
+
+ JavaModel(Object object) {
+ this.object = object;
+ }
+
+ @Override
+ public void forEach(BiConsumer consumer) {
+ asMap()
+ .ifPresent(
+ m ->
+ m.forEach(
+ (k, v) ->
+ consumer.accept(
+ k, v instanceof WorkflowModel model ? model : new JavaModel(v))));
+ }
+
+ @Override
+ public Optional asBoolean() {
+ return object instanceof Boolean value ? Optional.of(value) : Optional.empty();
+ }
+
+ @Override
+ public Collection asCollection() {
+ return object instanceof Collection value
+ ? new JavaModelCollection(value)
+ : Collections.emptyList();
+ }
+
+ @Override
+ public Optional asText() {
+ return object instanceof String value ? Optional.of(value) : Optional.empty();
+ }
+
+ @Override
+ public Optional asDate() {
+ return object instanceof OffsetDateTime value ? Optional.of(value) : Optional.empty();
+ }
+
+ @Override
+ public Optional asNumber() {
+ return object instanceof Number value ? Optional.of(value) : Optional.empty();
+ }
+
+ @Override
+ public Optional asCloudEventData() {
+ return object instanceof CloudEventData value ? Optional.of(value) : Optional.empty();
+ }
+
+ @Override
+ public Optional