Skip to content

Commit a47b3b6

Browse files
authored
Added HelloAwait sample (#565)
* Added HelloAwait sample * missed changes
1 parent ff8bdb4 commit a47b3b6

3 files changed

Lines changed: 264 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ See the README.md file in each main sample directory for cut/paste Gradle comman
5050
- [**HelloActivityRetry**](/core/src/main/java/io/temporal/samples/hello/HelloActivityRetry.java): Demonstrates how to Retry an Activity Execution.
5151
- [**HelloActivityExclusiveChoice**](/core/src/main/java/io/temporal/samples/hello/HelloActivityExclusiveChoice.java): Demonstrates how to execute Activities based on dynamic input.
5252
- [**HelloAsync**](/core/src/main/java/io/temporal/samples/hello/HelloAsync.java): Demonstrates how to execute Activities asynchronously and wait for them using Promises.
53+
- [**HelloAwait**](/core/src/main/java/io/temporal/samples/hello/HelloAwait.java): Demonstrates how to use Await statement to wait for a condition.
5354
- [**HelloParallelActivity**](/core/src/main/java/io/temporal/samples/hello/HelloParallelActivity.java): Demonstrates how to execute multiple Activities in parallel, asynchronously, and wait for them using `Promise.allOf`.
5455
- [**HelloAsyncActivityCompletion**](/core/src/main/java/io/temporal/samples/hello/HelloAsyncActivityCompletion.java): Demonstrates how to complete an Activity Execution asynchronously.
5556
- [**HelloAsyncLambda**](/core/src/main/java/io/temporal/samples/hello/HelloAsyncLambda.java): Demonstrates how to execute part of a Workflow asynchronously in a separate task (thread).
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
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.client.WorkflowClient;
23+
import io.temporal.client.WorkflowOptions;
24+
import io.temporal.client.WorkflowStub;
25+
import io.temporal.failure.ApplicationFailure;
26+
import io.temporal.serviceclient.WorkflowServiceStubs;
27+
import io.temporal.worker.Worker;
28+
import io.temporal.worker.WorkerFactory;
29+
import io.temporal.workflow.SignalMethod;
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+
* Sample Temporal workflow that demonstrates how to use workflow await methods to wait up to a
37+
* specified timeout for a condition updated from a signal handler.
38+
*/
39+
public class HelloAwait {
40+
41+
// Define the task queue name
42+
static final String TASK_QUEUE = "HelloAwaitTaskQueue";
43+
44+
// Define the workflow unique id
45+
static final String WORKFLOW_ID = "HelloAwaitWorkflow";
46+
47+
/**
48+
* The Workflow Definition's Interface must contain one method annotated with @WorkflowMethod.
49+
*
50+
* <p>Workflow Definitions should not contain any heavyweight computations, non-deterministic
51+
* code, network calls, database operations, etc. Those things should be handled by the
52+
* Activities.
53+
*
54+
* @see WorkflowInterface
55+
* @see WorkflowMethod
56+
*/
57+
@WorkflowInterface
58+
public interface GreetingWorkflow {
59+
/**
60+
* This is the method that is executed when the Workflow Execution is started. The Workflow
61+
* Execution completes when this method finishes execution.
62+
*/
63+
@WorkflowMethod
64+
String getGreeting();
65+
66+
// Define the workflow waitForName signal method. This method is executed when the workflow
67+
// receives a "WaitForName" signal.
68+
@SignalMethod
69+
void waitForName(String name);
70+
}
71+
72+
// Define the workflow implementation which implements the getGreetings workflow method.
73+
public static class GreetingWorkflowImpl implements GreetingWorkflow {
74+
75+
private String name;
76+
77+
@Override
78+
public String getGreeting() {
79+
boolean ok = Workflow.await(Duration.ofSeconds(10), () -> name != null);
80+
if (ok) {
81+
return "Hello " + name + "!";
82+
} else {
83+
// To fail workflow use ApplicationFailure. Any other exception would cause workflow to
84+
// stall, not to fail.
85+
throw ApplicationFailure.newFailure(
86+
"WaitForName signal is not received within 10 seconds.", "signal-timeout");
87+
}
88+
}
89+
90+
@Override
91+
public void waitForName(String name) {
92+
this.name = name;
93+
}
94+
}
95+
96+
/**
97+
* With the Workflow and Activities defined, we can now start execution. The main method starts
98+
* the worker and then the workflow.
99+
*/
100+
public static void main(String[] args) throws Exception {
101+
102+
// Get a Workflow service stub.
103+
WorkflowServiceStubs service = WorkflowServiceStubs.newLocalServiceStubs();
104+
105+
/*
106+
* Get a Workflow service client which can be used to start, Await, and Query Workflow Executions.
107+
*/
108+
WorkflowClient client = WorkflowClient.newInstance(service);
109+
110+
/*
111+
* Define the workflow factory. It is used to create workflow workers for a specific task queue.
112+
*/
113+
WorkerFactory factory = WorkerFactory.newInstance(client);
114+
115+
/*
116+
* Define the workflow worker. Workflow workers listen to a defined task queue and process
117+
* workflows and activities.
118+
*/
119+
Worker worker = factory.newWorker(TASK_QUEUE);
120+
121+
/*
122+
* Register the workflow implementation with the worker.
123+
* Workflow implementations must be known to the worker at runtime in
124+
* order to dispatch workflow tasks.
125+
*/
126+
worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class);
127+
128+
/*
129+
* Start all the workers registered for a specific task queue.
130+
* The started workers then start polling for workflows and activities.
131+
*/
132+
factory.start();
133+
134+
// Create the workflow options
135+
WorkflowOptions workflowOptions =
136+
WorkflowOptions.newBuilder().setTaskQueue(TASK_QUEUE).setWorkflowId(WORKFLOW_ID).build();
137+
138+
// Create the workflow client stub. It is used to start the workflow execution.
139+
GreetingWorkflow workflow = client.newWorkflowStub(GreetingWorkflow.class, workflowOptions);
140+
141+
// Start workflow asynchronously and call its getGreeting workflow method
142+
WorkflowClient.start(workflow::getGreeting);
143+
144+
// After start for getGreeting returns, the workflow is guaranteed to be started.
145+
// Send WaitForName signal.
146+
workflow.waitForName("World");
147+
148+
/*
149+
* Here we create a new untyped workflow stub using the same workflow id.
150+
* The untyped stub is a convenient way to wait for a workflow result.
151+
*/
152+
WorkflowStub workflowById = client.newUntypedWorkflowStub(WORKFLOW_ID);
153+
154+
String greeting = workflowById.getResult(String.class);
155+
156+
System.out.println(greeting);
157+
System.exit(0);
158+
}
159+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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 org.junit.Assert.assertEquals;
23+
import static org.junit.Assert.fail;
24+
25+
import io.temporal.client.WorkflowClient;
26+
import io.temporal.client.WorkflowException;
27+
import io.temporal.client.WorkflowOptions;
28+
import io.temporal.client.WorkflowStub;
29+
import io.temporal.failure.ApplicationFailure;
30+
import io.temporal.samples.hello.HelloAwait.GreetingWorkflow;
31+
import io.temporal.testing.TestWorkflowRule;
32+
import java.time.Duration;
33+
import org.junit.Rule;
34+
import org.junit.Test;
35+
36+
/** Unit test for {@link HelloAwait}. Doesn't use an external Temporal service. */
37+
public class HelloAwaitTest {
38+
39+
private final String WORKFLOW_ID = "WORKFLOW1";
40+
41+
@Rule
42+
public TestWorkflowRule testWorkflowRule =
43+
TestWorkflowRule.newBuilder().setWorkflowTypes(HelloAwait.GreetingWorkflowImpl.class).build();
44+
45+
@Test
46+
public void testAwaitSignal() {
47+
// Get a workflow stub using the same task queue the worker uses.
48+
WorkflowOptions workflowOptions =
49+
WorkflowOptions.newBuilder()
50+
.setTaskQueue(testWorkflowRule.getTaskQueue())
51+
.setWorkflowId(WORKFLOW_ID)
52+
.build();
53+
54+
GreetingWorkflow workflow =
55+
testWorkflowRule
56+
.getWorkflowClient()
57+
.newWorkflowStub(GreetingWorkflow.class, workflowOptions);
58+
59+
// Start workflow asynchronously to not use another thread to await.
60+
WorkflowClient.start(workflow::getGreeting);
61+
workflow.waitForName("World");
62+
// So we can send a await to it using workflow stub immediately.
63+
// But just to demonstrate the unit testing of a long running workflow adding a long sleep here.
64+
// testWorkflowRule.getTestEnvironment().sleep(Duration.ofSeconds(30));
65+
66+
WorkflowStub workflowById =
67+
testWorkflowRule.getWorkflowClient().newUntypedWorkflowStub(WORKFLOW_ID);
68+
69+
String greeting = workflowById.getResult(String.class);
70+
assertEquals("Hello World!", greeting);
71+
}
72+
73+
@Test
74+
public void testAwaitTimeout() {
75+
// Get a workflow stub using the same task queue the worker uses.
76+
WorkflowOptions workflowOptions =
77+
WorkflowOptions.newBuilder()
78+
.setTaskQueue(testWorkflowRule.getTaskQueue())
79+
.setWorkflowId(WORKFLOW_ID)
80+
.build();
81+
82+
GreetingWorkflow workflow =
83+
testWorkflowRule
84+
.getWorkflowClient()
85+
.newWorkflowStub(GreetingWorkflow.class, workflowOptions);
86+
87+
// Start workflow asynchronously to not use another thread to wait.
88+
WorkflowClient.start(workflow::getGreeting);
89+
90+
// Skip time to force Await timeout
91+
testWorkflowRule.getTestEnvironment().sleep(Duration.ofSeconds(30));
92+
93+
WorkflowStub workflowById =
94+
testWorkflowRule.getWorkflowClient().newUntypedWorkflowStub(WORKFLOW_ID);
95+
96+
try {
97+
workflowById.getResult(String.class);
98+
fail("not reachable");
99+
} catch (WorkflowException e) {
100+
ApplicationFailure applicationFailure = (ApplicationFailure) e.getCause();
101+
assertEquals("signal-timeout", applicationFailure.getType());
102+
}
103+
}
104+
}

0 commit comments

Comments
 (0)