From 2628645fc423b34d65a66177ac4181ffb4e6f46d Mon Sep 17 00:00:00 2001 From: fjtirado Date: Thu, 30 Oct 2025 12:33:36 +0100 Subject: [PATCH 1/2] [Fix #925] Allow association of additional objects to application Signed-off-by: fjtirado --- .../impl/ConstantAdditionalObject.java | 30 ++++++++++++++ .../impl/WorkflowAdditionalObject.java | 20 ++++++++++ .../impl/WorkflowApplication.java | 22 ++++++++++ .../executors/http/HttpClientResolver.java | 40 +++++++++++++++++++ .../impl/executors/http/HttpExecutor.java | 8 ++-- 5 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 impl/core/src/main/java/io/serverlessworkflow/impl/ConstantAdditionalObject.java create mode 100644 impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowAdditionalObject.java create mode 100644 impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/HttpClientResolver.java diff --git a/impl/core/src/main/java/io/serverlessworkflow/impl/ConstantAdditionalObject.java b/impl/core/src/main/java/io/serverlessworkflow/impl/ConstantAdditionalObject.java new file mode 100644 index 00000000..0d4100e9 --- /dev/null +++ b/impl/core/src/main/java/io/serverlessworkflow/impl/ConstantAdditionalObject.java @@ -0,0 +1,30 @@ +/* + * 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; + +public class ConstantAdditionalObject implements WorkflowAdditionalObject { + + private final T object; + + public ConstantAdditionalObject(T object) { + this.object = object; + } + + @Override + public T apply(WorkflowContext t, TaskContext u) { + return object; + } +} diff --git a/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowAdditionalObject.java b/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowAdditionalObject.java new file mode 100644 index 00000000..79d8a4cd --- /dev/null +++ b/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowAdditionalObject.java @@ -0,0 +1,20 @@ +/* + * 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; + +import java.util.function.BiFunction; + +public interface WorkflowAdditionalObject extends BiFunction {} diff --git a/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowApplication.java b/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowApplication.java index 58276eeb..bd515479 100644 --- a/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowApplication.java +++ b/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowApplication.java @@ -38,6 +38,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.Map; +import java.util.Optional; import java.util.ServiceLoader; import java.util.ServiceLoader.Provider; import java.util.concurrent.ConcurrentHashMap; @@ -61,6 +62,7 @@ public class WorkflowApplication implements AutoCloseable { private final boolean lifeCycleCEPublishingEnabled; private final WorkflowModelFactory modelFactory; private final WorkflowScheduler scheduler; + private final Map> additionalObjects; private WorkflowApplication(Builder builder) { this.taskFactory = builder.taskFactory; @@ -78,6 +80,7 @@ private WorkflowApplication(Builder builder) { this.lifeCycleCEPublishingEnabled = builder.lifeCycleCEPublishingEnabled; this.modelFactory = builder.modelFactory; this.scheduler = builder.scheduler; + this.additionalObjects = builder.additionalObjects; } public TaskExecutorFactory taskFactory() { @@ -153,6 +156,7 @@ public SchemaValidator getValidator(SchemaInline inline) { () -> new RuntimeDescriptor("reference impl", "1.0.0_alpha", Collections.emptyMap()); private boolean lifeCycleCEPublishingEnabled = true; private WorkflowModelFactory modelFactory; + private Map> additionalObjects; private Builder() {} @@ -221,6 +225,14 @@ public Builder withEventPublisher(EventPublisher eventPublisher) { return this; } + public Builder withExtensionObject(String name, WorkflowAdditionalObject additionalObject) { + if (additionalObjects == null) { + additionalObjects = new ConcurrentHashMap<>(); + } + additionalObjects.put(name, additionalObject); + return this; + } + public Builder withModelFactory(WorkflowModelFactory modelFactory) { this.modelFactory = modelFactory; return this; @@ -269,6 +281,10 @@ public WorkflowApplication build() { if (scheduler == null) { scheduler = new DefaultWorkflowScheduler(); } + if (additionalObjects == null) { + additionalObjects = Collections.emptyMap(); + } + return new WorkflowApplication(this); } } @@ -329,4 +345,10 @@ public boolean isLifeCycleCEPublishingEnabled() { public WorkflowScheduler scheduler() { return scheduler; } + + public Optional additionalObject( + String name, WorkflowContext workflowContext, TaskContext taskContext) { + return Optional.ofNullable(additionalObjects.get(name)) + .map(v -> (T) v.apply(workflowContext, taskContext)); + } } diff --git a/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/HttpClientResolver.java b/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/HttpClientResolver.java new file mode 100644 index 00000000..00c165cf --- /dev/null +++ b/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/HttpClientResolver.java @@ -0,0 +1,40 @@ +/* + * 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.http; + +import io.serverlessworkflow.impl.TaskContext; +import io.serverlessworkflow.impl.WorkflowContext; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; + +public class HttpClientResolver { + + public static final String HTTP_CLIENT_PROVIDER = "httpClientProvider"; + + private static class DefaultHolder { + private static final Client client = ClientBuilder.newClient(); + } + + public static Client client(WorkflowContext workflowContext, TaskContext taskContext) { + return workflowContext + .definition() + .application() + .additionalObject(HTTP_CLIENT_PROVIDER, workflowContext, taskContext) + .orElseGet(() -> DefaultHolder.client); + } + + private HttpClientResolver() {} +} diff --git a/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/HttpExecutor.java b/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/HttpExecutor.java index f912cb58..6498dbad 100644 --- a/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/HttpExecutor.java +++ b/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/HttpExecutor.java @@ -34,8 +34,6 @@ import io.serverlessworkflow.impl.expressions.ExpressionDescriptor; import jakarta.ws.rs.HttpMethod; import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.client.Client; -import jakarta.ws.rs.client.ClientBuilder; import jakarta.ws.rs.client.Invocation.Builder; import jakarta.ws.rs.client.WebTarget; import java.net.URI; @@ -46,7 +44,6 @@ public class HttpExecutor implements CallableTask { - private static final Client client = ClientBuilder.newClient(); // TODO allow changing default converter private static final HttpModelConverter defaultConverter = new HttpModelConverter() {}; @@ -262,13 +259,14 @@ public boolean accept(Class clazz) { } private static TargetSupplier getTargetSupplier(WorkflowValueResolver uriSupplier) { - return (w, t, n) -> client.target(uriSupplier.apply(w, t, n)); + return (w, t, n) -> HttpClientResolver.client(w, t).target(uriSupplier.apply(w, t, n)); } private static TargetSupplier getTargetSupplier( WorkflowValueResolver uriSupplier, WorkflowValueResolver pathSupplier) { return (w, t, n) -> - client.target(uriSupplier.apply(w, t, n).resolve(pathSupplier.apply(w, t, n))); + HttpClientResolver.client(w, t) + .target(uriSupplier.apply(w, t, n).resolve(pathSupplier.apply(w, t, n))); } private static interface TargetSupplier { From 7ea44f294d88c07f879effcc7bcc49e4c5892c08 Mon Sep 17 00:00:00 2001 From: fjtirado Date: Thu, 30 Oct 2025 15:32:01 +0100 Subject: [PATCH 2/2] [Fix #925] Review comments Signed-off-by: fjtirado --- .../impl/WorkflowApplication.java | 4 ++- .../ConstantAdditionalObject.java | 5 ++- .../additional/SuppliedAdditionalObject.java | 34 +++++++++++++++++++ .../WorkflowAdditionalObject.java | 4 ++- 4 files changed, 44 insertions(+), 3 deletions(-) rename impl/core/src/main/java/io/serverlessworkflow/impl/{ => additional}/ConstantAdditionalObject.java (86%) create mode 100644 impl/core/src/main/java/io/serverlessworkflow/impl/additional/SuppliedAdditionalObject.java rename impl/core/src/main/java/io/serverlessworkflow/impl/{ => additional}/WorkflowAdditionalObject.java (84%) diff --git a/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowApplication.java b/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowApplication.java index bd515479..cd97368a 100644 --- a/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowApplication.java +++ b/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowApplication.java @@ -19,6 +19,7 @@ import io.serverlessworkflow.api.types.SchemaInline; import io.serverlessworkflow.api.types.Workflow; +import io.serverlessworkflow.impl.additional.WorkflowAdditionalObject; import io.serverlessworkflow.impl.events.EventConsumer; import io.serverlessworkflow.impl.events.EventPublisher; import io.serverlessworkflow.impl.events.InMemoryEvents; @@ -225,7 +226,8 @@ public Builder withEventPublisher(EventPublisher eventPublisher) { return this; } - public Builder withExtensionObject(String name, WorkflowAdditionalObject additionalObject) { + public Builder withAdditionalObject( + String name, WorkflowAdditionalObject additionalObject) { if (additionalObjects == null) { additionalObjects = new ConcurrentHashMap<>(); } diff --git a/impl/core/src/main/java/io/serverlessworkflow/impl/ConstantAdditionalObject.java b/impl/core/src/main/java/io/serverlessworkflow/impl/additional/ConstantAdditionalObject.java similarity index 86% rename from impl/core/src/main/java/io/serverlessworkflow/impl/ConstantAdditionalObject.java rename to impl/core/src/main/java/io/serverlessworkflow/impl/additional/ConstantAdditionalObject.java index 0d4100e9..659af537 100644 --- a/impl/core/src/main/java/io/serverlessworkflow/impl/ConstantAdditionalObject.java +++ b/impl/core/src/main/java/io/serverlessworkflow/impl/additional/ConstantAdditionalObject.java @@ -13,7 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.serverlessworkflow.impl; +package io.serverlessworkflow.impl.additional; + +import io.serverlessworkflow.impl.TaskContext; +import io.serverlessworkflow.impl.WorkflowContext; public class ConstantAdditionalObject implements WorkflowAdditionalObject { diff --git a/impl/core/src/main/java/io/serverlessworkflow/impl/additional/SuppliedAdditionalObject.java b/impl/core/src/main/java/io/serverlessworkflow/impl/additional/SuppliedAdditionalObject.java new file mode 100644 index 00000000..d1eb1910 --- /dev/null +++ b/impl/core/src/main/java/io/serverlessworkflow/impl/additional/SuppliedAdditionalObject.java @@ -0,0 +1,34 @@ +/* + * 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.additional; + +import io.serverlessworkflow.impl.TaskContext; +import io.serverlessworkflow.impl.WorkflowContext; +import java.util.function.Supplier; + +public class SuppliedAdditionalObject implements WorkflowAdditionalObject { + + private final Supplier supplier; + + public SuppliedAdditionalObject(Supplier supplier) { + this.supplier = supplier; + } + + @Override + public T apply(WorkflowContext t, TaskContext u) { + return supplier.get(); + } +} diff --git a/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowAdditionalObject.java b/impl/core/src/main/java/io/serverlessworkflow/impl/additional/WorkflowAdditionalObject.java similarity index 84% rename from impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowAdditionalObject.java rename to impl/core/src/main/java/io/serverlessworkflow/impl/additional/WorkflowAdditionalObject.java index 79d8a4cd..f45c5edc 100644 --- a/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowAdditionalObject.java +++ b/impl/core/src/main/java/io/serverlessworkflow/impl/additional/WorkflowAdditionalObject.java @@ -13,8 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.serverlessworkflow.impl; +package io.serverlessworkflow.impl.additional; +import io.serverlessworkflow.impl.TaskContext; +import io.serverlessworkflow.impl.WorkflowContext; import java.util.function.BiFunction; public interface WorkflowAdditionalObject extends BiFunction {}