Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import java.util.ServiceLoader.Provider;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.function.Supplier;
import java.util.stream.Collectors;

public class WorkflowApplication implements AutoCloseable {
Expand All @@ -91,6 +92,7 @@ public class WorkflowApplication implements AutoCloseable {
private final WorkflowModelFactory contextFactory;
private final WorkflowScheduler scheduler;
private final Map<String, WorkflowAdditionalObject<?>> additionalObjects;
private final Map<String, Supplier<?>> additionalObjectSuppliers;
private final AuthProviderFactory authProviderFactory;
private final ConfigManager configManager;
private final SecretManager secretManager;
Expand Down Expand Up @@ -123,6 +125,7 @@ private WorkflowApplication(Builder builder) {
this.scheduler = builder.scheduler;
this.schedulerListener = builder.schedulerListener;
this.additionalObjects = builder.additionalObjects;
this.additionalObjectSuppliers = builder.additionalObjectSuppliers;
this.authProviderFactory = builder.authProviderFactory;
this.configManager = builder.configManager;
this.secretManager = builder.secretManager;
Expand Down Expand Up @@ -245,6 +248,7 @@ public SchemaValidator getValidator(SchemaInline inline) {
private WorkflowModelFactory modelFactory;
private WorkflowModelFactory contextFactory;
private Map<String, WorkflowAdditionalObject<?>> additionalObjects = new HashMap<>();
private Map<String, Supplier<?>> additionalObjectSuppliers = new HashMap<>();
private AuthProviderFactory authProviderFactory;
private SecretManager secretManager;
private ConfigManager configManager;
Expand Down Expand Up @@ -362,6 +366,11 @@ public <T> Builder withAdditionalObject(
return this;
}

public <T> Builder withAdditionalObject(String name, Supplier<T> additionalObject) {
additionalObjectSuppliers.put(name, additionalObject);
return this;
}

public Builder withAuthProviderFactory(AuthProviderFactory authProviderFactory) {
this.authProviderFactory = authProviderFactory;
return this;
Expand Down Expand Up @@ -594,6 +603,10 @@ public String id() {
return id;
}

public <T> Optional<T> additionalObject(String name) {
return Optional.ofNullable(additionalObjectSuppliers.get(name)).map(v -> (T) v.get());
}

public <T> Optional<T> additionalObject(
String name, WorkflowContext workflowContext, TaskContext taskContext) {
return Optional.ofNullable(additionalObjects.get(name))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* 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 static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import io.serverlessworkflow.impl.additional.WorkflowAdditionalObject;
import io.serverlessworkflow.impl.lifecycle.WorkflowExecutionCompletableListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class WorkflowAdditionalObjectTest {

private WorkflowExecutionCompletableListener mediumPrio = new MediumPriorityListener("javi");
private WorkflowExecutionCompletableListener lowestPrio = new LowestPriorityListener();
private WorkflowExecutionCompletableListener topPrio = new TopPriorityListener();
private WorkflowModelFactory modelFactory;

@BeforeEach
void setup() {
modelFactory = mock(WorkflowModelFactory.class);
}

private static class DummyAdditionalObjectBiFunction
implements WorkflowAdditionalObject<Integer> {
@Override
public Integer apply(WorkflowContextData workflowContext, TaskContextData taskContext) {
return Integer.valueOf((int) taskContext.retryAttempt());
}
}

private class DummyAdditionalObjectSupplier implements Supplier<List<ServicePriority>> {
@Override
public List<ServicePriority> get() {
return List.of(mediumPrio, lowestPrio, topPrio);
}
}

@Test
void testAdditionalObjectBiFunction() {
WorkflowContext workflowContext = mock(WorkflowContext.class);
TaskContext taskContext = mock(TaskContext.class);
when(taskContext.retryAttempt()).thenReturn((short) 2);
final String key = "Dummy_Bifactory";
try (WorkflowApplication appl =
WorkflowApplication.builder()
.withAdditionalObject(key, new DummyAdditionalObjectBiFunction())
.withModelFactory(modelFactory)
.build()) {
assertThat(appl.<Integer>additionalObject(key, workflowContext, taskContext).orElse(0))
.isEqualTo(2);
}
}

@Test
void testAdditionalObjectSupplier() {
final String key = "Dummy_supplier";
try (WorkflowApplication appl =
WorkflowApplication.builder()
.withModelFactory(modelFactory)
.withAdditionalObject(key, new DummyAdditionalObjectSupplier())
.build()) {
List<ServicePriority> priorities = new ArrayList<>();
WorkflowExecutionCompletableListener anotherMediumPrio =
new MediumPriorityListener("javierito");
priorities.add(anotherMediumPrio);
priorities.addAll(appl.<List<ServicePriority>>additionalObject(key).orElse(List.of()));
Collections.sort(priorities);
assertThat(priorities).isEqualTo(List.of(topPrio, anotherMediumPrio, mediumPrio, lowestPrio));
}
}

@Test
void testAdditionalObjectSupplierNull() {
Comment thread
fjtirado marked this conversation as resolved.
final String key = "Null_supplier";
try (WorkflowApplication appl =
WorkflowApplication.builder()
.withModelFactory(modelFactory)
.withAdditionalObject(key, () -> null)
.build()) {
assertThat(appl.additionalObject(key)).isEmpty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.concurrent.CompletableFuture;

public class HttpExecutor implements CallableTask {
Expand All @@ -45,17 +44,14 @@ public class HttpExecutor implements CallableTask {
Optional<WorkflowValueResolver<Map<String, Object>>> headersMap,
Optional<WorkflowValueResolver<Map<String, Object>>> queryMap,
RequestExecutor requestFunction,
Optional<WorkflowValueResolver<URI>> pathSupplier) {
Optional<WorkflowValueResolver<URI>> pathSupplier,
Collection<HttpRequestDecorator> requestDecorators) {
this.uriSupplier = uriSupplier;
this.headersMap = headersMap;
this.queryMap = queryMap;
this.requestFunction = requestFunction;
this.pathSupplier = pathSupplier;
this.requestDecorators =
ServiceLoader.load(HttpRequestDecorator.class).stream()
.map(ServiceLoader.Provider::get)
.sorted()
.toList();
this.requestDecorators = requestDecorators;
}

public CompletableFuture<WorkflowModel> apply(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,19 @@
import io.serverlessworkflow.impl.auth.AuthProvider;
import jakarta.ws.rs.HttpMethod;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.ServiceLoader;

public class HttpExecutorBuilder {

public static final String HTTP_REQUEST_DECORATOR_KEY = "HttpRequestDecorators";
private final WorkflowDefinition definition;
private final List<HttpRequestDecorator> requestDecorators;
private WorkflowValueResolver<URI> pathSupplier;
private Object body;
private String method = HttpMethod.GET;
Expand All @@ -40,6 +47,14 @@ public class HttpExecutorBuilder {

private HttpExecutorBuilder(WorkflowDefinition definition) {
this.definition = definition;
this.requestDecorators = new ArrayList<>();
requestDecorators.addAll(
definition
.application()
.<Collection<HttpRequestDecorator>>additionalObject(HTTP_REQUEST_DECORATOR_KEY)
.orElse(List.of()));
Comment thread
fjtirado marked this conversation as resolved.
ServiceLoader.load(HttpRequestDecorator.class).forEach(requestDecorators::add);
Collections.sort(requestDecorators);
}

public HttpExecutorBuilder withAuth(ReferenceableAuthenticationPolicy policy) {
Expand Down Expand Up @@ -110,7 +125,8 @@ public HttpExecutor build(WorkflowValueResolver<URI> uriSupplier) {
Optional.ofNullable(headersMap),
Optional.ofNullable(queryMap),
buildRequestExecutor(),
Optional.ofNullable(pathSupplier));
Optional.ofNullable(pathSupplier),
requestDecorators);
}

public static HttpExecutorBuilder builder(WorkflowDefinition definition) {
Expand Down
Loading