

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

# 活动和工作流程客户端
<a name="clients"></a>

工作流程和活动客户端由框架基于 `@Workflow` 和 `@Activities` 接口生成。所生成的单独客户端接口包含仅对该客户端有意义的方法和设置。如果您使用 Eclipse 开发，则每次保存包含相应接口的文件时，Amazon SWF Eclipse 插件都会执行此操作。所生成的代码放在项目中生成的源目录中，位于与接口相同的程序包内。

**注意**  
请注意，Eclipse 使用的默认目录名称为 .apt\$1generated。Eclipse 不显示目录名称以“.”在 Package Explorer 中。如果您希望在 Project Explorer 中查看生成的文件，请使用其他目录名称。在 Eclipse 中，右键单击 Package Explorer 中的程序包，然后依次选择 **Properties** (属性)、**Java Compiler** (Java 编译器)、**Annotation processing** (注释处理)，并修改 **Generate source directory** (生成源目录) 设置。

## 工作流程客户端
<a name="clients.workflow"></a>

为工作流程生成的构件包含三个客户端一侧的接口以及实施这些接口的类。生成的客户端包括：
+ *异步客户端*，应在工作流程实施内部使用，提供异步方法来启动工作流程执行和发送信号
+ *外部客户端*，可用于在工作流程实施范围之外启动执行和发送信号，以及检索工作流程状态
+ *自助客户端*，可用于创建连续工作流程

例如，为示例 `MyWorkflow` 接口生成的客户端接口为：

```
//Client for use from within a workflow
public interface MyWorkflowClient extends WorkflowClient
{
    Promise<Void> startMyWF(
       int a, String b);

    Promise<Void> startMyWF(
       int a, String b,
       Promise<?>... waitFor);

    Promise<Void> startMyWF(
       int a, String b,
       StartWorkflowOptions optionsOverride,
       Promise<?>... waitFor);

    Promise<Void> startMyWF(
       Promise<Integer> a,
       Promise<String> b);

    Promise<Void> startMyWF(
       Promise<Integer> a,
       Promise<String> b,
       Promise<?>... waitFor);

    Promise<Void> startMyWF(
       Promise<Integer> a,
       Promise<String> b,
       StartWorkflowOptions optionsOverride,
       Promise<?>... waitFor);

    void signal1(
      int a, int b, String c);
}

//External client for use outside workflows
public interface MyWorkflowClientExternal extends WorkflowClientExternal
{
    void startMyWF(
       int a, String b);

    void startMyWF(
       int a, String b,
       StartWorkflowOptions optionsOverride);

    void signal1(
       int a, int b, String c);

    MyWorkflowState getState();
}

//self client for creating continuous workflows
public interface MyWorkflowSelfClient extends WorkflowSelfClient
{
    void startMyWF(
       int a, String b);

    void startMyWF(
       int a, String b,
       Promise<?>... waitFor);

    void startMyWF(
       int a, String b,
       StartWorkflowOptions optionsOverride,
       Promise<?>... waitFor);

    void startMyWF(
       Promise<Integer> a,
       Promise<String> b);

    void startMyWF(
       Promise<Integer> a,
       Promise<String> b,
       Promise<?>... waitFor);

    void startMyWF(
       Promise<Integer> a,
       Promise<String> b,
       StartWorkflowOptions optionsOverride,
       Promise<?>... waitFor);
```

接口具有与所声明 `@Workflow` 接口中的各个方法对应的重载方法。

外部客户端通过接受 `StartWorkflowOptions` 的 `@Execute` 方法的一个额外重载，来镜像 `@Workflow` 接口上的方法。启动新工作流程执行时，您可以使用此重载方法传递额外的选项。通过这些选项，您可以覆盖默认任务列表、超时设置以及将标签与工作流程执行关联。

另一方面，异步客户端具有方法，这些方法允许异步调用 `@Execute` 方法。在客户端接口中，为工作流程接口中的 `@Execute` 方法生成以下方法重载：

