Skip to content

Commit 5120387

Browse files
authored
Added HelloPolymorphicActivity (#14)
1 parent a7e88a6 commit 5120387

2 files changed

Lines changed: 237 additions & 0 deletions

File tree

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
* Copyright (c) 2020 Temporal Technologies, Inc. All Rights Reserved
3+
*
4+
* Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5+
*
6+
* Modifications copyright (C) 2017 Uber Technologies, Inc.
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not
9+
* use this file except in compliance with the License. A copy of the License is
10+
* located at
11+
*
12+
* http://aws.amazon.com/apache2.0
13+
*
14+
* or in the "license" file accompanying this file. This file is distributed on
15+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
16+
* express or implied. See the License for the specific language governing
17+
* permissions and limitations under the License.
18+
*/
19+
20+
package io.temporal.samples.hello;
21+
22+
import io.temporal.activity.ActivityInterface;
23+
import io.temporal.activity.ActivityMethod;
24+
import io.temporal.activity.ActivityOptions;
25+
import io.temporal.client.WorkflowClient;
26+
import io.temporal.client.WorkflowOptions;
27+
import io.temporal.serviceclient.WorkflowServiceStubs;
28+
import io.temporal.worker.Worker;
29+
import io.temporal.worker.WorkerFactory;
30+
import io.temporal.workflow.Workflow;
31+
import io.temporal.workflow.WorkflowInterface;
32+
import io.temporal.workflow.WorkflowMethod;
33+
import java.time.Duration;
34+
35+
/**
36+
* Demonstrates activities that extend a common interface. The core idea is that an activity
37+
* interface annotated with {@literal @}{@link ActivityInterface} enumerates all the methods it
38+
* inherited and declared and generates an activity for each of them. To avoid collisions in
39+
* activity names (which are by default just method names) the {@link
40+
* ActivityInterface#namePrefix()} or {@link ActivityMethod#name()} parameters should be used.
41+
*/
42+
public class HelloPolymorphicActivity {
43+
44+
static final String TASK_LIST = "HelloPolymorphicActivity";
45+
46+
@WorkflowInterface
47+
public interface GreetingWorkflow {
48+
@WorkflowMethod
49+
String getGreeting(String name);
50+
}
51+
52+
/** Base activity interface. Note that it must not be annotated with @ActivityInterface. */
53+
public interface GreetingActivity {
54+
String composeGreeting(String name);
55+
}
56+
57+
/**
58+
* Activity definition interface. Must redefine the name of the composeGreeting activity to avoid
59+
* collision.
60+
*/
61+
@ActivityInterface(namePrefix = "Hello_")
62+
public interface HelloActivity extends GreetingActivity {
63+
@Override
64+
String composeGreeting(String name);
65+
}
66+
67+
/**
68+
* Activity definition interface. Must redefine the name of the composeGreeting activity to avoid
69+
* collision.
70+
*/
71+
@ActivityInterface(namePrefix = "Bye_")
72+
public interface ByeActivity extends GreetingActivity {
73+
@Override
74+
String composeGreeting(String name);
75+
}
76+
77+
public static class GreetingWorkflowImpl implements GreetingWorkflow {
78+
79+
private final GreetingActivity[] activities =
80+
new GreetingActivity[] {
81+
Workflow.newActivityStub(
82+
HelloActivity.class,
83+
ActivityOptions.newBuilder()
84+
.setScheduleToCloseTimeout(Duration.ofSeconds(2))
85+
.build()),
86+
Workflow.newActivityStub(
87+
ByeActivity.class,
88+
ActivityOptions.newBuilder().setScheduleToCloseTimeout(Duration.ofSeconds(2)).build())
89+
};
90+
91+
@Override
92+
public String getGreeting(String name) {
93+
StringBuilder result = new StringBuilder();
94+
for (GreetingActivity activity : activities) {
95+
result.append(activity.composeGreeting(name));
96+
result.append('\n');
97+
}
98+
return result.toString();
99+
}
100+
}
101+
102+
static class HelloActivityImpl implements HelloActivity {
103+
@Override
104+
public String composeGreeting(String name) {
105+
return "Hello " + name + "!";
106+
}
107+
}
108+
109+
static class ByeActivityImpl implements ByeActivity {
110+
@Override
111+
public String composeGreeting(String name) {
112+
return "Bye " + name + "!";
113+
}
114+
}
115+
116+
public static void main(String[] args) {
117+
// gRPC stubs wrapper that talks to the local docker instance of temporal service.
118+
WorkflowServiceStubs service = WorkflowServiceStubs.newInstance();
119+
// client that can be used to start and signal workflows
120+
WorkflowClient client = WorkflowClient.newInstance(service);
121+
122+
// worker factory that can be used to create workers for specific task lists
123+
WorkerFactory factory = WorkerFactory.newInstance(client);
124+
// Worker that listens on a task list and hosts both workflow and activity implementations.
125+
Worker worker = factory.newWorker(TASK_LIST);
126+
// Workflows are stateful. So you need a type to create instances.
127+
worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class);
128+
// Activities are stateless and thread safe. So a shared instance is used.
129+
worker.registerActivitiesImplementations(new HelloActivityImpl(), new ByeActivityImpl());
130+
// Start listening to the workflow and activity task lists.
131+
factory.start();
132+
133+
// Start a workflow execution. Usually this is done from another program.
134+
// Uses task list from the GreetingWorkflow @WorkflowMethod annotation.
135+
GreetingWorkflow workflow =
136+
client.newWorkflowStub(
137+
GreetingWorkflow.class, WorkflowOptions.newBuilder().setTaskList(TASK_LIST).build());
138+
// Execute a workflow waiting for it to complete. See {@link
139+
// io.temporal.samples.hello.HelloSignal}
140+
// for an example of starting workflow without waiting synchronously for its result.
141+
String greeting = workflow.getGreeting("World");
142+
System.out.println(greeting);
143+
System.exit(0);
144+
}
145+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright (c) 2020 Temporal Technologies, Inc. All Rights Reserved
3+
*
4+
* Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5+
*
6+
* Modifications copyright (C) 2017 Uber Technologies, Inc.
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not
9+
* use this file except in compliance with the License. A copy of the License is
10+
* located at
11+
*
12+
* http://aws.amazon.com/apache2.0
13+
*
14+
* or in the "license" file accompanying this file. This file is distributed on
15+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
16+
* express or implied. See the License for the specific language governing
17+
* permissions and limitations under the License.
18+
*/
19+
20+
package io.temporal.samples.hello;
21+
22+
import static io.temporal.samples.hello.HelloActivity.TASK_LIST;
23+
import static org.junit.Assert.assertEquals;
24+
import static org.mockito.Mockito.mock;
25+
import static org.mockito.Mockito.when;
26+
27+
import io.temporal.client.WorkflowClient;
28+
import io.temporal.client.WorkflowOptions;
29+
import io.temporal.samples.hello.HelloPolymorphicActivity.ByeActivityImpl;
30+
import io.temporal.samples.hello.HelloPolymorphicActivity.GreetingWorkflow;
31+
import io.temporal.samples.hello.HelloPolymorphicActivity.GreetingWorkflowImpl;
32+
import io.temporal.samples.hello.HelloPolymorphicActivity.HelloActivityImpl;
33+
import io.temporal.testing.TestWorkflowEnvironment;
34+
import io.temporal.worker.Worker;
35+
import org.junit.After;
36+
import org.junit.Before;
37+
import org.junit.Test;
38+
39+
/** Unit test for {@link HelloActivity}. Doesn't use an external Temporal service. */
40+
public class HelloPolymorphicActivityTest {
41+
42+
private TestWorkflowEnvironment testEnv;
43+
private Worker worker;
44+
private WorkflowClient client;
45+
46+
@Before
47+
public void setUp() {
48+
testEnv = TestWorkflowEnvironment.newInstance();
49+
worker = testEnv.newWorker(TASK_LIST);
50+
worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class);
51+
52+
client = testEnv.getWorkflowClient();
53+
}
54+
55+
@After
56+
public void tearDown() {
57+
testEnv.close();
58+
}
59+
60+
@Test
61+
public void testActivityImpl() {
62+
worker.registerActivitiesImplementations(new HelloActivityImpl(), new ByeActivityImpl());
63+
testEnv.start();
64+
65+
// Get a workflow stub using the same task list the worker uses.
66+
GreetingWorkflow workflow =
67+
client.newWorkflowStub(
68+
GreetingWorkflow.class, WorkflowOptions.newBuilder().setTaskList(TASK_LIST).build());
69+
// Execute a workflow waiting for it to complete.
70+
String greeting = workflow.getGreeting("World");
71+
assertEquals("Hello World!\nBye World!\n", greeting);
72+
}
73+
74+
@Test
75+
public void testMockedActivity() {
76+
HelloPolymorphicActivity.HelloActivity hello =
77+
mock(HelloPolymorphicActivity.HelloActivity.class);
78+
when(hello.composeGreeting("World")).thenReturn("Hello World!");
79+
HelloPolymorphicActivity.ByeActivity bye = mock(HelloPolymorphicActivity.ByeActivity.class);
80+
when(bye.composeGreeting("World")).thenReturn("Bye World!");
81+
worker.registerActivitiesImplementations(hello, bye);
82+
testEnv.start();
83+
84+
// Get a workflow stub using the same task list the worker uses.
85+
GreetingWorkflow workflow =
86+
client.newWorkflowStub(
87+
GreetingWorkflow.class, WorkflowOptions.newBuilder().setTaskList(TASK_LIST).build());
88+
// Execute a workflow waiting for it to complete.
89+
String greeting = workflow.getGreeting("World");
90+
assertEquals("Hello World!\nBye World!\n", greeting);
91+
}
92+
}

0 commit comments

Comments
 (0)