public Promise<String> startChildWorkflow(String workflow, String version, String input) {
   StartChildWorkflowExecutionParameters parameters = new StartChildWorkflowExecutionParameters();
   WorkflowType workflowType = new WorkflowType().withName(workflow).withVersion(version);
   parameters.setWorkflowType(workflowType);
   parameters.setInput(input);
   Settable<StartChildWorkflowReply> reply = new Settable<StartChildWorkflowReply>();
   Settable<String> result = new Settable<String>();
   startChildWorkflow(parameters, reply, result);
   return result;
 }
 @Override
 protected void doCatch(Throwable e) throws Throwable {
   failed = true;
   if (e instanceof WorkflowException) {
     WorkflowException we = (WorkflowException) e;
     throw new ChildWorkflowFailedException(
         0, childExecution, parameters.getWorkflowType(), e.getMessage(), we.getDetails());
   } else if (e instanceof CancellationException) {
     throw e;
   }
   // Unless there is problem in the framework or generic workflow implementation this shouldn't
   // be executed
   Exception failure =
       new ChildWorkflowFailedException(
           0, childExecution, parameters.getWorkflowType(), e.getMessage(), "null");
   failure.initCause(e);
   throw failure;
 }
  private void startChildWorkflow(
      final StartChildWorkflowExecutionParameters parameters,
      final Settable<StartChildWorkflowReply> reply,
      final Settable<String> result) {
    String workflowId = parameters.getWorkflowId();
    WorkflowType workflowType = parameters.getWorkflowType();
    WorkflowExecution childExecution = new WorkflowExecution();
    final String runId = UUID.randomUUID().toString();
    // TODO: Validate parameters against registration options to find missing timeouts or other
    // options
    try {
      DecisionContext parentDecisionContext = decisionContextProvider.getDecisionContext();
      if (workflowId == null) {
        workflowId =
            decisionContextProvider.getDecisionContext().getWorkflowClient().generateUniqueId();
      }
      childExecution.setWorkflowId(workflowId);
      childExecution.setRunId(runId);

      final GenericActivityClient activityClient = parentDecisionContext.getActivityClient();
      final WorkflowClock workflowClock = parentDecisionContext.getWorkflowClock();
      WorkflowDefinitionFactory factory;
      if (factoryFactory == null) {
        throw new IllegalStateException("required property factoryFactory is null");
      }
      factory = factoryFactory.getWorkflowDefinitionFactory(workflowType);
      if (factory == null) {
        String cause =
            StartChildWorkflowExecutionFailedCause.WORKFLOW_TYPE_DOES_NOT_EXIST.toString();
        throw new StartChildWorkflowFailedException(0, childExecution, workflowType, cause);
      }
      TestWorkflowContext workflowContext = new TestWorkflowContext();
      workflowContext.setWorkflowExecution(childExecution);
      workflowContext.setWorkflowType(parameters.getWorkflowType());
      workflowContext.setParentWorkflowExecution(
          parentDecisionContext.getWorkflowContext().getWorkflowExecution());
      workflowContext.setTagList(parameters.getTagList());
      workflowContext.setTaskList(parameters.getTaskList());
      DecisionContext context =
          new TestDecisionContext(
              activityClient, TestGenericWorkflowClient.this, workflowClock, workflowContext);
      // this, parameters, childExecution, workflowClock, activityClient);
      final WorkflowDefinition childWorkflowDefinition = factory.getWorkflowDefinition(context);
      final ChildWorkflowTryCatchFinally tryCatch =
          new ChildWorkflowTryCatchFinally(
              parameters, childExecution, childWorkflowDefinition, context, result);
      workflowContext.setRootTryCatch(tryCatch);
      ChildWorkflowTryCatchFinally currentRun = workflowExecutions.get(workflowId);
      if (currentRun != null) {
        String cause = StartChildWorkflowExecutionFailedCause.WORKFLOW_ALREADY_RUNNING.toString();
        throw new StartChildWorkflowFailedException(0, childExecution, workflowType, cause);
      }
      workflowExecutions.put(workflowId, tryCatch);
      continueAsNewWorkflowExecution(tryCatch, result);
    } catch (StartChildWorkflowFailedException e) {
      throw e;
    } catch (Throwable e) {
      // This cause is chosen to represent internal error for sub-workflow creation
      String cause = StartChildWorkflowExecutionFailedCause.OPEN_CHILDREN_LIMIT_EXCEEDED.toString();
      StartChildWorkflowFailedException failure =
          new StartChildWorkflowFailedException(0, childExecution, workflowType, cause);
      failure.initCause(e);
      throw failure;
    } finally {
      reply.set(new StartChildWorkflowReplyImpl(result, runId));
    }
  }
 @Override
 protected void doTry() throws Throwable {
   executeResult.chain(childWorkflowDefinition.execute(parameters.getInput()));
 }