1. 按原样接受原始参数的重载。如果原始方法返回了 `void`，此重载的返回类型将为 `Promise<Void>`；否则将为原始方法上声明的 `Promise<>`。例如：

   原始方法：

   ```
   void startMyWF(int a, String b);
   ```

   生成的方法：

   ```
   Promise<Void> startMyWF(int a, String b);
   ```

   在工作流的所有参数均可用并且不需要等待的时候，应使用此重载。

1. 按原样接受原始参数以及类型为 `Promise<?>` 的额外变量参数的重载。如果原始方法返回了 `void`，此重载的返回类型将为 `Promise<Void>`；否则将为原始方法上声明的 `Promise<>`。例如：

   原始方法：

   ```
   void startMyWF(int a, String b);
   ```

   生成的方法：

   ```
   Promise<void> startMyWF(int a, String b, Promise<?>...waitFor);
   ```

   在工作流程的所有参数均可用并且不需要等待，但您希望等待一些其他 promise 就绪时，应使用此重载。变量参数可用于传递此类未声明为参数的 `Promise<?>` 对象，不过在执行调用之前您可能需要等待。

1. 按原样接受原始参数、一个类型为 `StartWorkflowOptions` 的额外参数以及类型为 `Promise<?>` 的额外变量参数的重载。如果原始方法返回了 `void`，此重载的返回类型将为 `Promise<Void>`；否则将为原始方法上声明的 `Promise<>`。例如：

   原始方法：

   ```
   void startMyWF(int a, String b);
   ```

   生成的方法：

   ```
   Promise<void> startMyWF(
      int a,
      String b,
      StartWorkflowOptions optionOverrides,
      Promise<?>...waitFor);
   ```

   在工作流程的所有参数均可用并且不需要等待的时候，当您希望覆盖用于启动工作流程执行的默认设置时，或者当您希望等待一些其他 promise 就绪时，应使用此重载。变量参数可用于传递此类未声明为参数的 `Promise<?>` 对象，不过在执行调用之前您可能需要等待。

1. 将原始方法中的各个参数使用 `Promise<>` 包装器替换的重载。如果原始方法返回了 `void`，此重载的返回类型将为 `Promise<Void>`；否则将为原始方法上声明的 `Promise<>`。例如：

   原始方法：

   ```
   void startMyWF(int a, String b);
   ```

   生成的方法：

   ```
   Promise<Void> startMyWF(
      Promise<Integer> a,
      Promise<String> b);
   ```

   要对传递到工作流程执行的参数进行异步求值时，应使用此重载。在传递到此方法重载的所有参数就绪之前，不会执行对该重载的调用。

   如果一些参数已经就绪，则通过 `Promise.asPromise(value)` 方法将这些参数转换为已处于就绪状态的 `Promise`。例如：

   ```
   Promise<Integer> a = getA();
   String b = getB();
   startMyWF(a, Promise.asPromise(b));
   ```

1. 将原始方法中的各个参数使用 `Promise<>` 包装器替换的重载。重载还具有类型为 `Promise<?>` 的额外变量参数。如果原始方法返回了 `void`，此重载的返回类型将为 `Promise<Void>`；否则将为原始方法上声明的 `Promise<>`。例如：

   原始方法：

   ```
   void startMyWF(int a, String b);
   ```

   生成的方法：

   ```
   Promise<Void> startMyWF(
      Promise<Integer> a,
      Promise<String> b,
      Promise<?>...waitFor);
   ```

   要对传递到工作流程执行的参数进行异步求值，并且您还希望等待一些其他 promise 就绪时，应使用此重载。在传递到此方法重载的所有参数就绪之前，不会执行对该重载的调用。

