From 78173441133fb3365a72bcb5551170f93139212c Mon Sep 17 00:00:00 2001 From: fjtirado Date: Mon, 28 Jul 2025 14:21:02 +0200 Subject: [PATCH] Refactoring java executor to avoid instanceof at runtime Signed-off-by: fjtirado --- .../impl/executors/func/JavaCallExecutor.java | 67 ------------------- .../func/JavaConsumerCallExecutor.java | 53 +++++++++++++++ .../func/JavaForExecutorBuilder.java | 2 +- .../impl/executors/func/JavaFuncUtils.java | 27 ++++++++ .../func/JavaFunctionCallExecutor.java | 55 +++++++++++++++ .../func/JavaLoopFunctionCallExecutor.java | 62 +++++++++++++++++ .../JavaLoopFunctionIndexCallExecutor.java | 67 +++++++++++++++++++ ...erlessworkflow.impl.executors.CallableTask | 5 +- 8 files changed, 269 insertions(+), 69 deletions(-) delete mode 100644 experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaCallExecutor.java create mode 100644 experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaConsumerCallExecutor.java create mode 100644 experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFuncUtils.java create mode 100644 experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFunctionCallExecutor.java create mode 100644 experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaLoopFunctionCallExecutor.java create mode 100644 experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaLoopFunctionIndexCallExecutor.java diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaCallExecutor.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaCallExecutor.java deleted file mode 100644 index 10f10008..00000000 --- a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaCallExecutor.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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.func; - -import io.serverlessworkflow.api.types.TaskBase; -import io.serverlessworkflow.api.types.func.CallJava; -import io.serverlessworkflow.impl.TaskContext; -import io.serverlessworkflow.impl.WorkflowContext; -import io.serverlessworkflow.impl.WorkflowModel; -import io.serverlessworkflow.impl.WorkflowModelFactory; -import io.serverlessworkflow.impl.executors.CallableTask; -import java.util.concurrent.CompletableFuture; - -public class JavaCallExecutor implements CallableTask { - - @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 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/func/JavaConsumerCallExecutor.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaConsumerCallExecutor.java new file mode 100644 index 00000000..4c1abce7 --- /dev/null +++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaConsumerCallExecutor.java @@ -0,0 +1,53 @@ +/* + * 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.func; + +import io.serverlessworkflow.api.types.TaskBase; +import io.serverlessworkflow.api.types.Workflow; +import io.serverlessworkflow.api.types.func.CallJava; +import io.serverlessworkflow.impl.TaskContext; +import io.serverlessworkflow.impl.WorkflowApplication; +import io.serverlessworkflow.impl.WorkflowContext; +import io.serverlessworkflow.impl.WorkflowModel; +import io.serverlessworkflow.impl.executors.CallableTask; +import io.serverlessworkflow.impl.resources.ResourceLoader; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; + +public class JavaConsumerCallExecutor implements CallableTask { + + private Consumer consumer; + + public void init( + CallJava.CallJavaConsumer task, + Workflow workflow, + WorkflowApplication application, + ResourceLoader loader) { + consumer = task.consumer(); + } + + @Override + public CompletableFuture apply( + WorkflowContext workflowContext, TaskContext taskContext, WorkflowModel input) { + consumer.accept(input.asJavaObject()); + return CompletableFuture.completedFuture(input); + } + + @Override + public boolean accept(Class clazz) { + return CallJava.CallJavaConsumer.class.isAssignableFrom(clazz); + } +} diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaForExecutorBuilder.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaForExecutorBuilder.java index 0d80fa6d..f58ce510 100644 --- a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaForExecutorBuilder.java +++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaForExecutorBuilder.java @@ -16,7 +16,7 @@ package io.serverlessworkflow.impl.executors.func; -import static io.serverlessworkflow.impl.executors.func.JavaCallExecutor.safeObject; +import static io.serverlessworkflow.impl.executors.func.JavaFuncUtils.safeObject; import io.serverlessworkflow.api.types.ForTask; import io.serverlessworkflow.api.types.Workflow; diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFuncUtils.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFuncUtils.java new file mode 100644 index 00000000..33b90fb9 --- /dev/null +++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFuncUtils.java @@ -0,0 +1,27 @@ +/* + * 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.func; + +import io.serverlessworkflow.impl.WorkflowModel; + +public class JavaFuncUtils { + + static Object safeObject(Object obj) { + return obj instanceof WorkflowModel model ? model.asJavaObject() : obj; + } + + private JavaFuncUtils() {} +} diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFunctionCallExecutor.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFunctionCallExecutor.java new file mode 100644 index 00000000..8a9f219a --- /dev/null +++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaFunctionCallExecutor.java @@ -0,0 +1,55 @@ +/* + * 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.func; + +import io.serverlessworkflow.api.types.TaskBase; +import io.serverlessworkflow.api.types.Workflow; +import io.serverlessworkflow.api.types.func.CallJava; +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.executors.CallableTask; +import io.serverlessworkflow.impl.resources.ResourceLoader; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; + +public class JavaFunctionCallExecutor implements CallableTask { + + private Function function; + + public void init( + CallJava.CallJavaFunction task, + Workflow workflow, + WorkflowApplication application, + ResourceLoader loader) { + function = task.function(); + } + + @Override + public CompletableFuture apply( + WorkflowContext workflowContext, TaskContext taskContext, WorkflowModel input) { + WorkflowModelFactory modelFactory = workflowContext.definition().application().modelFactory(); + return CompletableFuture.completedFuture( + modelFactory.fromAny(function.apply(input.asJavaObject()))); + } + + @Override + public boolean accept(Class clazz) { + return CallJava.CallJavaFunction.class.isAssignableFrom(clazz); + } +} diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaLoopFunctionCallExecutor.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaLoopFunctionCallExecutor.java new file mode 100644 index 00000000..31c2100f --- /dev/null +++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaLoopFunctionCallExecutor.java @@ -0,0 +1,62 @@ +/* + * 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.func; + +import static io.serverlessworkflow.impl.executors.func.JavaFuncUtils.safeObject; + +import io.serverlessworkflow.api.types.TaskBase; +import io.serverlessworkflow.api.types.Workflow; +import io.serverlessworkflow.api.types.func.CallJava; +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.executors.CallableTask; +import io.serverlessworkflow.impl.expressions.LoopFunction; +import io.serverlessworkflow.impl.resources.ResourceLoader; +import java.util.concurrent.CompletableFuture; + +public class JavaLoopFunctionCallExecutor implements CallableTask { + + private LoopFunction function; + private String varName; + + public void init( + CallJava.CallJavaLoopFunction task, + Workflow workflow, + WorkflowApplication application, + ResourceLoader loader) { + function = task.function(); + varName = task.varName(); + } + + @Override + public CompletableFuture apply( + WorkflowContext workflowContext, TaskContext taskContext, WorkflowModel input) { + WorkflowModelFactory modelFactory = workflowContext.definition().application().modelFactory(); + return CompletableFuture.completedFuture( + modelFactory.fromAny( + function.apply( + input.asJavaObject(), safeObject(taskContext.variables().get(varName))))); + } + + @Override + public boolean accept(Class clazz) { + + return CallJava.CallJavaLoopFunction.class.isAssignableFrom(clazz); + } +} diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaLoopFunctionIndexCallExecutor.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaLoopFunctionIndexCallExecutor.java new file mode 100644 index 00000000..e566c0a0 --- /dev/null +++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaLoopFunctionIndexCallExecutor.java @@ -0,0 +1,67 @@ +/* + * 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.func; + +import static io.serverlessworkflow.impl.executors.func.JavaFuncUtils.safeObject; + +import io.serverlessworkflow.api.types.TaskBase; +import io.serverlessworkflow.api.types.Workflow; +import io.serverlessworkflow.api.types.func.CallJava; +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.executors.CallableTask; +import io.serverlessworkflow.impl.expressions.LoopFunctionIndex; +import io.serverlessworkflow.impl.resources.ResourceLoader; +import java.util.concurrent.CompletableFuture; + +public class JavaLoopFunctionIndexCallExecutor + implements CallableTask { + + private LoopFunctionIndex function; + private String varName; + private String indexName; + + public void init( + CallJava.CallJavaLoopFunctionIndex task, + Workflow workflow, + WorkflowApplication application, + ResourceLoader loader) { + function = task.function(); + varName = task.varName(); + indexName = task.indexName(); + } + + @Override + public CompletableFuture apply( + WorkflowContext workflowContext, TaskContext taskContext, WorkflowModel input) { + WorkflowModelFactory modelFactory = workflowContext.definition().application().modelFactory(); + + return CompletableFuture.completedFuture( + modelFactory.fromAny( + function.apply( + input.asJavaObject(), + safeObject(taskContext.variables().get(varName)), + (Integer) safeObject(taskContext.variables().get(indexName))))); + } + + @Override + public boolean accept(Class clazz) { + return CallJava.CallJavaLoopFunctionIndex.class.isAssignableFrom(clazz); + } +} diff --git a/experimental/lambda/src/main/resources/META-INF/services/io.serverlessworkflow.impl.executors.CallableTask b/experimental/lambda/src/main/resources/META-INF/services/io.serverlessworkflow.impl.executors.CallableTask index 780aa17e..1b69b5d3 100644 --- a/experimental/lambda/src/main/resources/META-INF/services/io.serverlessworkflow.impl.executors.CallableTask +++ b/experimental/lambda/src/main/resources/META-INF/services/io.serverlessworkflow.impl.executors.CallableTask @@ -1 +1,4 @@ -io.serverlessworkflow.impl.executors.func.JavaCallExecutor \ No newline at end of file +io.serverlessworkflow.impl.executors.func.JavaLoopFunctionIndexCallExecutor +io.serverlessworkflow.impl.executors.func.JavaLoopFunctionCallExecutor +io.serverlessworkflow.impl.executors.func.JavaFunctionCallExecutor +io.serverlessworkflow.impl.executors.func.JavaConsumerCallExecutor \ No newline at end of file