diff --git a/sdk-workflows/src/main/java/io/dapr/workflows/runtime/DefaultWorkflowActivityContext.java b/sdk-workflows/src/main/java/io/dapr/workflows/runtime/DefaultWorkflowActivityContext.java index d6f935e8f8..cc7cc44e74 100644 --- a/sdk-workflows/src/main/java/io/dapr/workflows/runtime/DefaultWorkflowActivityContext.java +++ b/sdk-workflows/src/main/java/io/dapr/workflows/runtime/DefaultWorkflowActivityContext.java @@ -21,7 +21,7 @@ /** * Wrapper for Durable Task Framework {@link TaskActivityContext}. */ -class DefaultWorkflowActivityContext implements WorkflowActivityContext { +public class DefaultWorkflowActivityContext implements WorkflowActivityContext { private final TaskActivityContext innerContext; private final Logger logger; @@ -50,6 +50,7 @@ public DefaultWorkflowActivityContext(TaskActivityContext context, Class claz * Constructor for WorkflowActivityContext. * * @param context TaskActivityContext + * @param logger org.slf4j.Logger instance * @throws IllegalArgumentException if context is null */ public DefaultWorkflowActivityContext(TaskActivityContext context, Logger logger) throws IllegalArgumentException { diff --git a/sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowRuntimeBuilder.java b/sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowRuntimeBuilder.java index 12fe62860b..c586387aa9 100644 --- a/sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowRuntimeBuilder.java +++ b/sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowRuntimeBuilder.java @@ -15,6 +15,8 @@ import io.dapr.config.Properties; import io.dapr.durabletask.DurableTaskGrpcWorkerBuilder; +import io.dapr.durabletask.TaskActivityFactory; +import io.dapr.durabletask.TaskOrchestrationFactory; import io.dapr.utils.NetworkUtils; import io.dapr.workflows.Workflow; import io.dapr.workflows.WorkflowActivity; @@ -80,8 +82,8 @@ public WorkflowRuntime build() { this.executorService = this.executorService == null ? Executors.newCachedThreadPool() : this.executorService; if (instance == null) { instance = new WorkflowRuntime( - this.builder.withExecutorService(this.executorService).build(), - this.managedChannel, this.executorService); + this.builder.withExecutorService(this.executorService).build(), + this.managedChannel, this.executorService); } } } @@ -125,7 +127,7 @@ public WorkflowRuntimeBuilder registerWorkflow(Class cla /** * Registers a Workflow object. * - * @param any Workflow type + * @param any Workflow type * @param instance the workflow instance being registered * @return the WorkflowRuntimeBuilder */ @@ -156,7 +158,7 @@ public WorkflowRuntimeBuilder registerActivity(Clas * Registers an Activity object. * * @param any WorkflowActivity type - * @param name Name of the activity to register. + * @param name Name of the activity to register. * @param clazz Class of the activity to register. * @return the WorkflowRuntimeBuilder */ @@ -173,7 +175,7 @@ public WorkflowRuntimeBuilder registerActivity(Stri /** * Registers an Activity object. * - * @param any WorkflowActivity type + * @param any WorkflowActivity type * @param instance the class instance being registered * @return the WorkflowRuntimeBuilder */ @@ -184,8 +186,8 @@ public WorkflowRuntimeBuilder registerActivity(T in /** * Registers an Activity object. * - * @param any WorkflowActivity type - * @param name Name of the activity to register. + * @param any WorkflowActivity type + * @param name Name of the activity to register. * @param instance the class instance being registered * @return the WorkflowRuntimeBuilder */ @@ -199,4 +201,52 @@ public WorkflowRuntimeBuilder registerActivity(Stri return this; } + /** + * Registers a Task Activity using a {@link TaskActivityFactory}. + * + *

This method allows advanced use cases where activities are created + * dynamically or require custom instantiation logic instead of relying + * on class-based or instance-based registration. + * + * @param activityName the logical name of the activity to register + * @param taskActivityFactory the factory responsible for creating the activity + * @return the {@link WorkflowRuntimeBuilder} + */ + public WorkflowRuntimeBuilder registerTaskActivityFactory( + String activityName, + TaskActivityFactory taskActivityFactory) { + + this.builder.addActivity(taskActivityFactory); + this.activitySet.add(activityName); + this.activities.add(activityName); + + this.logger.info("Registered Activity: {}", activityName); + + return this; + } + + /** + * Registers a Task Orchestration using a {@link TaskOrchestrationFactory}. + * + *

This method is intended for advanced scenarios where orchestrations + * are created programmatically or require custom construction logic, + * rather than being registered via workflow classes or instances. + * + * @param orchestrationName the logical name of the orchestration to register + * @param taskOrchestrationFactory the factory responsible for creating the orchestration + * @return the {@link WorkflowRuntimeBuilder} + */ + public WorkflowRuntimeBuilder registerTaskOrchestrationFactory( + String orchestrationName, + TaskOrchestrationFactory taskOrchestrationFactory) { + + this.builder.addOrchestration(taskOrchestrationFactory); + this.workflows.add(orchestrationName); + this.workflowSet.add(orchestrationName); + + this.logger.info("Registered Workflow: {}", orchestrationName); + + return this; + } + } diff --git a/sdk-workflows/src/test/java/io/dapr/workflows/runtime/WorkflowRuntimeBuilderTest.java b/sdk-workflows/src/test/java/io/dapr/workflows/runtime/WorkflowRuntimeBuilderTest.java index 98ddffd53d..50a21f0b38 100644 --- a/sdk-workflows/src/test/java/io/dapr/workflows/runtime/WorkflowRuntimeBuilderTest.java +++ b/sdk-workflows/src/test/java/io/dapr/workflows/runtime/WorkflowRuntimeBuilderTest.java @@ -12,6 +12,10 @@ */ package io.dapr.workflows.runtime; +import io.dapr.durabletask.TaskActivity; +import io.dapr.durabletask.TaskActivityFactory; +import io.dapr.durabletask.TaskOrchestration; +import io.dapr.durabletask.TaskOrchestrationFactory; import io.dapr.workflows.Workflow; import io.dapr.workflows.WorkflowActivity; import io.dapr.workflows.WorkflowActivityContext; @@ -62,6 +66,60 @@ public void registerValidWorkflowActivityInstance() { assertDoesNotThrow(() -> new WorkflowRuntimeBuilder().registerActivity(new TestActivity())); } + @Test + public void registerValidTaskActivityFactory() { + class A implements WorkflowActivity{ + + @Override + public Object run(WorkflowActivityContext ctx) { + return "a"; + } + } + + assertDoesNotThrow(() -> new WorkflowRuntimeBuilder().registerTaskActivityFactory(A.class.getName(), + new TaskActivityFactory() { + @Override + public String getName() { + return A.class.getName(); + } + + @Override + public TaskActivity create() { + A a = new A(); + return ctx -> a.run(new DefaultWorkflowActivityContext(ctx, a.getClass())); + } + })); + } + + @Test + public void registerValidWorkflowOrchestrator() { + class W implements Workflow{ + + @Override + public WorkflowStub create() { + return ctx -> { + ctx.complete("w"); + }; + } + } + + assertDoesNotThrow(() -> { + new WorkflowRuntimeBuilder().registerTaskOrchestrationFactory(W.class.getName(), new TaskOrchestrationFactory() { + @Override + public String getName() { + return W.class.getName(); + } + + @Override + public TaskOrchestration create() { + W w = new W(); + return ctx -> w.run(new DefaultWorkflowContext(ctx, w.getClass())); + } + }); + }); + + } + @Test public void buildTest() { assertDoesNotThrow(() -> {