

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# HelloWorldWorkflowAsync 应用程序
<a name="getting-started-example-helloworldworkflowasync"></a>

有时，最好让工作流程在本地执行某些任务，而不是使用活动。不过，工作流程任务通常涉及处理 `Promise<T>` 对象表示的值。如果将 `Promise<T>` 对象传递给一个同步工作流程方法，该方法将立即执行，但无法访问 `Promise<T>` 对象的值，直到该对象准备就绪。您可以轮询 `Promise<T>.isReady`，直到它返回 `true`，但这样做的效率非常低，并且该方法可能会阻止很长时间。更好的方法是使用*异步方法*。

异步方法的实现与标准方法类似，通常是作为工作流实现类的成员，并在工作流实现的上下文中运行。您可以应用 `@Asynchronous` 注释将其指定为异步方法，这会指示框架像对待活动一样处理它。
+ 在工作流程实现调用异步方法时，它将立即返回。异步方法通常返回一个 `Promise<T>` 对象，在该方法完成时，该对象将变为就绪状态。
+ 如果为异步方法传递一个或多个 `Promise<T>` 对象，它将推迟执行，直到所有输入对象准备就绪。因此，异步方法可以访问其输入 `Promise<T>` 值，而不会出现引发异常的风险。

**注意**  
由于 for Java 执行工作流程的方式，异步方法通常会执行多次，因此只能将它们用于快速的低开销任务。 AWS Flow Framework 您应该使用活动执行时间较长的任务，如规模较大的计算。有关更多信息，请参阅 [AWS Flow Framework 基本概念：分布式执行](awsflow-basics-distributed-execution.md)。

本主题是的演练 HelloWorldWorkflowAsync，它是一个修改后的版本 HelloWorldWorkflow ，它用异步方法替换了其中一个活动。要实现该应用程序，请创建 HelloWorld 的副本。 HelloWorldWorkflow 打包到你的项目目录中然后把它命名为 HelloWorld。 HelloWorldWorkflowAsync。

**注意**  
本主题以 [HelloWorld 应用程序](getting-started-example-helloworld.md)和 [HelloWorldWorkflow 应用程序](getting-started-example-helloworldworkflow.md)主题中提供的概念和文件为基础。熟悉这些文件和中介绍的概念，这些主题，然后再继续。

以下各节介绍如何修改原始 HelloWorldWorkflow 代码以使用异步方法。

## HelloWorldWorkflowAsync 活动实施
<a name="getting-started-example-helloworldworkflowasync.activities"></a>

HelloWorldWorkflowAsync 在中实现其活动工作者接口`GreeterActivities`，如下所示：

```
import com.amazonaws.services.simpleworkflow.flow.annotations.Activities;
import com.amazonaws.services.simpleworkflow.flow.annotations.ActivityRegistrationOptions;

@Activities(version="2.0")
@ActivityRegistrationOptions(defaultTaskScheduleToStartTimeoutSeconds = 300,
                             defaultTaskStartToCloseTimeoutSeconds = 10)
public interface GreeterActivities {
   public String getName();
   public void say(String what);
}
```

此接口与使用的接口类似 HelloWorldWorkflow，但有以下例外：
+ 它忽略 `getGreeting` 活动；该任务现在由异步方法进行处理。
+ 版本号设置为 2.0。在 Amazon SWF 注册活动接口后，您无法对其进行修改，除非更改版本号。

其余的活动方法实现与相同 HelloWorldWorkflow。只需从 `GreeterActivitiesImpl` 中删除 `getGreeting`。

## HelloWorldWorkflowAsync 工作流程实施
<a name="getting-started-example-helloworldworkflowasync.workflow"></a>

HelloWorldWorkflowAsync 定义工作流界面如下：

```
import com.amazonaws.services.simpleworkflow.flow.annotations.Execute;
import com.amazonaws.services.simpleworkflow.flow.annotations.Workflow;
import com.amazonaws.services.simpleworkflow.flow.annotations.WorkflowRegistrationOptions;

@Workflow
@WorkflowRegistrationOptions(defaultExecutionStartToCloseTimeoutSeconds = 3600)
public interface GreeterWorkflow {

   @Execute(version = "2.0")
   public void greet();
}
```

 HelloWorldWorkflow 除了新的版本号外，该接口与相同。与活动一样，如果要更改注册的工作流程，您必须更改其版本。

HelloWorldWorkflowAsync 按如下方式实现工作流程：

```
import com.amazonaws.services.simpleworkflow.flow.annotations.Asynchronous;
import com.amazonaws.services.simpleworkflow.flow.core.Promise;

public class GreeterWorkflowImpl implements GreeterWorkflow {
   private GreeterActivitiesClient operations = new GreeterActivitiesClientImpl();

   @Override
   public void greet() {
      Promise<String> name = operations.getName();
      Promise<String> greeting = getGreeting(name);
      operations.say(greeting);
   }

   @Asynchronous
   private Promise<String> getGreeting(Promise<String> name) {
      String returnString = "Hello " + name.get() + "!";
      return Promise.asPromise(returnString);
   }
}
```

HelloWorldWorkflowAsync 用`getGreeting`异步方法替换`getGreeting`活动，但该`greet`方法的工作方式大致相同：

1. 执行 `getName` 活动，这会立即返回 `Promise<String>` 对象 `name`，它表示名称。

1. 调用 `getGreeting` 异步方法并为其传递 `name` 对象。`getGreeting` 立即返回 `Promise<String>` 对象 `greeting`，它表示问候语。

1. 执行 `say` 活动并为其传递 `greeting` 对象。

1. 在 `getName` 完成时，`name` 会变为就绪状态，`getGreeting` 将使用它的值构建问候语。

1. 在 `getGreeting` 完成时，`greeting` 会变为就绪状态，`say` 会将字符串输出到控制台。

不同之处在于，greet 调用异步 `getGreeting` 方法，而不是调用活动客户端来执行 `getGreeting` 活动。实际结果是相同的，但 `getGreeting` 方法的工作方式与 `getGreeting` 活动略有不同。
+ 工作流程工作线程使用标准函数调用语义来执行 `getGreeting`。不过，活动异步执行是由 Amazon SWF 协调的。
+ `getGreeting` 在工作流程实现的进程中运行。
+ `getGreeting` 返回一个 `Promise<String>` 对象，而不是 `String` 对象。要获取 `Promise` 保留的字符串值，您需要调用其 `get()` 方法。但是，由于活动是异步运行的，因此其返回值可能无法立即准备就绪；在异步方法的返回值可用之前，`get()`将引发异常。

  有关 `Promise` 如何工作的更多信息，请参阅 [AWS Flow Framework 基本概念：活动和工作流之间的数据交换](awsflow-basics-data-exchange-activities-workflows.md)。

`getGreeting` 将问候语字符串传递给静态 `Promise.asPromise` 方法以创建返回值。该方法创建一个具有相应类型的 `Promise<T>` 对象，设置对象值，然后将其置于就绪状态。

## HelloWorldWorkflowAsync 工作流程和活动主持人和入门者
<a name="getting-started-example-helloworldworkflowasync.host"></a>

HelloWorldWorkflowAsync 实现`GreeterWorker`为工作流程和活动实现的主机类。除了`taskListToPoll`名称设置为 “`HelloWorldAsyncList`” 之外，它与 HelloWorldWorkflow实现相同。

```
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow;
import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowClient;
import com.amazonaws.services.simpleworkflow.flow.ActivityWorker;
import com.amazonaws.services.simpleworkflow.flow.WorkflowWorker;

public class GreeterWorker {
    public static void main(String[] args) throws Exception {
        ClientConfiguration config = new ClientConfiguration().withSocketTimeout(70*1000);

        String swfAccessId = System.getenv("AWS_ACCESS_KEY_ID");
        String swfSecretKey = System.getenv("AWS_SECRET_KEY");
        AWSCredentials awsCredentials = new BasicAWSCredentials(swfAccessId, swfSecretKey);

        AmazonSimpleWorkflow service = new AmazonSimpleWorkflowClient(awsCredentials, config);
        service.setEndpoint("https://swf.us-east-1.amazonaws.com");

        String domain = "helloWorldWalkthrough";
        String taskListToPoll = "HelloWorldAsyncList";

        ActivityWorker aw = new ActivityWorker(service, domain, taskListToPoll);
        aw.addActivitiesImplementation(new GreeterActivitiesImpl());
        aw.start();

        WorkflowWorker wfw = new WorkflowWorker(service, domain, taskListToPoll);
        wfw.addWorkflowImplementationType(GreeterWorkflowImpl.class);
        wfw.start();
    }
}
```

HelloWorldWorkflowAsync 在中实现工作流程启动器`GreeterMain`；它与 HelloWorldWorkflow 实现相同。

要执行工作流程，请运行`GreeterWorker`和`GreeterMain`，就像运行一样 HelloWorldWorkflow。