Skip to content

Commit 87d767a

Browse files
committed
[Fix #1625] Add null check for required 'in' property in ForExecutorBuilder
ForExecutorBuilder.buildCollectionFilter() dereferences task.getFor().getIn() without a null check. Programmatically-built workflows bypass schema validation, so a ForTask without 'in' set causes a raw NullPointerException with no context. Added Objects.requireNonNull with a descriptive message and a test that verifies the error when 'in' is missing. Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>
1 parent 90ead3c commit 87d767a

2 files changed

Lines changed: 47 additions & 1 deletion

File tree

impl/core/src/main/java/io/serverlessworkflow/impl/executors/ForExecutor.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import io.serverlessworkflow.impl.expressions.ExpressionDescriptor;
2929
import java.util.Collection;
3030
import java.util.Iterator;
31+
import java.util.Objects;
3132
import java.util.Optional;
3233
import java.util.concurrent.CompletableFuture;
3334

@@ -51,7 +52,8 @@ protected Optional<WorkflowPredicate> buildWhileFilter() {
5152
}
5253

5354
protected WorkflowValueResolver<Collection<?>> buildCollectionFilter() {
54-
In in = task.getFor().getIn();
55+
In in =
56+
Objects.requireNonNull(task.getFor().getIn(), "'in' is a required property for ForTask");
5557
return application
5658
.expressionFactory()
5759
.resolveCollection(
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.impl.test;
17+
18+
import static io.serverlessworkflow.fluent.spec.dsl.DSL.*;
19+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
20+
21+
import io.serverlessworkflow.api.types.Workflow;
22+
import io.serverlessworkflow.fluent.spec.WorkflowBuilder;
23+
import io.serverlessworkflow.impl.WorkflowApplication;
24+
import org.junit.jupiter.api.Test;
25+
26+
class ForTaskMissingInTest {
27+
28+
@Test
29+
void forTaskWithoutInShouldFailWithDescriptiveMessage() {
30+
Workflow workflow =
31+
WorkflowBuilder.workflow("for-missing-in", "test", "0.1.0")
32+
.tasks(
33+
doTasks(
34+
forEach(
35+
"loopWithoutIn",
36+
f -> f.each("item").tasks(t -> t.set("noop", s -> s.put("done", true))))))
37+
.build();
38+
try (WorkflowApplication app = WorkflowApplication.builder().build()) {
39+
assertThatThrownBy(() -> app.workflowDefinition(workflow))
40+
.isInstanceOf(NullPointerException.class)
41+
.hasMessageContaining("'in' is a required property for ForTask");
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)