mirror of https://github.com/dapr/java-sdk.git
feat: Support registering activities with custom name (#1431)
* feat: Support register of activities with custom name Signed-off-by: Javier Aliaga <javier@diagrid.io> * chore: Apply suggestions Signed-off-by: Javier Aliaga <javier@diagrid.io> --------- Signed-off-by: Javier Aliaga <javier@diagrid.io> Co-authored-by: Cassie Coyle <cassie.i.coyle@gmail.com> Co-authored-by: Dapr Bot <56698301+dapr-bot@users.noreply.github.com>
This commit is contained in:
parent
a782438c36
commit
6ee1f59d61
|
@ -147,6 +147,29 @@ public class DaprWorkflowsIT {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNamedActivitiesWorkflows() throws Exception {
|
||||
TestWorkflowPayload payload = new TestWorkflowPayload(new ArrayList<>());
|
||||
String instanceId = workflowClient.scheduleNewWorkflow(TestNamedActivitiesWorkflow.class, payload);
|
||||
|
||||
workflowClient.waitForInstanceStart(instanceId, Duration.ofSeconds(10), false);
|
||||
|
||||
Duration timeout = Duration.ofSeconds(10);
|
||||
WorkflowInstanceStatus workflowStatus = workflowClient.waitForInstanceCompletion(instanceId, timeout, true);
|
||||
|
||||
assertNotNull(workflowStatus);
|
||||
|
||||
TestWorkflowPayload workflowOutput = deserialize(workflowStatus.getSerializedOutput());
|
||||
|
||||
assertEquals(5, workflowOutput.getPayloads().size());
|
||||
assertEquals("First Activity", workflowOutput.getPayloads().get(0));
|
||||
assertEquals("First Activity", workflowOutput.getPayloads().get(1));
|
||||
assertEquals("Second Activity", workflowOutput.getPayloads().get(2));
|
||||
assertEquals("Anonymous Activity", workflowOutput.getPayloads().get(3));
|
||||
assertEquals("Anonymous Activity 2", workflowOutput.getPayloads().get(4));
|
||||
|
||||
assertEquals(instanceId, workflowOutput.getWorkflowId());
|
||||
}
|
||||
|
||||
private TestWorkflowPayload deserialize(String value) throws JsonProcessingException {
|
||||
return OBJECT_MAPPER.readValue(value, TestWorkflowPayload.class);
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright 2025 The Dapr 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.dapr.it.testcontainers.workflows;
|
||||
|
||||
import io.dapr.workflows.Workflow;
|
||||
import io.dapr.workflows.WorkflowStub;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class TestNamedActivitiesWorkflow implements Workflow {
|
||||
|
||||
@Override
|
||||
public WorkflowStub create() {
|
||||
return ctx -> {
|
||||
Logger logger = ctx.getLogger();
|
||||
String instanceId = ctx.getInstanceId();
|
||||
logger.info("Starting Workflow: " + ctx.getName());
|
||||
logger.info("Instance ID: " + instanceId);
|
||||
logger.info("Current Orchestration Time: " + ctx.getCurrentInstant());
|
||||
|
||||
TestWorkflowPayload workflowPayload = ctx.getInput(TestWorkflowPayload.class);
|
||||
workflowPayload.setWorkflowId(instanceId);
|
||||
|
||||
var payloadAfterA = ctx.callActivity("a", workflowPayload, TestWorkflowPayload.class)
|
||||
.await();
|
||||
|
||||
var payloadAfterB = ctx.callActivity("b", payloadAfterA, TestWorkflowPayload.class)
|
||||
.await();
|
||||
|
||||
var payloadAfterC = ctx.callActivity("c", payloadAfterB, TestWorkflowPayload.class)
|
||||
.await();
|
||||
|
||||
var payloadAfterD = ctx.callActivity("d", payloadAfterC, TestWorkflowPayload.class)
|
||||
.await();
|
||||
|
||||
var payloadAfterE = ctx.callActivity("e", payloadAfterD, TestWorkflowPayload.class)
|
||||
.await();
|
||||
|
||||
ctx.complete(payloadAfterE);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -15,8 +15,10 @@ package io.dapr.it.testcontainers.workflows;
|
|||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.dapr.config.Properties;
|
||||
import io.dapr.workflows.WorkflowActivityContext;
|
||||
import io.dapr.workflows.client.DaprWorkflowClient;
|
||||
import io.dapr.workflows.runtime.WorkflowRuntimeBuilder;
|
||||
import io.dapr.workflows.WorkflowActivity;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
@ -56,8 +58,31 @@ public class TestWorkflowsConfiguration {
|
|||
WorkflowRuntimeBuilder builder = new WorkflowRuntimeBuilder(new Properties(overrides));
|
||||
|
||||
builder.registerWorkflow(TestWorkflow.class);
|
||||
builder.registerWorkflow(TestNamedActivitiesWorkflow.class);
|
||||
|
||||
builder.registerActivity(FirstActivity.class);
|
||||
builder.registerActivity(SecondActivity.class);
|
||||
builder.registerActivity("a",FirstActivity.class);
|
||||
builder.registerActivity("b",FirstActivity.class);
|
||||
builder.registerActivity("c", new SecondActivity());
|
||||
builder.registerActivity("d", new WorkflowActivity() {
|
||||
@Override
|
||||
public Object run(WorkflowActivityContext ctx) {
|
||||
TestWorkflowPayload workflowPayload = ctx.getInput(TestWorkflowPayload.class);
|
||||
workflowPayload.getPayloads().add("Anonymous Activity");
|
||||
return workflowPayload;
|
||||
}
|
||||
});
|
||||
builder.registerActivity("e", new WorkflowActivity() {
|
||||
@Override
|
||||
public Object run(WorkflowActivityContext ctx) {
|
||||
TestWorkflowPayload workflowPayload = ctx.getInput(TestWorkflowPayload.class);
|
||||
workflowPayload.getPayloads().add("Anonymous Activity 2");
|
||||
return workflowPayload;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
|
|
@ -30,19 +30,28 @@ public class WorkflowActivityClassWrapper<T extends WorkflowActivity> implements
|
|||
/**
|
||||
* Constructor for WorkflowActivityWrapper.
|
||||
*
|
||||
* @param name Name of the activity to wrap.
|
||||
* @param clazz Class of the activity to wrap.
|
||||
*/
|
||||
public WorkflowActivityClassWrapper(Class<T> clazz) {
|
||||
this.name = clazz.getCanonicalName();
|
||||
public WorkflowActivityClassWrapper(String name, Class<T> clazz) {
|
||||
this.name = name;
|
||||
try {
|
||||
this.activityConstructor = clazz.getDeclaredConstructor();
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(
|
||||
String.format("No constructor found for activity class '%s'.", this.name), e
|
||||
);
|
||||
String.format("No constructor found for activity class '%s'.", this.name), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for WorkflowActivityWrapper.
|
||||
*
|
||||
* @param clazz Class of the activity to wrap.
|
||||
*/
|
||||
public WorkflowActivityClassWrapper(Class<T> clazz) {
|
||||
this(clazz.getCanonicalName(), clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
|
@ -53,13 +62,12 @@ public class WorkflowActivityClassWrapper<T extends WorkflowActivity> implements
|
|||
return ctx -> {
|
||||
Object result;
|
||||
T activity;
|
||||
|
||||
|
||||
try {
|
||||
activity = this.activityConstructor.newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(
|
||||
String.format("Unable to instantiate instance of activity class '%s'", this.name), e
|
||||
);
|
||||
String.format("Unable to instantiate instance of activity class '%s'", this.name), e);
|
||||
}
|
||||
|
||||
result = activity.run(new DefaultWorkflowActivityContext(ctx));
|
||||
|
|
|
@ -24,14 +24,24 @@ public class WorkflowActivityInstanceWrapper<T extends WorkflowActivity> impleme
|
|||
private final T activity;
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Constructor for WorkflowActivityWrapper.
|
||||
*
|
||||
* @param name Name of the activity to wrap.
|
||||
* @param instance Instance of the activity to wrap.
|
||||
*/
|
||||
public WorkflowActivityInstanceWrapper(String name, T instance) {
|
||||
this.name = name;
|
||||
this.activity = instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for WorkflowActivityWrapper.
|
||||
*
|
||||
* @param instance Instance of the activity to wrap.
|
||||
*/
|
||||
public WorkflowActivityInstanceWrapper(T instance) {
|
||||
this.name = instance.getClass().getCanonicalName();
|
||||
this.activity = instance;
|
||||
this(instance.getClass().getCanonicalName(), instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -149,11 +149,23 @@ public class WorkflowRuntimeBuilder {
|
|||
* @return the WorkflowRuntimeBuilder
|
||||
*/
|
||||
public <T extends WorkflowActivity> WorkflowRuntimeBuilder registerActivity(Class<T> clazz) {
|
||||
this.builder.addActivity(new WorkflowActivityClassWrapper<>(clazz));
|
||||
this.activitySet.add(clazz.getCanonicalName());
|
||||
this.activities.add(clazz.getSimpleName());
|
||||
return registerActivity(clazz.getCanonicalName(), clazz);
|
||||
}
|
||||
|
||||
this.logger.info("Registered Activity: {}", clazz.getSimpleName());
|
||||
/**
|
||||
* Registers an Activity object.
|
||||
*
|
||||
* @param <T> any WorkflowActivity type
|
||||
* @param name Name of the activity to register.
|
||||
* @param clazz Class of the activity to register.
|
||||
* @return the WorkflowRuntimeBuilder
|
||||
*/
|
||||
public <T extends WorkflowActivity> WorkflowRuntimeBuilder registerActivity(String name, Class<T> clazz) {
|
||||
this.builder.addActivity(new WorkflowActivityClassWrapper<>(name, clazz));
|
||||
this.activitySet.add(name);
|
||||
this.activities.add(name);
|
||||
|
||||
this.logger.info("Registered Activity: {}", name);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
@ -166,13 +178,23 @@ public class WorkflowRuntimeBuilder {
|
|||
* @return the WorkflowRuntimeBuilder
|
||||
*/
|
||||
public <T extends WorkflowActivity> WorkflowRuntimeBuilder registerActivity(T instance) {
|
||||
Class<T> clazz = (Class<T>) instance.getClass();
|
||||
return this.registerActivity(instance.getClass().getCanonicalName(), instance);
|
||||
}
|
||||
|
||||
this.builder.addActivity(new WorkflowActivityInstanceWrapper<>(instance));
|
||||
this.activitySet.add(clazz.getCanonicalName());
|
||||
this.activities.add(clazz.getSimpleName());
|
||||
/**
|
||||
* Registers an Activity object.
|
||||
*
|
||||
* @param <T> any WorkflowActivity type
|
||||
* @param name Name of the activity to register.
|
||||
* @param instance the class instance being registered
|
||||
* @return the WorkflowRuntimeBuilder
|
||||
*/
|
||||
public <T extends WorkflowActivity> WorkflowRuntimeBuilder registerActivity(String name, T instance) {
|
||||
this.builder.addActivity(new WorkflowActivityInstanceWrapper<>(name, instance));
|
||||
this.activitySet.add(name);
|
||||
this.activities.add(name);
|
||||
|
||||
this.logger.info("Registered Activity: {}", clazz.getSimpleName());
|
||||
this.logger.info("Registered Activity: {}", name);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -6,10 +6,7 @@ import io.dapr.workflows.WorkflowActivityContext;
|
|||
import org.junit.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public class WorkflowActivityClassWrapperTest {
|
||||
public static class TestActivity implements WorkflowActivity {
|
||||
|
|
|
@ -19,15 +19,13 @@ import io.dapr.workflows.WorkflowStub;
|
|||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public class WorkflowRuntimeBuilderTest {
|
||||
public static class TestWorkflow implements Workflow {
|
||||
@Override
|
||||
|
@ -94,6 +92,6 @@ public class WorkflowRuntimeBuilderTest {
|
|||
.info(eq("Registered Workflow: {}"), eq("TestWorkflow"));
|
||||
|
||||
verify(testLogger, times(1))
|
||||
.info(eq("Registered Activity: {}"), eq("TestActivity"));
|
||||
.info(eq("Registered Activity: {}"), eq("io.dapr.workflows.runtime.WorkflowRuntimeBuilderTest.TestActivity"));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue