

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# AWS Flow Framework for Java の開始方法
<a name="getting-started"></a>

このセクションでは、基本的なプログラミングモデルと API を導入する一連の簡単なサンプルアプリケーションを順を追 AWS Flow Framework って説明します。サンプルアプリケーションは、C および付随するプログラミング言語を導入するために使用される標準の Hello World アプリケーションに基づいています。Hello World の一般的な Java 実装は次のとおりです。

```
public class HelloWorld {
   public static void main(String[] args) {
      System.out.println("Hello World!");
   }
}
```

サンプルアプリケーションの簡単な説明を以下に示します。完全なソースコードが含まれているため、自分でアプリケーションを実装して実行することができます。開始する前に、まず開発環境を設定し、 のように AWS Flow Framework for Java プロジェクトを作成する必要があります[AWS Flow Framework for Java のセットアップ](setup.md)。
+ [HelloWorld アプリケーション](getting-started-example-helloworld.md) では、標準の Java アプリケーションとして Hello World を実装しますが、ワークフローアプリケーションのように構成して、ワークフローアプリケーションを導入します。
+ [HelloWorldWorkflow アプリケーション](getting-started-example-helloworldworkflow.md) は AWS Flow Framework for Java を使用して、HelloWorld を Amazon SWF ワークフローに変換します。
+ [HelloWorldWorkflowAsync アプリケーション](getting-started-example-helloworldworkflowasync.md) では、`HelloWorldWorkflow` を変更して、*非同期ワークフロー*メソッドを使用します。
+ [HelloWorldWorkflowDistributed アプリケーション](getting-started-example-helloworldworkflowdistributed.md) では、ワークフローおよびアクティビティワーカーを別々のシステムで実行できるように、`HelloWorldWorkflowAsync` を変更します。
+ [HelloWorldWorkflowParallel アプリケーション](getting-started-example-helloworldworkflowparallel.md) では、`HelloWorldWorkflow` を変更して、2 つのアクティビティを並列に実行します。

