diff --git a/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/DefaultProcessEventListenerConfig.java b/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/DefaultProcessEventListenerConfig.java index f6cfa8a58b5..143033d8c53 100644 --- a/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/DefaultProcessEventListenerConfig.java +++ b/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/DefaultProcessEventListenerConfig.java @@ -27,4 +27,10 @@ public DefaultProcessEventListenerConfig(ProcessEventListener... listeners) { register(listener); } } + + public DefaultProcessEventListenerConfig(Iterable listeners) { + for (ProcessEventListener listener : listeners) { + register(listener); + } + } } diff --git a/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/main/java/org/kie/kogito/serverless/workflow/executor/StaticWorkflowApplication.java b/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/main/java/org/kie/kogito/serverless/workflow/executor/StaticWorkflowApplication.java index bce8b4f53b6..aaaedd8606d 100644 --- a/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/main/java/org/kie/kogito/serverless/workflow/executor/StaticWorkflowApplication.java +++ b/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/main/java/org/kie/kogito/serverless/workflow/executor/StaticWorkflowApplication.java @@ -20,10 +20,13 @@ import java.io.IOException; import java.io.InputStream; +import java.net.URL; import java.time.Duration; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.Properties; @@ -46,6 +49,7 @@ import org.kie.kogito.config.StaticConfigBean; import org.kie.kogito.event.impl.EventFactoryUtils; import org.kie.kogito.internal.process.event.DefaultKogitoProcessEventListener; +import org.kie.kogito.internal.process.event.KogitoProcessEventListener; import org.kie.kogito.internal.process.runtime.KogitoWorkItemHandler; import org.kie.kogito.process.Process; import org.kie.kogito.process.ProcessInstance; @@ -120,28 +124,74 @@ public void afterProcessCompleted(ProcessCompletedEvent event) { } } - public static StaticWorkflowApplication create() { - Properties properties = new Properties(); - try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("application.properties")) { - if (is != null) { - properties.load(is); + public static class WorkflowApplicationBuilder { + + private Map properties; + private Collection listeners = new ArrayList<>(); + + private WorkflowApplicationBuilder() { + } + + public WorkflowApplicationBuilder withProperties(Map properties) { + this.properties = properties; + return this; + } + + public WorkflowApplicationBuilder withEventListener(KogitoProcessEventListener listener, KogitoProcessEventListener... extraListeners) { + listeners.add(listener); + for (KogitoProcessEventListener extraListener : extraListeners) { + listeners.add(extraListener); + } + return this; + } + + public StaticWorkflowApplication build() { + if (properties == null) { + this.properties = loadApplicationDotProperties(); + } + Map> queues = new ConcurrentHashMap<>(); + listeners.add(new StaticCompletionEventListener(queues)); + StaticWorkflowApplication application = new StaticWorkflowApplication(properties, queues, listeners); + application.applicationRegisters.forEach(register -> register.register(application)); + return application; + } + } + + private static Map loadApplicationDotProperties() { + Map allProperties = new HashMap<>(); + try { + Enumeration urls = Thread.currentThread().getContextClassLoader().getResources("application.properties"); + while (urls.hasMoreElements()) { + URL url = urls.nextElement(); + try (InputStream is = url.openStream()) { + Properties fileProperties = new Properties(); + fileProperties.load(is); + fileProperties.entrySet().forEach(e -> allProperties.put(e.getKey().toString(), e.getValue())); + } catch (IOException io) { + logger.info("Error loading properties from URL {}", url, io); + } } } catch (IOException io) { - logger.warn("Error loading application.properties from classpath", io); + logger.warn("Error searching for application.properties in classpath", io); } - return create((Map) properties); + return allProperties; + } + + public static WorkflowApplicationBuilder builder() { + return new WorkflowApplicationBuilder(); + } + + public static StaticWorkflowApplication create() { + return builder().build(); } public static StaticWorkflowApplication create(Map properties) { - Map> queues = new ConcurrentHashMap<>(); - StaticWorkflowApplication application = new StaticWorkflowApplication(properties, queues); - application.applicationRegisters.forEach(register -> register.register(application)); - return application; + return builder().withProperties(properties).build(); } - private StaticWorkflowApplication(Map properties, Map> queues) { + private StaticWorkflowApplication(Map properties, Map> queues, Collection listeners) { super(new StaticConfig(new Addons(Collections.emptySet()), new StaticProcessConfig(new CachedWorkItemHandlerConfig(), - new DefaultProcessEventListenerConfig(new StaticCompletionEventListener(queues)), + new DefaultProcessEventListenerConfig(listeners), new DefaultUnitOfWorkManager(new CollectingUnitOfWorkFactory())), new StaticConfigBean())); if (!properties.isEmpty()) { ConfigResolverHolder.setConfigResolver(MultiSourceConfigResolver.withSystemProperties(properties)); diff --git a/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/test/java/org/kie/kogito/serverless/workflow/executor/StaticFluentWorkflowApplicationTest.java b/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/test/java/org/kie/kogito/serverless/workflow/executor/StaticFluentWorkflowApplicationTest.java index d96afcd2c9d..81de083a09a 100644 --- a/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/test/java/org/kie/kogito/serverless/workflow/executor/StaticFluentWorkflowApplicationTest.java +++ b/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/test/java/org/kie/kogito/serverless/workflow/executor/StaticFluentWorkflowApplicationTest.java @@ -23,8 +23,11 @@ import java.util.Collections; import java.util.Map; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; import org.junit.jupiter.api.Test; +import org.kie.api.event.process.ProcessCompletedEvent; +import org.kie.kogito.internal.process.event.DefaultKogitoProcessEventListener; import org.kie.kogito.process.Process; import org.kie.kogito.serverless.workflow.actions.SysoutAction; import org.kie.kogito.serverless.workflow.actions.WorkflowLogLevel; @@ -67,9 +70,15 @@ public class StaticFluentWorkflowApplicationTest { @Test void helloWorld() { final String GREETING_STRING = "Hello World!!!"; - try (StaticWorkflowApplication application = StaticWorkflowApplication.create()) { + AtomicBoolean completed = new AtomicBoolean(false); + try (StaticWorkflowApplication application = StaticWorkflowApplication.builder().withEventListener(new DefaultKogitoProcessEventListener() { + public void afterProcessCompleted(ProcessCompletedEvent event) { + completed.set(true); + } + }).build()) { Workflow workflow = workflow("HelloWorld").start(inject(new TextNode(GREETING_STRING))).end().build(); assertThat(application.execute(workflow, Collections.emptyMap()).getWorkflowdata()).contains(new TextNode(GREETING_STRING)); + assertThat(completed.get()).isTrue(); } }