1. 将原始方法中的各个参数使用 `Promise<?>` 包装器替换的重载。重载还具有一个类型为 `StartWorkflowOptions` 的额外参数以及类型为 `Promise<?>` 的变量参数。如果原始方法返回了 `void`，此重载的返回类型将为 `Promise<Void>`；否则将为原始方法上声明的 `Promise<>`。例如：

   原始方法：

   ```
   void startMyWF(int a, String b);
   ```

   生成的方法：

   ```
   Promise<Void> startMyWF(
      Promise<Integer> a,
      Promise<String> b,
      StartWorkflowOptions optionOverrides,
      Promise<?>...waitFor);
   ```

   要对传递到工作流程执行的参数进行异步求值，并且您希望覆盖用于启动工作流程执行的默认设置时，使用此重载。在传递到此方法重载的所有参数就绪之前，不会执行对该重载的调用。

例如，工作流界面中的每个信号也会生成相应的方法：

原始方法：

```
void signal1(int a, int b, String c);
```

生成的方法：

```
void signal1(int a, int b, String c);
```

异步客户端不包含与原始接口中使用 `@GetState` 注释的方法相对应的方法。由于检索状态需要调用 Web 服务，因此不适合在工作流程中使用。因此，它仅通过外部客户端提供。

自助客户端应在工作流程内部执行，用于在当前执行完成后启动新执行。此客户端上的方法类似于异步客户端上的方法，不过返回 `void`。此客户端没有与使用 `@Signal` 和 `@GetState` 注释的方法相对应的方法。有关详细信息，请参阅[连续工作流程](continuous.md)。

生成的客户端分别派生自基本接口：`WorkflowClient` 和 `WorkflowClientExternal`，其中提供了可用于取消或终止工作流程执行的方法。有关这些接口的详细信息，请参阅 适用于 Java 的 AWS SDK 文档。

