Skip to main content

Child Workflows - Temporal Java SDK feature guide

This page shows how to do the following:

Start a Child Workflow Execution

How to start a Child Workflow Execution using the Java SDK.

A Child Workflow Execution is a Workflow Execution that is scheduled from within another Workflow using a Child Workflow API.

When using a Child Workflow API, Child Workflow related Events (StartChildWorkflowExecutionInitiated, ChildWorkflowExecutionStarted, ChildWorkflowExecutionCompleted, etc...) are logged in the Workflow Execution Event History.

Always block progress until the ChildWorkflowExecutionStarted Event is logged to the Event History to ensure the Child Workflow Execution has started. After that, Child Workflow Executions may be abandoned using the default Abandon Parent Close Policy set in the Child Workflow Options.

To be sure that the Child Workflow Execution has started, first call the Child Workflow Execution method on the instance of Child Workflow future, which returns a different future.

Then get the value of an object that acts as a proxy for a result that is initially unknown, which is what waits until the Child Workflow Execution has spawned.

The first call to the Child Workflow stub must always be its Workflow method (method annotated with @WorkflowMethod). Similar to Activities, invoking Child Workflow methods can be made synchronous or asynchronous by using Async#function or Async#procedure. The synchronous call blocks until a Child Workflow method completes. The asynchronous call returns a Promise which can be used to wait for the completion of the Child Workflow method, as in the following example:

GreetingChild child = Workflow.newChildWorkflowStub(GreetingChild.class);
Promise<String> greeting = Async.function(child::composeGreeting, "Hello", name);
// ...
greeting.get()

To execute an untyped Child Workflow asynchronously, call executeAsync on the ChildWorkflowStub, as shown in the following example.

//...
ChildWorkflowStub childUntyped =
Workflow.newUntypedChildWorkflowStub(
"GreetingChild", // your workflow type
ChildWorkflowOptions.newBuilder().setWorkflowId("childWorkflow").build());

Promise<String> greeting =
childUntyped.executeAsync(String.class, String.class, "Hello", name);
String result = greeting.get();
//...

The following examples show how to spawn a Child Workflow:

  • Spawn a Child Workflow from a Workflow

    // Child Workflow interface
    @WorkflowInterface
    public interface GreetingChild {
    @WorkflowMethod
    String composeGreeting(String greeting, String name);
    }
    // Child Workflow implementation not shown

    // Parent Workflow implementation
    public class GreetingWorkflowImpl implements GreetingWorkflow {

    @Override
    public String getGreeting(String name) {
    GreetingChild child = Workflow.newChildWorkflowStub(GreetingChild.class);

    // This is a blocking call that returns only after child has completed.
    return child.composeGreeting("Hello", name );
    }
    }
  • Spawn two Child Workflows (with the same type) in parallel:

    // Parent Workflow implementation
    public class GreetingWorkflowImpl implements GreetingWorkflow {

    @Override
    public String getGreeting(String name) {

    // Workflows are stateful, so a new stub must be created for each new child.
    GreetingChild child1 = Workflow.newChildWorkflowStub(GreetingChild.class);
    Promise<String> greeting1 = Async.function(child1::composeGreeting, "Hello", name);

    // Both children will run concurrently.
    GreetingChild child2 = Workflow.newChildWorkflowStub(GreetingChild.class);
    Promise<String> greeting2 = Async.function(child2::composeGreeting, "Bye", name);

    // Do something else here.
    ...
    return "First: " + greeting1.get() + ", second: " + greeting2.get();
    }
    }
  • Send a Signal to a Child Workflow from the parent:

    // Child Workflow interface
    @WorkflowInterface
    public interface GreetingChild {
    @WorkflowMethod
    String composeGreeting(String greeting, String name);

    @SignalMethod
    void updateName(String name);
    }

    // Parent Workflow implementation
    public class GreetingWorkflowImpl implements GreetingWorkflow {

    @Override
    public String getGreeting(String name) {
    GreetingChild child = Workflow.newChildWorkflowStub(GreetingChild.class);
    Promise<String> greeting = Async.function(child::composeGreeting, "Hello", name);
    child.updateName("Temporal");
    return greeting.get();
    }
    }
  • Sending a Query to Child Workflows from within the parent Workflow code is not supported. However, you can send a Query to Child Workflows from Activities using WorkflowClient.

Related reads:

Parent Close Policy

How to set a Parent Close Policy for a Child Workflow using the Java SDK.

A Parent Close Policy determines what happens to a Child Workflow Execution if its Parent changes to a Closed status (Completed, Failed, or Timed Out).

The default Parent Close Policy option is set to terminate the Child Workflow Execution.

Set Parent Close Policy on an instance of ChildWorkflowOptions using ChildWorkflowOptions.newBuilder().setParentClosePolicy.

  • Type: ChildWorkflowOptions.Builder
  • Default: PARENT_CLOSE_POLICY_TERMINATE
 public void parentWorkflow() {
ChildWorkflowOptions options =
ChildWorkflowOptions.newBuilder()
.setParentClosePolicy(ParentClosePolicy.PARENT_CLOSE_POLICY_ABANDON)
.build();
MyChildWorkflow child = Workflow.newChildWorkflowStub(MyChildWorkflow.class, options);
Async.procedure(child::<workflowMethod>, <args>...);
Promise<WorkflowExecution> childExecution = Workflow.getWorkflowExecution(child);
// Wait for child to start
childExecution.get()
}

In this example, we are:

  1. Setting ChildWorkflowOptions.ParentClosePolicy to ABANDON when creating a Child Workflow stub.
  2. Starting Child Workflow Execution asynchronously using Async.function or Async.procedure.
  3. Calling Workflow.getWorkflowExecution(…) on the child stub.
  4. Waiting for the Promise returned by getWorkflowExecution to complete. This indicates whether the Child Workflow started successfully (or failed).
  5. Completing parent Workflow Execution asynchronously.

Steps 3 and 4 are needed to ensure that a Child Workflow Execution starts before the parent closes. If the parent initiates a Child Workflow Execution and then completes immediately after, the Child Workflow will never execute.