Skip to content

Commit 58d6218

Browse files
Register workflows and acitivities using instances along classes (#1201)
1 parent cf7405f commit 58d6218

11 files changed

+306
-45
lines changed

dapr-spring/dapr-spring-workflows/src/main/java/io/dapr/spring/workflows/config/DaprWorkflowsConfiguration.java

+12-7
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
public class DaprWorkflowsConfiguration implements ApplicationContextAware {
1818
private static final Logger LOGGER = LoggerFactory.getLogger(DaprWorkflowsConfiguration.class);
1919

20-
private WorkflowRuntimeBuilder workflowRuntimeBuilder;
20+
private final WorkflowRuntimeBuilder workflowRuntimeBuilder;
2121

2222
public DaprWorkflowsConfiguration(WorkflowRuntimeBuilder workflowRuntimeBuilder) {
2323
this.workflowRuntimeBuilder = workflowRuntimeBuilder;
@@ -29,16 +29,21 @@ public DaprWorkflowsConfiguration(WorkflowRuntimeBuilder workflowRuntimeBuilder)
2929
*/
3030
private void registerWorkflowsAndActivities(ApplicationContext applicationContext) {
3131
LOGGER.info("Registering Dapr Workflows and Activities");
32+
3233
Map<String, Workflow> workflowBeans = applicationContext.getBeansOfType(Workflow.class);
33-
for (Workflow w : workflowBeans.values()) {
34-
LOGGER.info("Dapr Workflow: '{}' registered", w.getClass().getName());
35-
workflowRuntimeBuilder.registerWorkflow(w.getClass());
34+
35+
for (Workflow workflow : workflowBeans.values()) {
36+
LOGGER.info("Dapr Workflow: '{}' registered", workflow.getClass().getName());
37+
38+
workflowRuntimeBuilder.registerWorkflow(workflow);
3639
}
3740

3841
Map<String, WorkflowActivity> workflowActivitiesBeans = applicationContext.getBeansOfType(WorkflowActivity.class);
39-
for (WorkflowActivity a : workflowActivitiesBeans.values()) {
40-
LOGGER.info("Dapr Workflow Activity: '{}' registered", a.getClass().getName());
41-
workflowRuntimeBuilder.registerActivity(a.getClass());
42+
43+
for (WorkflowActivity activity : workflowActivitiesBeans.values()) {
44+
LOGGER.info("Dapr Workflow Activity: '{}' registered", activity.getClass().getName());
45+
46+
workflowRuntimeBuilder.registerActivity(activity);
4247
}
4348

4449
try (WorkflowRuntime runtime = workflowRuntimeBuilder.build()) {

sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowActivityWrapper.java sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowActivityClassWrapper.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
/**
2424
* Wrapper for Durable Task Framework task activity factory.
2525
*/
26-
public class WorkflowActivityWrapper<T extends WorkflowActivity> implements TaskActivityFactory {
26+
public class WorkflowActivityClassWrapper<T extends WorkflowActivity> implements TaskActivityFactory {
2727
private final Constructor<T> activityConstructor;
2828
private final String name;
2929

@@ -32,7 +32,7 @@ public class WorkflowActivityWrapper<T extends WorkflowActivity> implements Task
3232
*
3333
* @param clazz Class of the activity to wrap.
3434
*/
35-
public WorkflowActivityWrapper(Class<T> clazz) {
35+
public WorkflowActivityClassWrapper(Class<T> clazz) {
3636
this.name = clazz.getCanonicalName();
3737
try {
3838
this.activityConstructor = clazz.getDeclaredConstructor();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2023 The Dapr Authors
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
package io.dapr.workflows.runtime;
15+
16+
import com.microsoft.durabletask.TaskActivity;
17+
import com.microsoft.durabletask.TaskActivityFactory;
18+
import io.dapr.workflows.WorkflowActivity;
19+
20+
/**
21+
* Wrapper for Durable Task Framework task activity factory.
22+
*/
23+
public class WorkflowActivityInstanceWrapper<T extends WorkflowActivity> implements TaskActivityFactory {
24+
private final T activity;
25+
private final String name;
26+
27+
/**
28+
* Constructor for WorkflowActivityWrapper.
29+
*
30+
* @param instance Instance of the activity to wrap.
31+
*/
32+
public WorkflowActivityInstanceWrapper(T instance) {
33+
this.name = instance.getClass().getCanonicalName();
34+
this.activity = instance;
35+
}
36+
37+
@Override
38+
public String getName() {
39+
return name;
40+
}
41+
42+
@Override
43+
public TaskActivity create() {
44+
return ctx -> activity.run(new DefaultWorkflowActivityContext(ctx));
45+
}
46+
}

sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowWrapper.java sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowClassWrapper.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@
2424
/**
2525
* Wrapper for Durable Task Framework orchestration factory.
2626
*/
27-
class WorkflowWrapper<T extends Workflow> implements TaskOrchestrationFactory {
27+
class WorkflowClassWrapper<T extends Workflow> implements TaskOrchestrationFactory {
2828
private final Constructor<T> workflowConstructor;
2929
private final String name;
3030

31-
public WorkflowWrapper(Class<T> clazz) {
31+
public WorkflowClassWrapper(Class<T> clazz) {
3232
this.name = clazz.getCanonicalName();
3333
try {
3434
this.workflowConstructor = clazz.getDeclaredConstructor();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2023 The Dapr Authors
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
package io.dapr.workflows.runtime;
15+
16+
import com.microsoft.durabletask.TaskOrchestration;
17+
import com.microsoft.durabletask.TaskOrchestrationFactory;
18+
import io.dapr.workflows.Workflow;
19+
import io.dapr.workflows.saga.Saga;
20+
21+
/**
22+
* Wrapper for Durable Task Framework orchestration factory.
23+
*/
24+
class WorkflowInstanceWrapper<T extends Workflow> implements TaskOrchestrationFactory {
25+
private final T workflow;
26+
private final String name;
27+
28+
public WorkflowInstanceWrapper(T instance) {
29+
this.name = instance.getClass().getCanonicalName();
30+
this.workflow = instance;
31+
}
32+
33+
@Override
34+
public String getName() {
35+
return name;
36+
}
37+
38+
@Override
39+
public TaskOrchestration create() {
40+
return ctx -> {
41+
if (workflow.getSagaOption() != null) {
42+
Saga saga = new Saga(workflow.getSagaOption());
43+
workflow.run(new DefaultWorkflowContext(ctx, saga));
44+
} else {
45+
workflow.run(new DefaultWorkflowContext(ctx));
46+
}
47+
};
48+
}
49+
}

sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowRuntimeBuilder.java

+42-4
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,30 @@ public WorkflowRuntime build() {
9292
* @return the WorkflowRuntimeBuilder
9393
*/
9494
public <T extends Workflow> WorkflowRuntimeBuilder registerWorkflow(Class<T> clazz) {
95-
this.builder.addOrchestration(new WorkflowWrapper<>(clazz));
95+
this.builder.addOrchestration(new WorkflowClassWrapper<>(clazz));
9696
this.workflowSet.add(clazz.getCanonicalName());
9797
this.workflows.add(clazz.getSimpleName());
9898

99-
this.logger.info("Registered Workflow: " + clazz.getSimpleName());
99+
this.logger.info("Registered Workflow: {}", clazz.getSimpleName());
100+
101+
return this;
102+
}
103+
104+
/**
105+
* Registers a Workflow object.
106+
*
107+
* @param <T> any Workflow type
108+
* @param instance the workflow instance being registered
109+
* @return the WorkflowRuntimeBuilder
110+
*/
111+
public <T extends Workflow> WorkflowRuntimeBuilder registerWorkflow(T instance) {
112+
Class<T> clazz = (Class<T>) instance.getClass();
113+
114+
this.builder.addOrchestration(new WorkflowInstanceWrapper<>(instance));
115+
this.workflowSet.add(clazz.getCanonicalName());
116+
this.workflows.add(clazz.getSimpleName());
117+
118+
this.logger.info("Registered Workflow: {}", clazz.getSimpleName());
100119

101120
return this;
102121
}
@@ -109,11 +128,30 @@ public <T extends Workflow> WorkflowRuntimeBuilder registerWorkflow(Class<T> cla
109128
* @return the WorkflowRuntimeBuilder
110129
*/
111130
public <T extends WorkflowActivity> WorkflowRuntimeBuilder registerActivity(Class<T> clazz) {
112-
this.builder.addActivity(new WorkflowActivityWrapper<>(clazz));
131+
this.builder.addActivity(new WorkflowActivityClassWrapper<>(clazz));
132+
this.activitySet.add(clazz.getCanonicalName());
133+
this.activities.add(clazz.getSimpleName());
134+
135+
this.logger.info("Registered Activity: {}", clazz.getSimpleName());
136+
137+
return this;
138+
}
139+
140+
/**
141+
* Registers an Activity object.
142+
*
143+
* @param <T> any WorkflowActivity type
144+
* @param instance the class instance being registered
145+
* @return the WorkflowRuntimeBuilder
146+
*/
147+
public <T extends WorkflowActivity> WorkflowRuntimeBuilder registerActivity(T instance) {
148+
Class<T> clazz = (Class<T>) instance.getClass();
149+
150+
this.builder.addActivity(new WorkflowActivityInstanceWrapper<>(instance));
113151
this.activitySet.add(clazz.getCanonicalName());
114152
this.activities.add(clazz.getSimpleName());
115153

116-
this.logger.info("Registered Activity: " + clazz.getSimpleName());
154+
this.logger.info("Registered Activity: {}", clazz.getSimpleName());
117155

118156
return this;
119157
}

sdk-workflows/src/test/java/io/dapr/workflows/runtime/WorkflowActivityWrapperTest.java sdk-workflows/src/test/java/io/dapr/workflows/runtime/WorkflowActivityClassWrapperTest.java

+13-12
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@
33
import com.microsoft.durabletask.TaskActivityContext;
44
import io.dapr.workflows.WorkflowActivity;
55
import io.dapr.workflows.WorkflowActivityContext;
6-
import org.junit.Assert;
76
import org.junit.Test;
87

8+
import static org.junit.jupiter.api.Assertions.assertEquals;
99
import static org.mockito.Mockito.mock;
1010
import static org.mockito.Mockito.times;
1111
import static org.mockito.Mockito.verify;
1212
import static org.mockito.Mockito.when;
1313

14-
15-
public class WorkflowActivityWrapperTest {
14+
public class WorkflowActivityClassWrapperTest {
1615
public static class TestActivity implements WorkflowActivity {
1716
@Override
1817
public Object run(WorkflowActivityContext ctx) {
@@ -22,24 +21,26 @@ public Object run(WorkflowActivityContext ctx) {
2221
}
2322

2423
@Test
25-
public void getName() throws NoSuchMethodException {
26-
WorkflowActivityWrapper<TestActivity> wrapper = new WorkflowActivityWrapper<>(
27-
WorkflowActivityWrapperTest.TestActivity.class);
28-
Assert.assertEquals(
29-
"io.dapr.workflows.runtime.WorkflowActivityWrapperTest.TestActivity",
24+
public void getName() {
25+
WorkflowActivityClassWrapper<TestActivity> wrapper = new WorkflowActivityClassWrapper<>(TestActivity.class);
26+
27+
assertEquals(
28+
"io.dapr.workflows.runtime.WorkflowActivityClassWrapperTest.TestActivity",
3029
wrapper.getName()
3130
);
3231
}
3332

3433
@Test
35-
public void createWithClass() throws NoSuchMethodException {
34+
public void createWithClass() {
3635
TaskActivityContext mockContext = mock(TaskActivityContext.class);
37-
WorkflowActivityWrapper<TestActivity> wrapper = new WorkflowActivityWrapper<>(
38-
WorkflowActivityWrapperTest.TestActivity.class);
36+
WorkflowActivityClassWrapper<TestActivity> wrapper = new WorkflowActivityClassWrapper<>(TestActivity.class);
37+
3938
when(mockContext.getInput(String.class)).thenReturn("Hello");
4039
when(mockContext.getName()).thenReturn("TestActivityContext");
40+
4141
Object result = wrapper.create().run(mockContext);
42+
4243
verify(mockContext, times(1)).getInput(String.class);
43-
Assert.assertEquals("Hello world! from TestActivityContext", result);
44+
assertEquals("Hello world! from TestActivityContext", result);
4445
}
4546
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package io.dapr.workflows.runtime;
2+
3+
import com.microsoft.durabletask.TaskActivityContext;
4+
import io.dapr.workflows.WorkflowActivity;
5+
import io.dapr.workflows.WorkflowActivityContext;
6+
import org.junit.Test;
7+
8+
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
import static org.mockito.Mockito.mock;
10+
import static org.mockito.Mockito.times;
11+
import static org.mockito.Mockito.verify;
12+
import static org.mockito.Mockito.when;
13+
14+
public class WorkflowActivityInstanceWrapperTest {
15+
public static class TestActivity implements WorkflowActivity {
16+
@Override
17+
public Object run(WorkflowActivityContext ctx) {
18+
String activityContextName = ctx.getName();
19+
return ctx.getInput(String.class) + " world! from " + activityContextName;
20+
}
21+
}
22+
23+
@Test
24+
public void getName() {
25+
WorkflowActivityInstanceWrapper<TestActivity> wrapper = new WorkflowActivityInstanceWrapper<>(new TestActivity());
26+
27+
assertEquals(
28+
"io.dapr.workflows.runtime.WorkflowActivityInstanceWrapperTest.TestActivity",
29+
wrapper.getName()
30+
);
31+
}
32+
33+
@Test
34+
public void createWithInstance() {
35+
TaskActivityContext mockContext = mock(TaskActivityContext.class);
36+
WorkflowActivityInstanceWrapper<TestActivity> wrapper = new WorkflowActivityInstanceWrapper<>(new TestActivity());
37+
38+
when(mockContext.getInput(String.class)).thenReturn("Hello");
39+
when(mockContext.getName()).thenReturn("TestActivityContext");
40+
41+
Object result = wrapper.create().run(mockContext);
42+
43+
verify(mockContext, times(1)).getInput(String.class);
44+
assertEquals("Hello world! from TestActivityContext", result);
45+
}
46+
}

sdk-workflows/src/test/java/io/dapr/workflows/runtime/WorkflowWrapperTest.java sdk-workflows/src/test/java/io/dapr/workflows/runtime/WorkflowClassWrapperTest.java

+9-8
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,19 @@
1313

1414
package io.dapr.workflows.runtime;
1515

16-
1716
import com.microsoft.durabletask.TaskOrchestrationContext;
1817
import io.dapr.workflows.Workflow;
1918
import io.dapr.workflows.WorkflowContext;
2019
import io.dapr.workflows.WorkflowStub;
21-
import org.junit.jupiter.api.Assertions;
2220
import org.junit.jupiter.api.Test;
2321

22+
import static org.junit.jupiter.api.Assertions.assertEquals;
2423
import static org.mockito.Mockito.mock;
2524
import static org.mockito.Mockito.times;
2625
import static org.mockito.Mockito.verify;
2726
import static org.mockito.Mockito.when;
2827

29-
public class WorkflowWrapperTest {
28+
public class WorkflowClassWrapperTest {
3029
public static class TestWorkflow implements Workflow {
3130
@Override
3231
public WorkflowStub create() {
@@ -36,20 +35,22 @@ public WorkflowStub create() {
3635

3736
@Test
3837
public void getName() {
39-
WorkflowWrapper<TestWorkflow> wrapper = new WorkflowWrapper<>(TestWorkflow.class);
40-
Assertions.assertEquals(
41-
"io.dapr.workflows.runtime.WorkflowWrapperTest.TestWorkflow",
38+
WorkflowClassWrapper<TestWorkflow> wrapper = new WorkflowClassWrapper<>(TestWorkflow.class);
39+
40+
assertEquals(
41+
"io.dapr.workflows.runtime.WorkflowClassWrapperTest.TestWorkflow",
4242
wrapper.getName()
4343
);
4444
}
4545

4646
@Test
4747
public void createWithClass() {
4848
TaskOrchestrationContext mockContext = mock(TaskOrchestrationContext.class);
49-
WorkflowWrapper<TestWorkflow> wrapper = new WorkflowWrapper<>(TestWorkflow.class);
49+
WorkflowClassWrapper<TestWorkflow> wrapper = new WorkflowClassWrapper<>(TestWorkflow.class);
50+
5051
when(mockContext.getInstanceId()).thenReturn("uuid");
5152
wrapper.create().run(mockContext);
5253
verify(mockContext, times(1)).getInstanceId();
5354
}
5455

55-
}
56+
}

0 commit comments

Comments
 (0)