生成的客户端允许您以强类型方式与工作流程执行交互。在创建后，所生成客户端的一个实例将绑定到特定工作流程执行，并且只能用于该执行。此外，该框架还提供非特定于工作流程类型或执行的动态客户端。在涵盖的范围内，生成的客户端依靠此客户端。您还可以直接使用这些客户端。请参阅[动态客户端](#dynamicclients)中的章节。

该框架还生成用于创建强类型客户端的工厂。为示例 `MyWorkflow` 接口生成的客户端工厂为：

```
//Factory for clients to be used from within a workflow
public interface MyWorkflowClientFactory
   extends WorkflowClientFactory<MyWorkflowClient>
{
}

//Factory for clients to be used outside the scope of a workflow
public interface MyWorkflowClientExternalFactory
{
   GenericWorkflowClientExternal getGenericClient();
   void setGenericClient(GenericWorkflowClientExternal genericClient);
   DataConverter getDataConverter();
   void setDataConverter(DataConverter dataConverter);
   StartWorkflowOptions getStartWorkflowOptions();
   void setStartWorkflowOptions(StartWorkflowOptions startWorkflowOptions);
   MyWorkflowClientExternal getClient();
   MyWorkflowClientExternal getClient(String workflowId);
   MyWorkflowClientExternal getClient(WorkflowExecution workflowExecution);
   MyWorkflowClientExternal getClient(
      WorkflowExecution workflowExecution,
      GenericWorkflowClientExternal genericClient,
      DataConverter dataConverter,
      StartWorkflowOptions options);
}
```

`WorkflowClientFactory` 基本接口为：

```
public interface WorkflowClientFactory<T> {
    GenericWorkflowClient getGenericClient();
    void setGenericClient(GenericWorkflowClient genericClient);
    DataConverter getDataConverter();
    void setDataConverter(DataConverter dataConverter);
    StartWorkflowOptions getStartWorkflowOptions();
    void setStartWorkflowOptions(StartWorkflowOptions startWorkflowOptions);
    T getClient();
    T getClient(String workflowId);
    T getClient(WorkflowExecution execution);
    T getClient(WorkflowExecution execution,
                StartWorkflowOptions options);
    T getClient(WorkflowExecution execution,
                StartWorkflowOptions options,
                DataConverter dataConverter);
}
```

您应使用这些工厂创建客户端的实例。使用工厂可以配置常规客户端 (常规客户端应该用于提供自定义客户端实施) 和由客户端用于编集数据的 `DataConverter`，以及用于启动*工作流程执行* 的选项。有关更多信息，请参阅[DataConverters](dataconverters.md)和[子工作流程执行](childworkflow.md)部分。`StartWorkflowOptions` 包含可用于覆盖在注册时指定的默认值（例如，超时值）的设置。有关该`StartWorkflowOptions`类的更多详细信息，请参阅 适用于 Java 的 AWS SDK 文档。

外部客户端可用于从工作流程范围之外启动工作流程执行，而异步客户端可用于从工作流程中的代码启动工作流程执行。要启动执行，您只需使用生成的客户端调用与工作流程接口中使用 `@Execute` 注释的方法对应的方法。

该框架还为客户端接口生成实施类。这些客户端创建请求并发送给 Amazon SWF，以执行相应的操作。该`@Execute`方法的客户端版本要么启动新的工作流程执行，要么使用 Amazon SW APIs F 创建子工作流程执行。同样，该`@Signal`方法的客户端版本使用 Amazon SWF APIs 发送信号。

**注意**  
外部工作流客户端必须配置 Amazon SWF 客户端和域。您可以使用将这些配置作为参数的客户端工厂构造函数，或者传入已经配置好 Amazon SWF 客户端和域的通用客户端实施。  
该框架遍历工作流程接口的类型层次，还会为父工作流程接口生成客户端接口并从它们进行派生。

## 活动客户端
<a name="clients.activity"></a>

与工作流程客户端类似，为使用 `@Activities` 注释的每个接口生成一个客户端。生成的构件包括客户端接口以及客户端类。为以上示例 `@Activities` 接口 (`MyActivities`) 生成的接口如下所示：

```
public interface MyActivitiesClient extends ActivitiesClient
{
  Promise<Integer> activity1();
  Promise<Integer> activity1(Promise<?>... waitFor);
  Promise<Integer> activity1(ActivitySchedulingOptions optionsOverride,
                             Promise<?>... waitFor);
  Promise<Void> activity2(int a);
  Promise<Void> activity2(int a,
                          Promise<?>... waitFor);
  Promise<Void> activity2(int a,
                          ActivitySchedulingOptions optionsOverride,
                          Promise<?>... waitFor);
  Promise<Void> activity2(Promise<Integer> a);
  Promise<Void> activity2(Promise<Integer> a,
                          Promise<?>... waitFor);
  Promise<Void> activity2(Promise<Integer> a,
                          ActivitySchedulingOptions optionsOverride,
                          Promise<?>... waitFor);
}
```

接口包含一组重载方法，这些方法对应于 `@Activities` 接口中的各个活动方法。提供这些重载是为了方便起见，并允许异步调用活动。对于 `@Activities` 接口中的各个活动方法，在客户端接口中生成以下方法重载：

1. 按原样接受原始参数的重载。此重载的返回类型为 `Promise<T>`，其中 `T` 是原始方法的返回类型。例如：

   原始方法：

   ```
   void activity2(int foo);
   ```

   生成的方法：

   ```
   Promise<Void> activity2(int foo);
   ```

   在工作流的所有参数均可用并且不需要等待的时候，应使用此重载。

1. 按原样接受原始参数、一个类型为 `ActivitySchedulingOptions` 的参数以及类型为 `Promise<?>` 的额外变量参数的重载。此重载的返回类型为 `Promise<T>`，其中 `T` 是原始方法的返回类型。例如：

   原始方法：

   ```
   void activity2(int foo);
   ```

   生成的方法：

   ```
   Promise<Void> activity2(
     int foo,
     ActivitySchedulingOptions optionsOverride,
     Promise<?>... waitFor);
   ```

   在工作流程的所有参数均可用并且不需要等待的时候，在您希望覆盖默认设置时，或者当您希望等待额外的 `Promise` 就绪时，应使用此重载。变量参数可用于传递此类未声明为参数的额外 `Promise<?>` 对象，不过在执行调用之前您可能需要等待。

1. 将原始方法中的各个参数使用 `Promise<>` 包装器替换的重载。此重载的返回类型为 `Promise<T>`，其中 `T` 是原始方法的返回类型。例如：

   原始方法：

   ```
   void activity2(int foo);
   ```

   生成的方法：

   ```
   Promise<Void> activity2(Promise<Integer> foo);
   ```

   要对传递到活动的参数进行异步求值时，应使用此重载。在传递到此方法重载的所有参数就绪之前，不会执行对该重载的调用。

1. 将原始方法中的各个参数使用 `Promise<>` 包装器替换的重载。重载还具有一个类型为 `ActivitySchedulingOptions` 的额外参数以及类型为 `Promise<?>` 的变量参数。此重载的返回类型为 `Promise<T>`，其中 `T` 是原始方法的返回类型。例如：

   原始方法：

   ```
   void activity2(int foo);
   ```

   生成的方法：

   ```
   Promise<Void> activity2(
      Promise<Integer> foo,
      ActivitySchedulingOptions optionsOverride,
      Promise<?>...waitFor);
   ```

   要对传递到活动的参数进行异步求值时，当您希望覆盖随类型注册的默认设置时，或者当您希望等待其他 `Promise` 就绪时，应使用此重载。在传递到此方法重载的所有参数就绪之前，不会执行对该重载的调用。生成的客户端类实施此接口。每种接口方法的实现都会创建并向 Amazon SWF 发送请求，要求使用 Amazon SWF 安排相应类型的活动任务。 APIs

1. 按原样接受原始参数以及类型为 `Promise<?>` 的额外变量参数的重载。此重载的返回类型为 `Promise<T>`，其中 `T` 是原始方法的返回类型。例如：

   原始方法：

   ```
   void activity2(int foo);
   ```

   生成的方法：

   ```
   Promise< Void > activity2(int foo,
                                Promise<?>...waitFor);
   ```

   在所有活动参数均可用并且无需等待，但您希望等待另一个 `Promise` 对象就绪时，应使用此重载。

1. 将原始方法中各个参数替换为 `Promise` 包装器并具有类型为 `Promise<?>` 的附加变量参数的重载。此重载的返回类型为 `Promise<T>`，其中 `T` 是原始方法的返回类型。例如：

   原始方法：

   ```
   void activity2(int foo);
   ```

   生成的方法：

   ```
   Promise<Void> activity2(
     Promise<Integer> foo,
     Promise<?>... waitFor);
   ```

   在活动的所有参数将等待异步处理并且您还希望等待某些其他的 `Promise` 就绪时，应使用此重载。在传递的所有 `Promise` 对象都就绪后，对此方法重载的调用将异步执行。

生成的活动客户端还具有与各个活动方法对应的受保护方法，方法的名称为 `{activity method name}Impl()`，所有活动重载都将调用该方法。您可以覆盖此方法以创建模拟客户端实施。此方法接受以下对象作为参数：传递到 `Promise<>` 包装器中原始方法的所有参数、`ActivitySchedulingOptions`，以及类型为 `Promise<?>` 的变量参数。例如：

原始方法：

```
void activity2(int foo);
```

生成的方法：

```
Promise<Void> activity2Impl(
   Promise<Integer> foo,
   ActivitySchedulingOptions optionsOverride,
   Promise<?>...waitFor);
```

## 计划选项
<a name="schedulingoptions"></a>

生成的活动客户端允许您传入 `ActivitySchedulingOptions` 作为参数。`ActivitySchedulingOptions` 结构包含的设置可决定框架在 Amazon SWF 中安排的活动任务配置。这些设置覆盖指定为注册选项的默认值。要动态指定计划选项，请创建 `ActivitySchedulingOptions` 对象，根据需要进行配置，并将该对象传递到活动方法。在以下示例中，我们指定了应该用于活动任务的任务列表。这会覆盖活动的此调用的默认注册任务列表。

```
public class OrderProcessingWorkflowImpl implements OrderProcessingWorkflow {

    OrderProcessingActivitiesClient activitiesClient
            = new OrderProcessingActivitiesClientImpl();

    // Workflow entry point
    @Override
    public void processOrder(Order order) {
        Promise<Void> paymentProcessed = activitiesClient.processPayment(order);
        ActivitySchedulingOptions schedulingOptions
             = new ActivitySchedulingOptions();
        if (order.getLocation() == "Japan") {
            schedulingOptions.setTaskList("TasklistAsia");
        } else {
            schedulingOptions.setTaskList("TasklistNorthAmerica");
        }

        activitiesClient.shipOrder(order,
                                   schedulingOptions,
                                   paymentProcessed);
    }
}
```

## 动态客户端
<a name="dynamicclients"></a>

除了所生成的客户端之外，框架还会提供通用客户端 `DynamicWorkflowClient` 和 `DynamicActivityClient`，您可以使用这些客户端来动态启动工作流执行、发送信号和安排活动等。例如，您可能希望计划其类型在设计时未知的活动。您可以使用 `DynamicActivityClient` 来计划此类活动任务。与此类似，您可以使用 `DynamicWorkflowClient` 来动态计划子工作流程执行。在以下示例中，工作流程从数据库中查找活动并使用动态活动客户端来计划该活动：

```
//Workflow entrypoint
@Override
public void start() {
   MyActivitiesClient client = new MyActivitiesClientImpl();
  Promise<ActivityType> activityType
      = client.lookUpActivityFromDB();
  Promise<String> input = client.getInput(activityType);
  scheduleDynamicActivity(activityType,
                          input);
}
@Asynchronous
void scheduleDynamicActivity(Promise<ActivityType> type,
                             Promise<String> input){
  Promise<?>[] args = new Promise<?>[1];
   args[0] = input;
   DynamicActivitiesClient activityClient
       = new DynamicActivitiesClientImpl();
   activityClient.scheduleActivity(type.get(),
                                   args,
                                   null,
                                   Void.class);
}
```

有关更多详细信息，请参阅 适用于 Java 的 AWS SDK 文档。

### 发送信号和取消工作流程执行
<a name="executioncontext.signal"></a>

所生成的工作流程客户端具有与可发送到工作流程的各个信号相对应的方法。您可以在工作流程中使用这些方法将信号发送到其他工作流程执行。这为发送信号提供了类型化机制。但有时您可能需要动态确定信号名称，例如，在消息中接收信号名称时。您可以使用动态工作流程客户端将信号动态地发送到任意工作流程执行。与此类似，您可以使用客户端来请求取消另一个工作流程执行。

在以下示例中，工作流程查找将信号从数据库发送到的执行，并使用动态工作流程客户端来动态发送信号。

```
//Workflow entrypoint
public void start()
{
  MyActivitiesClient client = new MyActivitiesClientImpl();
  Promise<WorkflowExecution> execution = client.lookUpExecutionInDB();
  Promise<String> signalName = client.getSignalToSend();
  Promise<String> input = client.getInput(signalName);
  sendDynamicSignal(execution, signalName, input);
}

@Asynchronous
void sendDynamicSignal(
   Promise<WorkflowExecution> execution,
   Promise<String> signalName,
   Promise<String> input)
{
   DynamicWorkflowClient workflowClient
      = new DynamicWorkflowClientImpl(execution.get());
   Object[] args = new Promise<?>[1];
   args[0] = input.get();
   workflowClient.signalWorkflowExecution(signalName.get(), args);
}
```