From 5425d808a0f40a0739f26dd0904fd462bbea28c0 Mon Sep 17 00:00:00 2001 From: Matheus Andre Date: Sat, 4 Apr 2026 22:18:25 -0300 Subject: [PATCH] fix: Exception on loop after agent call Signed-off-by: Matheus Andre Signed-off-by: Matheus Andre --- .../func/JavaForExecutorBuilder.java | 2 +- .../func/ForTaskFunctionRegressionTest.java | 60 +++++++++++++++++++ .../api/types/func/ForTaskFunction.java | 6 +- 3 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 experimental/lambda/src/test/java/io/serverless/workflow/impl/executors/func/ForTaskFunctionRegressionTest.java 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 0d07bbdb..e28a4d77 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 @@ -69,7 +69,7 @@ protected WorkflowValueResolver> buildCollectionFilter() { } private Object collectionFilterObject(ForTaskFunction taskFunctions) { - return taskFunctions.getForClass().isPresent() + return taskFunctions.getForClass() != null && taskFunctions.getForClass().isPresent() ? new TypedFunction( taskFunctions.getCollection(), taskFunctions.getForClass().orElseThrow()) : taskFunctions.getCollection(); diff --git a/experimental/lambda/src/test/java/io/serverless/workflow/impl/executors/func/ForTaskFunctionRegressionTest.java b/experimental/lambda/src/test/java/io/serverless/workflow/impl/executors/func/ForTaskFunctionRegressionTest.java new file mode 100644 index 00000000..4c52be94 --- /dev/null +++ b/experimental/lambda/src/test/java/io/serverless/workflow/impl/executors/func/ForTaskFunctionRegressionTest.java @@ -0,0 +1,60 @@ +/* + * 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.serverless.workflow.impl.executors.func; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.serverlessworkflow.api.types.Workflow; +import io.serverlessworkflow.api.types.func.ForTaskFunction; +import io.serverlessworkflow.fluent.func.FuncWorkflowBuilder; +import io.serverlessworkflow.impl.WorkflowApplication; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.ExecutionException; +import org.junit.jupiter.api.Test; + +class ForTaskFunctionRegressionTest { + + @Test + void initializesOptionalFieldsAsEmpty() { + ForTaskFunction taskFunction = new ForTaskFunction(); + + assertThat(taskFunction.getWhileClass()).isNotNull().isEmpty(); + assertThat(taskFunction.getItemClass()).isNotNull().isEmpty(); + assertThat(taskFunction.getForClass()).isNotNull().isEmpty(); + } + + @Test + void forLoopWithoutExplicitCollectionClassExecutesSuccessfully() + throws InterruptedException, ExecutionException { + try (WorkflowApplication app = WorkflowApplication.builder().build()) { + Workflow workflow = + FuncWorkflowBuilder.workflow("loop-without-collection-class") + .tasks( + tasks -> + tasks.forEach( + f -> + f.whileC(CallTest::isEven) + .collection(v -> (Collection) v) + .tasks(CallTest::sum))) + .build(); + + var result = app.workflowDefinition(workflow).instance(List.of(2, 4, 6)).start().get(); + + assertThat(result.asNumber().orElseThrow()).isEqualTo(12); + } + } +} diff --git a/experimental/types/src/main/java/io/serverlessworkflow/api/types/func/ForTaskFunction.java b/experimental/types/src/main/java/io/serverlessworkflow/api/types/func/ForTaskFunction.java index 9b88fd01..56572f03 100644 --- a/experimental/types/src/main/java/io/serverlessworkflow/api/types/func/ForTaskFunction.java +++ b/experimental/types/src/main/java/io/serverlessworkflow/api/types/func/ForTaskFunction.java @@ -24,9 +24,9 @@ public class ForTaskFunction extends ForTask { private static final long serialVersionUID = 1L; private LoopPredicateIndexFilter whilePredicate; - private Optional> whileClass; - private Optional> itemClass; - private Optional> forClass; + private Optional> whileClass = Optional.empty(); + private Optional> itemClass = Optional.empty(); + private Optional> forClass = Optional.empty(); private Function> collection; public ForTaskFunction withWhile(LoopPredicate whilePredicate) {