Skip to content

Commit 4d6427d

Browse files
authored
Example with untyped child workflow started async (temporalio#543)
* wip * wip * wip * wip * fix package name
1 parent 50a6ebd commit 4d6427d

10 files changed

Lines changed: 389 additions & 2 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ See the README.md file in each main sample directory for cut/paste Gradle comman
9393

9494
#### API demonstrations
9595

96+
- [**Async Untyped Child Workflow**](/core/src/main/java/io/temporal/samples/asyncuntypedchild): Demonstrates how to invoke an untyped child workflow async, that can complete after parent workflow is already completed.
97+
9698
- [**Updatable Timer**](/core/src/main/java/io/temporal/samples/updatabletimer): Demonstrates the use of a helper class which relies on `Workflow.await` to implement a blocking sleep that can be updated at any moment.
9799

98100
- [**Workflow Count Interceptor**](/core/src/main/java/io/temporal/samples/countinterceptor): Demonstrates how to create and register a simple Workflow Count Interceptor.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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.asyncuntypedchild;
21+
22+
import io.temporal.workflow.WorkflowInterface;
23+
import io.temporal.workflow.WorkflowMethod;
24+
25+
/**
26+
* Define the child workflow Interface. It must contain one method annotated with @WorkflowMethod
27+
*
28+
* @see WorkflowInterface
29+
* @see WorkflowMethod
30+
*/
31+
@WorkflowInterface
32+
public interface ChildWorkflow {
33+
34+
/**
35+
* Define the child workflow method. This method is executed when the workflow is started. The
36+
* workflow completes when the workflow method finishes execution.
37+
*/
38+
@WorkflowMethod
39+
String composeGreeting(String greeting, String name);
40+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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.asyncuntypedchild;
21+
22+
import io.temporal.workflow.Workflow;
23+
24+
/**
25+
* Define the parent workflow implementation. It implements the getGreeting workflow method
26+
*
27+
* <p>Note that a workflow implementation must always be public for the Temporal library to be able
28+
* to create its instances.
29+
*/
30+
public class ChildWorkflowImpl implements ChildWorkflow {
31+
32+
@Override
33+
public String composeGreeting(String greeting, String name) {
34+
35+
// Sleep for 2 seconds to ensure the child completes after the parent.
36+
Workflow.sleep(2000);
37+
38+
return greeting + " " + name + "!";
39+
}
40+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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.asyncuntypedchild;
21+
22+
import io.temporal.workflow.WorkflowInterface;
23+
import io.temporal.workflow.WorkflowMethod;
24+
25+
/**
26+
* Define the parent workflow interface. It must contain one method annotated with @WorkflowMethod
27+
*
28+
* @see WorkflowInterface
29+
* @see WorkflowMethod
30+
*/
31+
@WorkflowInterface
32+
public interface ParentWorkflow {
33+
34+
/**
35+
* Define the parent workflow method. This method is executed when the workflow is started. The
36+
* workflow completes when the workflow method finishes execution.
37+
*/
38+
@WorkflowMethod
39+
String getGreeting(String name);
40+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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.asyncuntypedchild;
21+
22+
import static io.temporal.samples.asyncuntypedchild.Starter.WORKFLOW_ID;
23+
24+
import io.temporal.api.common.v1.WorkflowExecution;
25+
import io.temporal.api.enums.v1.ParentClosePolicy;
26+
import io.temporal.workflow.*;
27+
28+
// Define the parent workflow implementation. It implements the getGreeting workflow method
29+
public class ParentWorkflowImpl implements ParentWorkflow {
30+
31+
@Override
32+
public String getGreeting(String name) {
33+
/*
34+
* Define the child workflow stub. Since workflows are stateful,
35+
* a new stub must be created for each child workflow.
36+
*/
37+
ChildWorkflowStub child =
38+
Workflow.newUntypedChildWorkflowStub(
39+
ChildWorkflow.class.getSimpleName(),
40+
ChildWorkflowOptions.newBuilder()
41+
.setParentClosePolicy(ParentClosePolicy.PARENT_CLOSE_POLICY_ABANDON)
42+
.setWorkflowId("Child_of_" + WORKFLOW_ID)
43+
.build());
44+
45+
/*
46+
* Invoke the child workflows composeGreeting workflow method async.
47+
* This call is non-blocking and returns immediately returning a {@link io.temporal.workflow.Promise},
48+
* you can invoke `get()` on the returned promise to wait for the child workflow result.
49+
*/
50+
child.executeAsync(String.class, "Hello", name);
51+
52+
// Wait for the child workflow to start before returning the result
53+
Promise<WorkflowExecution> childExecution = child.getExecution();
54+
WorkflowExecution childWorkflowExecution = childExecution.get();
55+
56+
// return the child workflowId
57+
return childWorkflowExecution.getWorkflowId();
58+
}
59+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Async Child Workflow execution
2+
3+
The sample demonstrates shows how to invoke an Untyped Child Workflow asynchronously.
4+
The Child Workflow continues running for some time after the Parent Workflow completes.
5+
6+
```bash
7+
./gradlew -q execute -PmainClass=io.temporal.samples.asyncuntypedchild.Starter
8+
```
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
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.asyncuntypedchild;
21+
22+
import io.temporal.client.WorkflowClient;
23+
import io.temporal.client.WorkflowOptions;
24+
import io.temporal.serviceclient.WorkflowServiceStubs;
25+
import io.temporal.worker.Worker;
26+
import io.temporal.worker.WorkerFactory;
27+
28+
/**
29+
* Sample Temporal Workflow Definition that demonstrates the execution of a Child Workflow. Child
30+
* workflows allow you to group your Workflow logic into small logical and reusable units that solve
31+
* a particular problem. They can be typically reused by multiple other Workflows.
32+
*/
33+
public class Starter {
34+
35+
static final String WORKFLOW_ID = "ParentWithAsyncUntypedChild";
36+
37+
static final String TASK_QUEUE = WORKFLOW_ID + "Queue";
38+
39+
/**
40+
* With the workflow, and child workflow defined, we can now start execution. The main method is
41+
* the workflow starter.
42+
*/
43+
public static void main(String[] args) {
44+
45+
// Get a Workflow service stub.
46+
WorkflowServiceStubs service = WorkflowServiceStubs.newLocalServiceStubs();
47+
48+
/*
49+
* Get a Workflow service client which can be used to start, Signal, and Query Workflow Executions.
50+
*/
51+
WorkflowClient client = WorkflowClient.newInstance(service);
52+
53+
/*
54+
* Define the workflow factory. It is used to create workflow workers for a specific task queue.
55+
*/
56+
WorkerFactory factory = WorkerFactory.newInstance(client);
57+
58+
/*
59+
* Define the workflow worker. Workflow workers listen to a defined task queue and process
60+
* workflows and activities.
61+
*/
62+
Worker worker = factory.newWorker(TASK_QUEUE);
63+
64+
/*
65+
* Register the parent and child workflow implementation with the worker.
66+
* Since workflows are stateful in nature,
67+
* we need to register the workflow types.
68+
*/
69+
worker.registerWorkflowImplementationTypes(ParentWorkflowImpl.class, ChildWorkflowImpl.class);
70+
71+
/*
72+
* Start all the workers registered for a specific task queue.
73+
* The started workers then start polling for workflows and activities.
74+
*/
75+
factory.start();
76+
77+
// Start a workflow execution. Usually this is done from another program.
78+
// Uses task queue from the GreetingWorkflow @WorkflowMethod annotation.
79+
80+
// Create our parent workflow client stub. It is used to start the parent workflow execution.
81+
ParentWorkflow workflow =
82+
client.newWorkflowStub(
83+
ParentWorkflow.class,
84+
WorkflowOptions.newBuilder()
85+
.setWorkflowId(WORKFLOW_ID)
86+
.setTaskQueue(TASK_QUEUE)
87+
.build());
88+
89+
// Execute our parent workflow and wait for it to complete, it returns the child workflow id.
90+
String childWorkflowId = workflow.getGreeting("World");
91+
System.out.println("Child WorkflowId=[" + childWorkflowId + "] started in abandon mode");
92+
93+
String childResult = client.newUntypedWorkflowStub(childWorkflowId).getResult(String.class);
94+
95+
System.out.println("Result from child workflow = " + childResult);
96+
97+
System.exit(0);
98+
}
99+
}

0 commit comments

Comments
 (0)