# AWS Flow Framework for Java のセットアップ
<a name="setup"></a>

 AWS Flow Framework for Java は に含まれています[AWS SDK for Java](https://aws.amazon.com/sdkforjava/)。をまだ設定していない場合は AWS SDK for Java、「 AWS SDK for Java デベロッパーガイド[」の「開始方法](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/getting-started.html)」で SDK 自体のインストールと設定に関する情報を参照してください。

## Maven でフローフレームワークを追加する
<a name="installing-maven"></a>

Amazon SWF ビルドツールはオープンソースです。コードを表示またはダウンロードするか、ツールを自分で作成するには、[https://github.com/aws/aws-swf-build-tools](https://github.com/aws/aws-swf-build-tools) のリポジトリを参照してください。

Amazon [は、Maven Central Repository に Amazon SWF ビルドツール](https://mvnrepository.com/artifact/com.amazonaws/aws-swf-build-tools)を提供しています。

Maven でフローフレームワークを設定するには、次の依存関係をプロジェクトの `pom.xml` ファイルを追加します。

```
<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-swf-build-tools</artifactId>
    <version>2.0.0</version>
</dependency>
```

# HelloWorld アプリケーション
<a name="getting-started-example-helloworld"></a>

Amazon SWF アプリケーションの開発方法を導入するために、ワークフローのように動作するが、1 つのプロセスでローカルに実行する Java アプリケーションを作成します。アマゾン ウェブ サービスへの接続は必要ありません。

**注記**  
[HelloWorldWorkflow](getting-started-example-helloworldworkflow.md) の例では、これを基に構成されており、Amazon SWF に接続してワークフローを管理します。

ワークフローアプリケーションは、3 つの基本コンポーネントで構成されています。
+ *アクティビティワーカー*は、一連の*アクティビティ*をサポートしており、各アクティビティは、特定のタスクを実行するために個別に実行するメソッドです。
+ *ワークフローワーカー*は、アクティビティの実行を調整し、データフローを管理します。*ワークフロートポロジー*のプログラムによる結論です。これは、基本的に、順番または同時に実行されるかどうかに関係なく、さまざまなアクティビティを実行する際に定義するフローチャートです。
+ *ワークフロースターター*は、*実行*と呼ばれるワークフローインスタンスを開始し、実行時にそのインスタンスと通信できます。

HelloWorld は 3 つのクラスと 2 つの関連インターフェイスとして実装されます。詳細については、次のセクションで説明しています。開始する前に、「」の説明に従って開発環境を設定し、新しい AWS Java プロジェクトを作成する必要があります[AWS Flow Framework for Java のセットアップ](setup.md)。次のウォークスルーで使用されているパッケージの名前はすべて、`helloWorld.XYZ` です。このような名前を使用するには、次のように aop.xml で `within` 属性を設定します。

```
...
<weaver options="-verbose">
   <include within="helloWorld..*"/>
</weaver>
```

HelloWorld を実装するには、 という名前の AWS SDK プロジェクトに新しい Java パッケージを作成し`helloWorld.HelloWorld`、次のファイルを追加します。
+ インターフェイス (`GreeterActivities.java`)
+ クラスファイル (`GreeterActivitiesImpl.java`)。アクティビティワーカーを実装します。
+ インターフェイス (`GreeterWorkflow.java`)。
+ クラスファイル (`GreeterWorkflowImpl.java`)。ワークフローワーカーを実装します。
+ クラスファイル (`GreeterMain.java`)。ワークフロースターターを実装します。

各コンポーネントの完全なコードなどの詳細は、以下のセクションに記載されています。このコードは適切なファイルに追加できます。

## HelloWorld アクティビティの実装
<a name="getting-started-example-helloworld.activityworker"></a>

HelloWorld は、あいさつ (`"Hello World!"`) をコンソールに出力する全体的なタスクを 3 つのタスクに分割します。各タスクは、* アクティビティメソッド* で実行されます。このアクティビティメソッドは、次のように `GreeterActivities` インターフェイスで定義されています。

```
public interface GreeterActivities {
   public String getName();
   public String getGreeting(String name);
   public void say(String what);
}
```

HelloWorld には 1 つのアクティビティ (`GreeterActivitiesImpl`) が実装されています。このアクティビティでは、次のように `GreeterActivities` メソッドが使用されます。

```
public class GreeterActivitiesImpl implements GreeterActivities {
   @Override
   public String getName() {
      return "World";
   }

   @Override
   public String getGreeting(String name) {
      return "Hello " + name + "!";
   }

   @Override
   public void say(String what) {
      System.out.println(what);
   }
}
```

アクティビティは互いに独立しており、多くの場合、異なるワークフローで使用できます。たとえば、どのワークフローでも、`say` アクティビティを使用して文字列をコンソールに出力できます。ワークフローでは、複数のアクティビティを実装して、それぞれ異なるタスクセットを実行できます。

## HelloWorld ワークフローワーカー
<a name="getting-started-example-helloworld.workflowworker"></a>

「Hello World\$1」を コンソールに出力するには、正しいデータのアクティビティタスクを適切な順序で実行します。HelloWorld ワークフローワーカーは、以下の図に示すように、シンプルな*リニアワークフロートポロジー*に基づき、アクティビティの実行を調整します。

![\[リニアワークフロートポロジー\]](http://docs.aws.amazon.com/ja_jp/amazonswf/latest/awsflowguide/images/helloworld_topology.png)


3 つのアクティビティは、順番に実行され、そのデータはアクティビティからアクティビティに流れます。

HelloWorld ワークフローワーカーには、ワークフローのエントリポイントとなる 1 つのメソッドがあります。このメソッドは、次のように `GreeterWorkflow` インターフェイスで定義されています。

```
public interface GreeterWorkflow {
   public void greet();
}
```

`GreeterWorkflowImpl` クラスは、次のようにこのインターフェイスを実装します。

```
public class GreeterWorkflowImpl implements GreeterWorkflow{
   private GreeterActivities operations = new GreeterActivitiesImpl();

   public void greet() {
      String name = operations.getName();
      String greeting = operations.getGreeting(name);
      operations.say(greeting);
   }
}
```

`greet` メソッドは、`GreeterActivitiesImpl` のインスタンスを作成して、適切な順番で各アクティビティメソッドを呼び出し、各メソッドに適切なデータを渡して、HelloWorld トポロジーを実装します。

## HelloWorld ワークフロースターター
<a name="getting-started-example-helloworld.starter"></a>

*ワークフロースターター*は、ワークフロー実行を開始するアプリケーションです。実行中にワークフローと通信することもあります。`GreeterMain` クラスは、次のように、HelloWorld ワークフロースターターを実装します。

```
public class GreeterMain {
   public static void main(String[] args) {
      GreeterWorkflow greeter = new GreeterWorkflowImpl();
      greeter.greet();
   }
}
```

`GreeterMain` は `GreeterWorkflowImpl` のインスタンスを作成し、`greet` を呼び出してワークフローワーカーを実行します。Java アプリケーションとして `GreeterMain` を実行すると、「Hello World\$1」が コンソール出力に表示されます。

# HelloWorldWorkflow アプリケーション
<a name="getting-started-example-helloworldworkflow"></a>

基本的な [HelloWorld](getting-started-example-helloworld.md) 例は、ワークフローのように構成されていますが、Amazon SWF ワークフローとはいくつかの重要な点で異なります。


**従来のアプリケーションと Amazon SWF ワークフローアプリケーション**  

| HelloWorld | Amazon SWF ワークフロー | 
| --- | --- | 
| 単一のプロセスとしてローカルで実行されます。 | 複数のプロセスとして複数のシステム (Amazon EC2 インスタンス、プライベートデータセンター、クライアントコンピュータなど) に分散して実行できます。各プロセスで同じオペレーティングシステムを実行する必要もありません。 | 
| アクティビティは同期メソッドであり、完了するまで他はブロックされます。 | アクティビティは非同期メソッドとして即座に戻り、完了するまで待つ間にワークフローで他のタスクを実行できます。 | 
| ワークフローワーカーは、アクティビティワーカーとやり取りするために、適切なメソッドを呼び出します。 | ワークフローワーカーは、仲介として動作する Amazon SWF で HTTP リクエストを使用して、アクティビティワーカーとやり取りします。 | 
| ワークフロースターターは、ワークフローワーカーとやり取りするために、適切なメソッドを呼び出します。 | ワークフロースターターは、仲介として動作する Amazon SWF で HTTP リクエストを使用して、ワークフローワーカーとやり取りします。 | 

分散非同期ワークフローアプリケーションは、ワークフローワーカーとアクティビティワーカーのやり取りに直接ウェブサービスの呼び出しを使用することで、ゼロから実装することもできます。ただし、その場合は、複数のアクティビティの非同期実行を管理したり、データフローを処理したりするために必要なすべての複雑なコードを実装する必要があります。 AWS Flow Framework for Java と Amazon SWF はこれらの詳細をすべて処理するため、ビジネスロジックの実装に集中できます。

HelloWorldWorkflow は、HelloWorld の修正バージョンであり、Amazon SWF ワークフローとして実行されます。次の図は、2 つのアプリケーションの大まかな仕組みを示しています。

![\[従来バージョンと Amazon SWF バージョンの Hello World!\]](http://docs.aws.amazon.com/ja_jp/amazonswf/latest/awsflowguide/images/workflow_conceptual_welcome.png)


HelloWorld は単一のプロセスとして実行されます。スターター、ワークフローワーカー、およびアクティビティワーカーのやり取りには、従来のメソッド呼び出しが使用されます。`HelloWorldWorkflow`では、スターター、ワークフローワーカー、およびアクティビティワーカーは、HTTP リクエストを使用して Amazon SWF を介して相互作用する分散コンポーネントです。Amazon SWF は、ワークフローおよびアクティビティタスクのリストを維持することで相互作用を管理し、それぞれのコンポーネントにディスパッチします。このセクションでは、HelloWorldWorkflow を使用して、このフレームワークの仕組みを説明します。

HelloWorldWorkflow は AWS Flow Framework for Java API を使用して実装されます。この API は、バックグラウンドで Amazon SWF とやり取りする際の複雑な詳細を処理し、開発プロセスを大幅に簡素化します。Java アプリケーション用に設定されている HelloWorld AWS Flow Framework と同じプロジェクトを使用できます。ただし、アプリケーションを実行するには、Amazon SWF アカウントを以下のように設定する必要があります。
+  AWS アカウントをお持ちでない場合は、[Amazon Web Services](https://aws.amazon.com/) でサインアップします。
+ アカウントのアクセス ID とシークレットキー ID を、AWS\$1ACCESS\$1KEY\$1ID 環境変数と AWS\$1SECRET\$1KEY 環境変数にそれぞれ割り当てます。コードのリテラルキー値は公開しないようお勧めします。環境変数に保存すると、問題に対処しやすくなります。
+ [Amazon Simple Workflow Service](https://aws.amazon.com/swf/) で、Amazon SWF アカウントにサインアップします。
+ にログイン AWS マネジメントコンソール し、Amazon SWF サービスを選択します。
+ 右上隅の **[ドメインの管理]** を選択し、新しい Amazon SWF ドメインを登録します。*ドメイン*は、アプリケーションリソース (ワークフロータイプ、アクティビティタイプ、ワークフロー実行など) の論理コンテナです。ドメイン名は任意に指定できます。このウォークスルーでは「helloWorldWalkthrough」を使用します。

HelloWorldWorkflow を実装するには、helloWorld.HelloWorld パッケージのコピーをプロジェクトディレクトリに作成し、名前を helloWorld.HelloWorldWorkflow とします。以下のセクションでは、元の HelloWorld コードを変更して AWS Flow Framework for Java を使用し、Amazon SWF ワークフローアプリケーションとして実行する方法について説明します。

## HelloWorldWorkflow アクティビティワーカー
<a name="getting-started-example-helloworldworkflow.activities"></a>

HelloWorld では、アクティビティワーカーを単一のクラスとして実装しました。 AWS Flow Framework for Java アクティビティワーカーには 3 つの基本コンポーネントがあります。
+ *アクティビティメソッド* — 実際のタスクを実行するこのメソッドは、インターフェイスで定義され、関連するクラスに実装されます。
+ [ActivityWorker](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/simpleworkflow/flow/ActivityWorker.html) クラスは、アクティビティメソッドと Amazon SWF 間のやり取りを管理します。
+ *アクティビティホスト*アプリケーションは、アクティビティワーカーを登録して開始し、クリーンアップを処理します。

このセクションでは、アクティビティメソッドについて説明します。他の 2 つのクラスについては後で説明します。

HelloWorldWorkflow は、アクティビティインターフェイスを `GreeterActivities` で次のように定義します。

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

@ActivityRegistrationOptions(defaultTaskScheduleToStartTimeoutSeconds = 300,
                             defaultTaskStartToCloseTimeoutSeconds = 10)
@Activities(version="1.0")

public interface GreeterActivities {
   public String getName();
   public String getGreeting(String name);
   public void say(String what);
}
```

このインターフェイスは HelloWorld に厳密に必要なものではありませんが、 AWS Flow Framework for Java アプリケーション用です。インターフェイスの定義自体は変わっていないことに注意してください。ただし、Java 注釈 AWS Flow Framework には 2 つの [@ActivityRegistrationOptions](annotations.md#annotations-activityregistration)と [@Activities](annotations.md#annotations-activities)をインターフェイス定義に適用する必要があります。注釈は設定情報を提供し、 AWS Flow Framework for Java 注釈プロセッサにインターフェイス定義を使用して*アクティビティクライアント*クラスを生成するように指示します。これについては、後で説明します。

`@ActivityRegistrationOptions` には、いくつかの名前付きの値があり、アクティビティの動作を設定するために使用されます。HelloWorldWorkflow では 2 つのタイムアウトを指定します。
+ `defaultTaskScheduleToStartTimeoutSeconds` は、アクティビティのタスクリストでタスクをキューイングできる時間を指定します。300 秒 (5 分) に設定されています。
+ `defaultTaskStartToCloseTimeoutSeconds` は、アクティビティでタスクを実行する最大許容時間を指定します。10 秒に設定されています。

これらのタイムアウトにより、適切な時間内にアクティビティでタスクが完了されます。どちらかのタイムアウトを超えると、フレームワークでエラーが生成されます。ワークフローワーカーはエラーの処理方法を決定する必要があります。このようなエラーの処理方法については、「[エラー処理](errorhandling.md)」を参照してください。

`@Activities` には複数の値がありますが、通常はアクティビティのバージョン番号を指定するだけです。このバージョン番号により、世代が異なるアクティビティ実装を追跡できます。アクティビティインターフェイスを Amazon SWF に登録した後で変更した場合 (`@ActivityRegistrationOptions` の値を変更するなど) は、新しいバージョン番号を使用する必要があります。

HelloWorldWorkflow では、次のようにアクティビティメソッドを `GreeterActivitiesImpl` に実装します。

```
public class GreeterActivitiesImpl implements GreeterActivities {
   @Override
   public String getName() {
      return "World";
   }
   @Override
   public String getGreeting(String name) {
      return "Hello " + name;
   }
   @Override
   public void say(String what) {
      System.out.println(what);
   }
}
```

このコードは HelloWorld の実装と同じであることに注意してください。アクティビティの中核となるの AWS Flow Framework は、一部のコードを実行して結果を返すメソッドにすぎません。標準的なアプリケーションと Amazon SWF ワークフローアプリケーションの違いは、ワークフローでアクティビティを実行する方法、アクティビティの実行場所、および結果をワークフローワーカーに返す方法にあります。

## HelloWorldWorkflow ワークフローワーカー
<a name="getting-started-example-helloworldworkflow.workflow"></a>

Amazon SWF ワークフローワーカーには 3 つの基本コンポーネントがあります。
+ *ワークフロー実装*は、ワークフロー関連のタスクを実行するクラスです。
+ *アクティビティクライアント*クラスは、基本的にアクティビティクラスのプロキシであり、アクティビティメソッドを非同期的に実行するためにワークフロー実装で使用されます。
+ [WorkflowWorker](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/simpleworkflow/flow/WorkflowWorker.html) クラスは、ワークフローと Amazon SWF のやり取りを管理します。

このセクションでは、ワークフロー実装とアクティビティクライアントについて説明します。`WorkflowWorker`クラスについては後で説明します。

HelloWorldWorkflow では、次のようにワークフローインターフェイスを `GreeterWorkflow` で定義します。

```
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 = "1.0")
   public void greet();
}
```

このインターフェイスは、HelloWorld に厳密に必要なわけではありませんが、 AWS Flow Framework for Java アプリケーションに不可欠です。ワークフローインターフェイス定義[@WorkflowRegistrationOptions](annotations.md#annotations-workflowregistrationoptions)には、Java 注釈 AWS Flow Framework に 2 つの [@Workflow](annotations.md#annotations-workflow)と を適用する必要があります。注釈は設定情報を提供し、後で説明するように、 AWS Flow Framework for Java 注釈プロセッサがインターフェイスに基づいてワークフロークライアントクラスを生成するように指示します。

`@Workflow` には、デフォルト値である *dataConverter* でよく使用される dataConverter というオプションのパラメータが 1 つあります。これは、JsonDataConverter を使用する必要があることを示します。 NullDataConverter

`@WorkflowRegistrationOptions` にも複数のオプションのパラメータがあります。これらは、ワークフローワーカーの設定に使用できます。ここでは、`defaultExecutionStartToCloseTimeoutSeconds` を設定し、ワークフローの実行時間を指定します。最大は 3600 秒 (1 時間) です。

`GreeterWorkflow` インターフェイス定義は、HelloWorld とは 1 つの重要な点 ([@Execute](annotations.md#annotations-execute) 注釈) で異なります。ワークフローインターフェイスで指定するメソッドは、アプリケーション (ワークフロースターターなど) から呼び出すことができます。これらのメソッドの数は限られており、メソッドごとにロールが異なります。フレームワークはワークフローインターフェイスメソッドの名前やパラメータリストを指定しません。ユーザーがワークフローに適した名前やパラメータリストを使用し、 AWS Flow Framework for Java の注釈を適用してメソッドのロールを特定します。

`@Execute` には 2 つの目的があります。
+ ワークフローのエントリポイントとして `greet` を識別します。これは、ワークフローを開始するために、ワークフロースターターで呼び出すメソッドです。通常、エントリポイントには 1 つ以上のパラメータを設定できます。これにより、スターターはワークフローを初期化できます。ただし、この例では初期化が不要です。
+ ワークフローのバージョン番号を指定します。これにより、世代が異なるワークフロー実装を追跡できます。ワークフローインターフェイスを Amazon SWF に登録した後で変更する (タイムアウト値を変更するなど) には、新しいバージョン番号を使用する必要があります。

ワークフローインターフェイスに設定できる他のメソッドについては、「[ワークフローコントラクトとアクティビティコントラクト](features.workflow.md)」を参照してください。

HelloWorldWorkflow では、次のようにワークフローを `GreeterWorkflowImpl` に実装します。

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

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

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

このコードは HelloWorld に似ていますが、2 つの重要な相違点があります。
+ `GreeterWorkflowImpl` は、`GreeterActivitiesImpl` の代わりにアクティビティクライアントとして `GreeterActivitiesClientImpl` のインスタンスを作成し、クライアントオブジェクトのメソッドを呼び出してアクティビティを実行します。
+ 名前とグリーティングアクティビティは、`String` オブジェクトの代わりに `Promise<String>` オブジェクトを返します。

HelloWorld は単一のプロセスとしてローカルで実行される標準の Java アプリケーションです。そのため、`GreeterWorkflowImpl` でワークフロートポロジーを実装するには、単に `GreeterActivitiesImpl` のインスタンスを作成し、メソッドを順に呼び出して、戻り値をアクティビティ間で受け渡すだけです。Amazon SWF ワークフローの場合も同様に、アクティビティのタスクは `GreeterActivitiesImpl` のアクティビティメソッドで実行されます。ただし、このメソッドはワークフローと同じプロセスで実行されない場合があります。同じシステムで実行されない場合さえあります。したがって、ワークフローではアクティビティを非同期的に実行する必要があります。以上の要件に伴って以下の問題が生じします。
+ 異なるプロセス (異なるシステムの場合もある) で実行されている可能性があるアクティビティメソッドを実行する方法。
+ アクティビティメソッドを非同期的に実行する方法。
+ アクティビティの入力と戻り値を管理する方法。たとえば、アクティビティ A の戻り値がアクティビティ B への入力である場合、アクティビティ A が完了するまでアクティビティ B の実行をブロックする必要があります。

使い慣れた Java フロー制御、アクティビティクライアント、および `Promise<T>` を組み合わせることで、さまざまなワークフロートポロジーをアプリケーションの制御フローで実装できます。

### アクティビティクライアント
<a name="getting-started-example-helloworldworkflow.workflow.client"></a>

`GreeterActivitiesClientImpl` は、基本的に `GreeterActivitiesImpl` のプロキシであり、ワークフロー実装で `GreeterActivitiesImpl` のメソッドを非同期的に実行できます。

`GreeterActivitiesClient` クラスと `GreeterActivitiesClientImpl` クラスは自動生成されます。この自動生成には、`GreeterActivities` クラスに適用した注釈で提供される情報が使用されます。これらをユーザーが実装する必要はありません。

**注記**  
プロジェクトを保存すると、これらのクラスが Eclipse で生成されます。生成されたコードは、プロジェクトディレクトリの `.apt_generated` サブディレクトリで確認できます。  
`GreeterWorkflowImpl` クラスでのコンパイルエラーを回避するには、`.apt_generated` ディレクトリを **[Java Build Path]** (Java ビルドパス) ダイアログボックスの **[Order and Export]** (オーダーとエクスポート) タブの一番上に移動することをお勧めします。

ワークフローワーカーは、対応するクライアントメソッドを呼び出すことで、アクティビティを実行します。このメソッドは非同期であり、`Promise<T>` オブジェクトを即座に返します。ここで `T` はアクティビティの戻り値の型です。返される `Promise<T>` オブジェクトは、基本的に、アクティビティメソッドから最終的に返される値のプレースホルダです。
+ アクティビティクライアントメソッドが戻った最初の時点では、`Promise<T>` オブジェクトは*準備ができていない状態*です。この状態は、オブジェクトがまだ有効な戻り値を反映していないことを示します。
+ 次に対応するアクティビティメソッドがタスクを完了して戻ると、フレームワークは `Promise<T>` オブジェクトに戻り値を割り当て、これを *準備完了状態*にします。

### プロミス <T>Type
<a name="getting-started-example-helloworldworkflow.workflow.promise"></a>

`Promise<T>` の主目的は、非同期コンポーネント間のデータフローを管理し、これらのコンポーネントの実行時期を制御することです。これにより、アプリケーションでは、明示的に同期を管理したり、タイマーなどの機構に依存したりしなくても、非同期コンポーネントが予定より早く実行するのをブロックできます。アクティビティクライアントメソッドを呼び出すと、このメソッドは即座に戻ります。ただし、フレームワークでは入力の `Promise<T>` オブジェクトが準備完了して有効なデータを反映するまで、対応するアクティビティメソッドの実行を遅らせます。

`GreeterWorkflowImpl` の観点からは、3 つすべてのアクティビティクライアントメソッドが即座に戻ります。`GreeterActivitiesImpl` の観点からは、フレームワークは `name` が完了するまで `getGreeting` を呼び出さず、`getGreeting` が完了するまで `say` を呼び出しません。

`HelloWorldWorkflow` では `Promise<T>` を使用してアクティビティ間でデータを受け渡すことで、アクティビティメソッドで無効なデータが使用されないようにします。さらに、アクティビティの実行時期を制御し、ワークフロートポロジーを暗黙で定義します。各アクティビティの `Promise<T>` の戻り値を次のアクティビティに渡すには、アクティビティを順に実行するためのリニアトポロジー (前述) を定義する必要があります。 AWS Flow Framework for Java では、特別なモデリングコードを使用して、標準の Java フロー制御と だけでなく、複雑なトポロジーも定義する必要はありません`Promise<T>`。シンプルなパラレルトポロジーの実装方法を示す例については、「[HelloWorldWorkflowParallel アクティビティワーカー](getting-started-example-helloworldworkflowparallel.md#getting-started-example-helloworldworkflowparallel.activities)」を参照してください。

**注記**  
アクティビティメソッド (`say` など) が値を返さない場合は、対応するクライアントメソッドから `Promise<Void>` オブジェクトが返されます。オブジェクトをデータを反映しませんが、最初は準備未完了状態で、アクティビティが完了すると準備完了状態になります。したがって、`Promise<Void>` オブジェクトを他のアクティビティクライアントメソッドに渡し、元のアクティビティが完了するまで実行を遅らせることができます。

`Promise<T>` を使用すると、ワークフロー実装ではアクティビティクライアントメソッドとその戻り値を同期メソッドのように使用できます。ただし、`Promise<T>` オブジェクトの値にアクセスする場合は注意が必要です。Java の [Future<T>](http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html) タイプとは異なり、フレームワークで処理するのは `Promise<T>` の同期であり、アプリケーションではありません。`Promise<T>.get` を呼び出したときに、オブジェクトが準備未完了であれば、`get` から例外がスローされます。`HelloWorldWorkflow` が `Promise<T>` オブジェクトに直接アクセスすることはありません。オブジェクトをアクティビティ間で受け渡すだけです。オブジェクトが準備完了状態になると、フレームワークでは値を抽出し、その値を標準タイプとしてアクティビティメソッドに渡します。

`Promise<T>` オブジェクトは、必ず非同期コードでアクセスする必要があります。ここで、フレームワークは、オブジェクトを準備状態にし、有効な値を表します。`HelloWorldWorkflow` は、`Promise<T>` オブジェクトをアクティビティのクライアントメソッドにのみ渡して、問題を解決します。ワークフロー実装で `Promise<T>` オブジェクトの値にアクセスするには、オブジェクトを *非同期ワークフローメソッド*に渡します。このメソッドはアクティビティのように動作します。例については、[HelloWorldWorkflowAsync アプリケーション](getting-started-example-helloworldworkflowasync.md)を参照してください。

## HelloWorldWorkflow のワークフロー実装とアクティビティ実装
<a name="getting-started-example-helloworldworkflow.host"></a>

ワークフロー実装とアクティビティ実装には、ワーカークラスとして [ActivityWorker](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/simpleworkflow/flow/ActivityWorker.html) と [WorkflowWorker](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/simpleworkflow/flow/WorkflowWorker.html) に関連付けられています。これらのワーカークラスでは、Amazon SWF とアクティビティ/ワークフロー実装の間の通信を処理するために、適切な Amazon SWF タスクリストでタスクをポーリングし、各タスクの適切なメソッドを実行して、データフローを管理します。詳細については、「[AWS Flow Framework 基本的な概念: アプリケーション構造](awsflow-basics-application-structure.md)」を参照してください。

アクティビティ/ワーカー実装と対応するワーカーオブジェクトを関連付けるには、以下の操作を行うワーカーアプリケーションを 1 つ以上実装します。
+ ワークフローまたはアクティビティを Amazon SWF に登録する。
+ ワーカーオブジェクトを作成してワークフローまたはアクティビティのワーカー実装に関連付ける。
+ Amazon SWF との通信を開始するようワーカーオブジェクトに指示する。

ワークフローとアクティビティを別個のプロセスとして実行する場合は、ワークフローとアクティビティのワーカーホストを別個に実装する必要があります。例については、[HelloWorldWorkflowDistributed アプリケーション](getting-started-example-helloworldworkflowdistributed.md)を参照してください。シンプルにするために、HelloWorldWorkflow では以下のように 1 つのワーカーホストを実装し、アクティビティとワークフローのワーカーを同じプロセスで実行します。

```
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 = "HelloWorldList";

     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();
   }
}
```

HelloWorld には `GreeterWorker` に対応するものがないため、`GreeterWorker` という Java クラスをプロジェクトに追加し、そのファイルにコード例をコピーする必要があります。

最初のステップとして、[AmazonSimpleWorkflowClient](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/simpleworkflow/AmazonSimpleWorkflowClient.html) オブジェクトを作成して設定します。このオブジェクトは基となる Amazon SWF サービスのメソッドを呼び出します。これを行うために、`GreeterWorker` で以下の操作を実行します。

1. [ClientConfiguration](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/ClientConfiguration.html) オブジェクトを作成し、ソケットのタイムアウトとして 70 秒を指定します。この値により、ソケットが閉じるまでに、確立したオープン接続でデータを転送する時間を指定します。

1. [BasicAWSCredentials](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/BasicAWSCredentials.html) オブジェクトを作成して AWS アカウントを識別し、アカウントキーをコンストラクタに渡します。利便性のためと、キーがコードでプレーンテキストとして公開されるのを避けるために、キーを環境変数として保存します。

1. ワークフローを表す [AmazonSimpleWorkflowClient](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/simpleworkflow/AmazonSimpleWorkflowClient.html) オブジェクトを作成し、`BasicAWSCredentials` オブジェクトと `ClientConfiguration` オブジェクトをコンストラクタに渡します。

1. クライアントオブジェクトのサービスエンドポイントの URL を設定します。Amazon SWF は現在、すべての AWS リージョンで利用可能です。

便宜上、`GreeterWorker` では 2 つの文字列定数を定義します。
+ `domain` は、ワークフローの Amazon SWF ドメイン名を設定したときに作成した Amazon SWF アカウントです。`HelloWorldWorkflow` では、「helloWorldWalkthrough」ドメインのワークフローが実行されていることを前提としています。
+ `taskListToPoll` はタスクリストの名前です。ワークフローとアクティビティのワーカー間の通信を管理するために Amazon SWF で使用します。この名前として任意の便利な文字列を設定できます。HelloWorldWorkflow では、ワークフローとアクティビティの両方のタスクリストで「HelloWorldList」を使用します。バックグラウンドでは、これらの名前は最終的に別の名前空間に属するため、2 つのタスクリストは異なります。

`GreeterWorker` では、文字列定数と [AmazonSimpleWorkflowClient](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/simpleworkflow/AmazonSimpleWorkflowClient.html) オブジェクトを使用してワーカーオブジェクトを作成し、アクティビティ/ワーカー実装と Amazon SWF 間のやり取りを管理します。特に、ワーカーオブジェクトでは適切なタスクリストでタスクをポーリングするタスクを処理します。

`GreeterWorker` は、`ActivityWorker` オブジェクトを作成し、新しいクラスインスタンスを追加して `GreeterActivitiesImpl` を処理するよう設定します。`GreeterWorker` はその後 `ActivityWorker` オブジェクトの `start` メソッドを呼び出します。これにより、指定されたアクティビティのタスクリストのポーリングを開始するようオブジェクトに指示します。

`GreeterWorker` では、`WorkflowWorker` オブジェクトを作成して設定し、クラスファイル名として `GreeterWorkflowImpl.class` を追加して `GreeterWorkflowImpl` を処理できるようにします。次に、`WorkflowWorker` オブジェクトの `start` メソッドを呼び出し、このオブジェクトに対して指定されたアクティビティタスクリストのポーリングを開始するよう指示します。

この時点で `GreeterWorker` を正常に実行できます。ワークフローとアクティビティが Amazon SWF に登録され、ワーカーオブジェクトによる各タスクリストのポーリングが開始されます。これを検証するには、`GreeterWorker` を実行し、Amazon SWF コンソールに移動して、ドメインのリストから `helloWorldWalkthrough` を選択します。**[Navigation]** (ナビゲーション) ペインで **[Workflow Types]** (ワークフロータイプ) を選択すると、`GreeterWorkflow.greet` が表示されるはずです。

![\[HelloWorldWorkflow ワークフロータイプ\]](http://docs.aws.amazon.com/ja_jp/amazonswf/latest/awsflowguide/images/Workflow_Type.png)


**[アクティビティタイプ]** を選択すると、`GreeterActivities` メソッドが表示されます。

![\[HelloWorldWorkflow アクティビティタイプ\]](http://docs.aws.amazon.com/ja_jp/amazonswf/latest/awsflowguide/images/Activity_Types.png)


ただし、**[Workflow Executions] (ワークフロー実行)** を選択すると、アクティブな実行は表示されません。ワークフローワーカーとアクティビティワーカーはタスクをポーリングしますが、ワークフロー実行はまだ開始していないためです。

## HelloWorldWorkflow スターター
<a name="getting-started-example-helloworldworkflow.starter"></a>

仕上げとして、ワークフロースターターを実装します。スターターは、ワークフロー実行を開始するアプリケーションです。実行状態は Amazon SWF で保存され、その履歴と実行ステータスを確認できるようになります。HelloWorldWorkflow では、ワークフロースターターを実装するために、次のように`GreeterMain` クラスを変更します。

```
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;

public class GreeterMain {

   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";

     GreeterWorkflowClientExternalFactory factory = new GreeterWorkflowClientExternalFactoryImpl(service, domain);
     GreeterWorkflowClientExternal greeter = factory.getClient("someID");
     greeter.greet();
   }
}
```

`GreeterMain` は、まず `GreeterWorker` と同じコードを使用して `AmazonSimpleWorkflowClient` オブジェクトを作成します。次に、`GreeterWorkflowClientExternal` オブジェクトを作成します。このオブジェクトは、ワークフローのプロキシとして機能しますが、その方法は `GreeterWorkflowClientImpl` で作成したアクティビティクライアントがアクティビティメソッドのプロキシとして機能する方法とほぼ同じです。ワークフロークライアントオブジェクトを作成するには、`new` を使用しないで、次の手順に従います。

1. 外部クライアントのファクトリオブジェクトを作成し、`AmazonSimpleWorkflowClient` オブジェクトと Amazon SWF ドメイン名をコンストラクタに渡します。クライアントのファクトリオブジェクトは、フレームワークの注釈プロセッサで作成します。このプロセッサでは、ワークフローインターフェイス名に「ClientExternalFactoryImpl」と付加するだけでオブジェクト名を作成します。

1. 外部クライアントオブジェクトを作成するために、ファクトリオブジェクトの `getClient` メソッドを呼び出し、ワークフローインターフェイス名に「ClientExternal」と付加してオブジェクト名を作成します。オプションとして、`getClient` に文字列を渡します。Amazon SWF では、この文字列を使用して、このワークフローインスタンスを識別します。それ以外の場合、Amazon SWF は生成された GUID を使用してワークフローインスタンスを識別します。

ファクトリから返されるクライアントでは、[getClient](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/simpleworkflow/flow/WorkflowClientFactoryExternal.html#getClient(java.lang.String)) メソッドに渡された文字列を名前に使用するワークフローのみを作成します (ファクトリから返されるクライアントはすでに Amazon SWF 内に状態があります)。別の ID のワークフローを実行するには、ファクトリに戻り、別の ID を指定して新しいクライアントを作成する必要があります。

ワークフロークライアントは `greet` メソッドを公開します。`GreeterMain` では、このメソッドを呼び出してワークフローを開始します。`@Execute` 注釈で指定した `greet()` メソッドと同様です。

**注記**  
注釈プロセッサでは、内部クライアントのファクトリオブジェクトも作成されます。このオブジェクトは、子ワークフローの作成に使用されます。詳細については、「[子ワークフロー実行](childworkflow.md)」を参照してください。

`GreeterWorker` がまだ実行中の場合は、これを一時的にシャットダウンして `GreeterMain` を実行します。これで、Amazon SWF コンソールのアクティブなワークフロー実行のリストに someID が表示されます。

![\[HelloWorldWorkflow ワークフロー実行\]](http://docs.aws.amazon.com/ja_jp/amazonswf/latest/awsflowguide/images/Active_Execution.png)


`someID` を選択して [**イベント**] タブを選択すると、イベントが表示されます。

![\[HelloWorldWorkflow の最初のワークフローイベント\]](http://docs.aws.amazon.com/ja_jp/amazonswf/latest/awsflowguide/images/Events1.png)


**注記**  
`GreeterWorker` を早く開始して、まだ実行中の場合は、後で説明する理由のために表示されるイベントリストが長くなります。`GreeterWorker` を停止し、`GreaterMain` の実行を再試行してください。

[**イベント**] タブには 2 つのイベントのみが表示されます。
+ `WorkflowExecutionStarted` は、ワークフローの実行を開始したことを示します。
+ `DecisionTaskScheduled` は、Amazon SWF が最初の決定タスクをキューに入れたことを示します。

最初の決定タスクでワークフローがブロックされた理由は、ワークフローは、2 つのアプリケーション (`GreeterMain` と `GreeterWorker`) 間で分散されたからです。`GreeterMain` によってワークフロー実行が開始されましたが、`GreeterWorker` が実行されていないため、ワーカーはリストのポーリングとタスクの実行を行いません。各アプリケーションは個別に実行できますが、最初の決定タスクを超えてワークフロー実行を進めるには両方のアプリケーションが必要です。ここで `GreeterWorker` を実行すると、ワークフローとアクティビティのワーカーはポーリングを開始し、さまざまなタスクが迅速に完了されます。ここで [`Events`] (イベント) タブを確認すると、最初のイベントのバッチが表示されます。

![\[HelloWorldWorkflow の詳細なワークフローイベント\]](http://docs.aws.amazon.com/ja_jp/amazonswf/latest/awsflowguide/images/Events2.png)


個別のイベントを選択して詳細情報を取得できます。確認が終わるまでに、ワークフローで「Hello World\$1」が コンソールに出力されます。

完了したワークフローは、アクティブな実行のリストに表示されなくなります。ただし、再確認する場合は、実行ステータスボタンの [**Closed**] (終了) を選択し、[**List Executions**] (実行の一覧表示) を選択できます。これにより、すべての完了したワークフローインスタンスのうち、ドメインの作成時に指定した保持期間を超えていないものが、指定したドメイン (`helloWorldWalkthrough`) に表示されます。

![\[HelloWorldWorkflow の完了済みワークフロー\]](http://docs.aws.amazon.com/ja_jp/amazonswf/latest/awsflowguide/images/Closed_Workflows.png)


各ワークフローインスタンスには [**Run ID**] (実行 ID) として一意の値が割り当てられています。異なるワークフローインスタンスに同じワークフロー ID を使用できますが、一度に 1 つのアクティブな実行に対してのみ使用できます。

# HelloWorldWorkflowAsync アプリケーション
<a name="getting-started-example-helloworldworkflowasync"></a>

ワークフローは、アクティビティを使用せずに、一定のタスクをローカルで実行する方が望ましい場合があります。ただし、多くの場合、ワークフロータスクは、`Promise<T>` オブジェクトで表す値を処理する必要があります。`Promise<T>` オブジェクトを非同期ワークフローメソッドに渡すと、ただちに実行されますが、オブジェクトの準備が完了するまで `Promise<T>` オブジェクトの値にアクセスすることはできません。`true` を返すまでは `Promise<T>.isReady` をポーリングできますが、非効率なだけでなく、メソッドによって長時間ブロックされる場合があります。この場合は、*非同期メソッド*を使用する方が適切です。

非同期メソッドは、標準メソッドとよく似た方法で (多くの場合、ワークフロー実装クラスのメンバーとして) 実装され、ワークフロー実装のコンテキストで実行されます。非同期メソッドとして指定するには、`@Asynchronous` の注釈を適用します。これにより、アクティビティとよく似た方法で処理するようにフレームワークに指示されます。
+ ワークフロー実装で非同期メソッドが呼び出されると、ただちに返ります。非同期メソッドでは、通常 `Promise<T>` オブジェクトが返り、メソッドが完了すると準備状態になります。
+ 非同期メソッドを 1 つ以上の `Promise<T>` オブジェクトに渡すと、すべての入力オブジェクトが準備状態になるまで、実行は延期されます。そのため、非同期メソッドでは、例外のリスクなしに、入力値 `Promise<T>` にアクセスすることができます。

**注記**  
 AWS Flow Framework for Java がワークフローを実行する方法のため、非同期メソッドは通常複数回実行されるため、それらは簡単な低オーバーヘッドタスクにのみ使用する必要があります。また、大規模な計算などの長時間タスクを実行するには、アクティビティを使用します。詳細については、「[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` オブジェクトを渡します。`Promise<String>` オブジェクト、`greeting` が `getGreeting` よりすぐに返ります。これは、あいさつを表します。

1. `say` アクティビティを実行し、`greeting` オブジェクトに渡します。

1. `getName` が完了すると、`name` は準備状態になり、`getGreeting` はその値を使用してあいさつを作成します。

1. `getGreeting` が完了すると、`greeting` は準備状態になり、`say` によって文字列がコンソールに出力されます。

この場合、アクティビティクライアントを呼び出して `getGreeting` アクティビティを実行せずに、あいさつで非同期の `getGreeting` メソッドを呼び出すという点が異なります。最終的な結果は同じですが、`getGreeting` メソッドの動作は、`getGreeting` アクティビティとは少し異なります。
+ ワークフローワーカーは、標準の関数呼び出しのセマンティクスを使用して `getGreeting` を実行します。ただし、アクティビティの非同期実行は Amazon SWF を介して行われます。
+ `getGreeting` は、ワークフロー実装のプロセスで実行されます。
+ `getGreeting` では、`String` オブジェクトではなく、`Promise<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` という名前を除き、HelloWorldWorkflow と同様に実装されます。名前は「`HelloWorldAsyncList`」に設定されます。

```
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 と同様に実装されます。

ワークフローを実行するには、HelloWorldWorkflow の場合と同様に `GreeterWorker` および `GreeterMain` を実行します。

# HelloWorldWorkflowDistributed アプリケーション
<a name="getting-started-example-helloworldworkflowdistributed"></a>

HelloWorldWorkflow および HelloWorldWorkflowAsync では、Amazon SWF は、ワークフローとアクティビティ実装間の相互作用を仲介しますが、1 つのプロセスとしてローカルに実行されます。`GreeterMain` は、個別のプロセスですが、同じシステム上で実行されます。

Amazon SWF の主な機能は、分散アプリケーションをサポートすることです。例えば、ワークフローワーカーは Amazon EC2 インスタンス、ワークフロースターターはデータセンターコンピュータ、アクティビティはクライアントデスクトップコンピュータといったように実行できます。さまざまなシステムでさまざまなアクティビティを実行できます。

HelloWorldWorkflowDistributed アプリケーションは、2 つのシステムと 3 つのプロセスでアプリケーションを分散するように、HelloWorldWorkflowAsync を拡張します。
+ ワークフローとワークフロースターターは、別々のプロセスを 1 つのシステムで実行します。
+ アクティビティは、別々のシステムで実行されます。

アプリケーションを実装するには、helloWorld.HelloWorldWorkflowAsync パッケージのコピーをプロジェクトディレクトリに作成し、helloWorld.HelloWorldWorkflowDistributed という名前を付けます。以下のセクションでは、元の HelloWorldWorkflowAsync コードを変更し、2 つのシステムと 3 つのプロセスでアプリケーションを分散する方法について説明します。

別々のシステムで実行するために、ワークフロー実装やアクティビティ実装、バージョン番号を変更する必要はありません。また、`GreeterMain` の変更も不要です。必要なのは、アクティビティとワークフローのホストの変更のみです。

HelloWorldWorkflowAsync では、1 つのアプリケーションをワークフローとアクティビティのホストとして使用できます。ワークフロー実装とアクティビティの実装を別々のシステムで実行するには、アプリケーションを個別に実装する必要があります。GreeterWorker をプロジェクトから削除して、2 つの新しいクラスファイル (GreeterWorkflowWorker および GreeterActivitiesWorker) を追加します。

HelloWorldWorkflowDistributed は、アクティビティホストを次のように GreeterActivitiesWorker に実装します。

```
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;

public class GreeterActivitiesWorker {
   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 = "helloWorldExamples";
      String taskListToPoll = "HelloWorldAsyncList";

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

HelloWorldWorkflowDistributed は、ワークフローホストを次のように `GreeterWorkflowWorker` に実装します。

```
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.WorkflowWorker;

public class GreeterWorkflowWorker {
   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 = "helloWorldExamples";
      String taskListToPoll = "HelloWorldAsyncList";

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

`GreeterActivitiesWorker` は、`WorkflowWorker` コードを使用しない `GreeterWorker`、`GreeterWorkflowWorker` は、`ActivityWorker` コードを使用しない `GreeterWorker` です。

**ワークフローを実行するには:**

1. `GreeterActivitiesWorker` で実行できる JAR ファイルをエントリポイントとして作成します。

1. ステップ 1 から JAR ファイルを別のシステムにコピーします。これにより、Java をサポートするすべてのオペレーティングシステムを実行できます。

1. 同じ Amazon SWF ドメインにアクセスできる AWS 認証情報が他のシステムで使用可能であることを確認します。

1. JAR ファイルを実行します。

1. 開発システムで Eclipse を使用して、`GreeterWorkflowWorker` および `GreeterMain` を実行します。

アクティビティがワークフローワーカーやワークフロースターターとは異なるシステムで実行されているという事実を除き、ワークフローは HelloWorldAsync とまったく同じ方法で動作します。ただし、「Hello World\$1」という文字列をコンソールに出力する `println` コールは `say` アクティビティ内にあり、出力はアクティビティワーカーで実行されているシステムに表示されます。

# HelloWorldWorkflowParallel アプリケーション
<a name="getting-started-example-helloworldworkflowparallel"></a>

前述のバージョンの Hello World\$1 線形ワークフロートポロジーをすべて使用します。ただし、Amazon SWF はリニアトポロジーに制限されません。以下の図のように、HelloWorldWorkflowParallel アプリケーションは、変更されたバージョンの HelloWorldWorkflow であり、並列トポロジーが使用されています。

![\[HelloWorldWorkflowParallel ワークフロートポロジー\]](http://docs.aws.amazon.com/ja_jp/amazonswf/latest/awsflowguide/images/helloworld_parallel_topology.png)


HelloWorldWorkflowParallel では、`getName` と `getGreeting` は並列に実行され、それぞれよりあいさつの一部が返ります。`say` はその後、2 つの文字列をグリーティングにマージし、コンソールに出力します。

アプリケーションを実装するには、helloWorld.HelloWorldWorkflow パッケージのコピーをプロジェクトディレクトリに作成し、helloWorld.HelloWorldWorkflowParallel という名前を付けます。以下のセクションでは、元の HelloWorldWorkflow コードを変更して、`getName` および `getGreeting` を並列に実行する方法について説明します。

## HelloWorldWorkflowParallel アクティビティワーカー
<a name="getting-started-example-helloworldworkflowparallel.activities"></a>

HelloWorldWorkflowParallel アクティビティのインターフェイスは、以下の例に示すように、`GreeterActivities` で実装されます。

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

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

このインターフェイスは、次の点を除き、HelloWorldWorkflow で使用するものと似ています。
+ `getGreeting` は入力を一切受け付けません。あいさつの文字列のみ帰ります。
+ `say` は、2 つの入力文字列 (あいさつと名前) を受け付けます。
+ インターフェイスには新しいバージョン番号があります。登録済みのインターフェイスを変更する場合に必要です。

HelloWorldWorkflowParallel は、次のように `GreeterActivitiesImpl` でアクティビティを実装します。

```
public class GreeterActivitiesImpl implements GreeterActivities {

   @Override
   public String getName() {
      return "World!";
   }

   @Override
   public String getGreeting() {
      return "Hello ";
   }

   @Override
   public void say(String greeting, String name) {
      System.out.println(greeting + name);
   }
}
```

`getName` と `getGreeting` はあいさつの文字列の半分を返します。`say` は、その 2 つの部分を連結して完全なフレーズを生成し、コンソールに出力します。

## HelloWorldWorkflowParallel ワークフローワーカー
<a name="getting-started-example-helloworldworkflowparallel-worker"></a>

HelloWorldWorkflowParallel ワークフローインターフェイスは、次のように `GreeterWorkflow` で実装されます。

```
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 = "5.0")
   public void greet();
}
```

このクラスは、アクティビティワーカーに一致させるようにバージョン番号が変更されている点を除き、HelloWorldWorkflow バージョンと同じものです。

このワークフローは、次のように `GreeterWorkflowImpl` で実装されます。

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

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

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

ひと目で分かるように、この実装は、HelloWorldWorkflow にとてもよく似ています。3 つのアクティビティクライアントメソッドは順番に実行されます。ただし、アクティビティは実行されません。
+ HelloWorldWorkflow は、`name` を `getGreeting` に渡しました。`name` は `Promise<T>` オブジェクトだったため、`getGreeting` は `getName` が完了するまでアクティビティを延期しました。その結果、2 つのアクティビティは順番に実行されました。
+ HelloWorldWorkflowParallel では、入力 `getName` と `getGreeting` のいずれも渡されません。どちらのメソッドの実行も延期されず、そのアクティビティメソッドは並行ですぐに実行されます。

`say` アクティビティは、`greeting` と `name` のいずれも、入力パラメータとして取得します。これらは `Promise<T>` オブジェクトであるため、両方のアクティビティが完了するまで `say` で実行は延期されます。その後、あいさつが作成、出力されます。

HelloWorldWorkflowParallel では、ワークフロートポロジーの定義に特殊なモデル化コードは一切使用しません。これは、標準の Java フローコントロールを使用し、`Promise<T>`オブジェクトのプロパティを利用することによって暗黙的に行われます。 AWS Flow Framework for Java アプリケーションは、`Promise<T>`オブジェクトを従来の Java コントロールフロー構造と組み合わせて使用するだけで、複雑なトポロジーも実装できます。

## HelloWorldWorkflowParallel ワークフローおよびアクティビティのホストおよびスターター
<a name="HelloWorldWorkflowParallel-workflow-activities-host-starter"></a>

HelloWorldWorkflowParallel は、ワークフローとアクティビティ実装のホストクラスとして `GreeterWorker` を実装します。このメソッドでは、`taskListToPoll` という名前を除き、HelloWorldWorkflow と同様に実装されます。名前は「HelloWorldParallelList」に設定されます。

`HelloWorldWorkflowParallel` では、`GreeterMain` でワークフロースターターを実装します。この実装は、HelloWorldWorkflow と同様に行われます。

ワークフローを実行するには、`HelloWorldWorkflow` の場合と同様に `GreeterWorker` および `GreeterMain` を実行します。