シンプルな Amazon SWF アプリケーションの構築 - AWS SDK for Java 1.x

AWS SDK for Java (v1) の近日発表 end-of-support しました。AWS SDK for Java v2 に移行することをお勧めします。日付、その他の詳細、移行方法については、リンク先の発表内容を参照してください。

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

シンプルな Amazon SWF アプリケーションの構築

このトピックでは、AWS SDK for Java を使用した Amazon SWF アプリケーションのプログラミングについて、重要な概念を示しながら説明します。

例について

例のプロジェクトでは、AWS クラウドを通じて渡されるワークフローデータを受け入れる 1 つのアクティビティでワークフローを作成し (HelloWorld では、いつものように、あいさつする相手の名前になります)、応答であいさつを出力します。

これは表面的には非常に単純に見えますが、Amazon SWF アプリケーションは連携して動作する数多くの部分で構成されます。

  • ワークフロー実行データの論理コンテナとして使用されるドメイン

  • ワークフローのアクティビティと子ワークフローの実行の論理的順序を定義するコードコンポーネントを表す 1 つ以上のワークフロー

  • 決定タスクをポーリングし、それに応じてアクティビティまたは子ワークフローをスケジュールするワークフローワーカー (ディサイダーとも呼ばれる)。

  • それぞれがワークフローのワークの単位を表す、1 つ以上のアクティビティ

  • アクティビティタスクをポーリングし、それに応じてアクティビティメソッドを実行するアクティビティワーカー

  • ワークフローとアクティビティワーカーにリクエストを発行するために使用される によって管理されるキューである、1 つ以上のタスクリストAmazon SWF。ワークフローワーカーを想定したタスクリスト内のタスクは、決定タスクと呼ばれます。アクティビティワーカーを想定したものは、アクティビティタスクと呼ばれます。

  • ワークフローの実行を開始するワークフロースターター

バックグラウンドでは、Amazon SWF がこれらのコンポーネントの操作を調整して、AWS クラウドからのフローの連携、それらの間のデータの受け渡し、タイムアウトとハートビート通知の処理、およびワークフロー実行履歴のログ記録を行います。

前提条件

デベロッパー環境

このチュートリアルで使用する開発環境は、以下で構成されます。

  • AWS SDK for Java

  • Apache Maven (3.3.1)。

  • JDK 1.7 以降。このチュートリアルは JDK 1.8.0 を使用して開発され、テスト済みです。

  • 適切な Java テキストエディター (任意の選択)。

注記

Maven とは異なるビルドシステムを使用する場合、環境に適したステップを使用してプロジェクトを作成し、ここに示されている概念を使用して作業を行うことができます。さまざまな構築システムでの AWS SDK for Java の設定と使用の詳細は、「はじめに」で示されています。

同様に (より多くの努力が必要ですが)、ここに示すステップは、Amazon SWF をサポートしている任意の AWS SDK を使用して実装できます。

すべての必要な外部依存関係は AWS SDK for Java に含まれているため、追加でダウンロードするものはありません。

AWS アクセス

このチュートリアルを正常に進めるには、このガイドの基本設定セクションで説明されている AWS アクセスポータルにアクセスできる必要があります。

手順には、ローカル共有 credentials ファイルにコピーして貼り付ける一時的な認証情報にアクセスする方法が記載されています。貼り付ける一時的な認証情報は、Amazon SWF へのアクセス権限を持つ IAM ロールに AWS IAM Identity Center で関連付けられている必要があります。一時的な認証情報を貼り付けると、credentials ファイルは次のようになります。

[default] aws_access_key_id=AKIAIOSFODNN7EXAMPLE aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY aws_session_token=IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZVERYLONGSTRINGEXAMPLE

これらの一時的な認証情報は、default プロファイルに関連付けられます。

SWF プロジェクトの作成

  1. Maven での新しいプロジェクトの開始

    mvn archetype:generate -DartifactId=helloswf \ -DgroupId=aws.example.helloswf -DinteractiveMode=false

    これにより、標準の Maven プロジェクト構造を持つ新しいプロジェクトが作成されます。

    helloswf ├── pom.xml └── src ├── main │   └── java │   └── aws │   └── example │   └── helloswf │   └── App.java └── test └── ...

    test ディレクトリとそれに含まれるすべては、このチュートリアルでは使用しないため、無視または削除できます。また、新しいクラスに置き換えるため、App.java も削除できます。

  2. <dependencies> ブロック内で依存関係を追加することで、プロジェクトの pom.xml ファイルを編集して aws-java-sdk-simpleworkflow モジュールを追加します。

    <dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-simpleworkflow</artifactId> <version>1.11.1000</version> </dependency> </dependencies>
  3. Maven によって JDK 1.7 以降のサポートがあるプロジェクトが構築されることを確認します。プロジェクトの pom.xml に以下を追加します (<dependencies> ブロックの前または後)。

    <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.6.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>

プロジェクトのコーディング

サンプルプロジェクトは 4 つの個別のアプリケーションで構成されます。それらについて 1 つずつ説明します。

  • HelloTypes.java--プロジェクトのドメイン、アクティビティ、およびワークフロータイプデータが含まれ、他のコンポーネントと共有されます。また、SWF でのこれらのタイプの登録も処理されます。

  • ActivityWorker.java--アクティビティタスクをポーリングし、それに応じてアクティビティを実行するアクティビティワーカーを含みます。

  • WorkflowWorker.java--決定タスクをポーリングし、新しいアクティビティをスケジュールするワークフローワーカー (ディサイダー) を含みます。

  • WorkflowStarter.java--新しいワークフローの実行を開始するワークフロースターターを含みます。ワークフロースターターにより、SWF はワーカーが使用する決定とワークフロータスクを生成します。

すべてのソースファイルに共通のステップ

Java クラスを格納するために作成するすべてのファイルには、いくつか共通の事柄があります。時間を節約するため、これらのステップはプロジェクトに新しいファイルを追加するたびに暗黙的に示されます

  1. プロジェクトの src/main/java/aws/example/helloswf/ ディレクトリでファイルを作成します。

  2. 各ファイルの先頭に package 宣言を追加して名前空間を宣言します。サンプルプロジェクトでは以下を使用します。

    package aws.example.helloswf;
  3. AmazonSimpleWorkflowClient クラスおよび com.amazonaws.services.simpleworkflow.model 名前空間内の複数のクラスの import 宣言を追加します。作業を簡素化するため、以下を使用します。

    import com.amazonaws.regions.Regions; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowClientBuilder; import com.amazonaws.services.simpleworkflow.model.*;

ドメイン、ワークフロー、およびアクティビティタイプの登録

最初に、新しい実行可能クラス HelloTypes.java を作成します。このファイルには、ワークフローの各部分必要となる共有データ (アクティビティとワークフロータイプの名前とバージョン、ドメイン名、タスクリスト名など) が含まれます。

  1. テキストエディターを開き、ファイル HelloTypes.java を作成して、共通のステップに従ってパッケージ宣言とインポートを追加します。

  2. HelloTypes クラスを宣言し、登録されたアクティビティとワークフロータイプで使用する値を指定します。

    public static final String DOMAIN = "HelloDomain"; public static final String TASKLIST = "HelloTasklist"; public static final String WORKFLOW = "HelloWorkflow"; public static final String WORKFLOW_VERSION = "1.0"; public static final String ACTIVITY = "HelloActivity"; public static final String ACTIVITY_VERSION = "1.0";

    これらの値は、コード全体で使用されます。

  3. 文字列を宣言したら、AmazonSimpleWorkflowClient クラスのインスタンスを作成します。これは、AWS SDK for Java で提供される Amazon SWF メソッドの基本インタフェースです。

    private static final AmazonSimpleWorkflow swf = AmazonSimpleWorkflowClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();

    前述のスニペットでは、一時的な認証情報が default プロファイルに関連付けられていることを前提としています。別のプロファイルを使用する場合は、上記のコードを次のように変更し、profile_name を実際のプロファイル名の名前に置き換えてください。

    private static final AmazonSimpleWorkflow swf = AmazonSimpleWorkflowClientBuilder .standard() .withCredentials(new ProfileCredentialsProvider("profile_name")) .withRegion(Regions.DEFAULT_REGION) .build();
  4. SWF ドメインを登録するための新しい関数を追加します。ドメインは、数多くの関連 SWF アクティビティおよびワークフロータイプ用の論理コンテナです。SWF コンポーネントは、同じドメイン内に存在する場合にのみ相互に通信できます。

    try { System.out.println("** Registering the domain '" + DOMAIN + "'."); swf.registerDomain(new RegisterDomainRequest() .withName(DOMAIN) .withWorkflowExecutionRetentionPeriodInDays("1")); } catch (DomainAlreadyExistsException e) { System.out.println("** Domain already exists!"); }

    ドメインを登録する場合、名前 (:/| を除く 1~256 文字、制御文字、またはリテラル文字列「arn」の任意のセット) と保持期間を指定します。保持期間は、ワークフローの実行が完了してから Amazon SWF がワークフローの実行履歴データを保持する日数です。ワークフロー実行の最大保持期間は 90 日です。詳細については、「RegisterDomainRequest」を参照してください。

    その名前のドメインがすでに存在する場合、DomainAlreadyExistsException が発生します。ドメインがすでに作成されているかどうかは問題ではないため、この例外は無視できます。

    注記

    このコードは、AWS SDK for Java のメソッドを使用する場合の一般的なパターン、simpleworkflow.model 名前空間のクラスで提供されるメソッドのデータを示します。これは、チェーン可能な –0—with* メソッドを使用してインスタンス化および入力します。

  5. 新しいアクティビティタイプを登録する関数を追加します。アクティビティはワークフローのワークの単位を表します。

    try { System.out.println("** Registering the activity type '" + ACTIVITY + "-" + ACTIVITY_VERSION + "'."); swf.registerActivityType(new RegisterActivityTypeRequest() .withDomain(DOMAIN) .withName(ACTIVITY) .withVersion(ACTIVITY_VERSION) .withDefaultTaskList(new TaskList().withName(TASKLIST)) .withDefaultTaskScheduleToStartTimeout("30") .withDefaultTaskStartToCloseTimeout("600") .withDefaultTaskScheduleToCloseTimeout("630") .withDefaultTaskHeartbeatTimeout("10")); } catch (TypeAlreadyExistsException e) { System.out.println("** Activity type already exists!"); }

    アクティビティタイプは名前およびバージョンによって識別されます。これらは、登録されているドメインでこのアクティビティを他のアクティビティから一意に識別するために使用されます。アクティビティには、SWF からタスクとデータを受け取るために使用されるデフォルトのタスクリスト、アクティビティ実行の各部分にかかる時間に対する制約適用に使用できるさまざまなタイムアウトなど、数多くのオプションパラメーターも含まれます。詳細については、「RegisterActivityTypeRequest」を参照してください。

    注記

    すべてタイムアウト値は秒単位で指定されます。タイムアウトのワークフローの実行への影響の詳細については、「Amazon SWF Timeout Types」を参照してください。

登録しようとしているアクティビティタイプが既に存在する場合は、TypeAlreadyExistsException が発生します。新しいワークフロータイプを登録する関数を追加します。ワークフローディサイダーとも呼ばれ、ワークフロー実行のロジックを表します。

+

try { System.out.println("** Registering the workflow type '" + WORKFLOW + "-" + WORKFLOW_VERSION + "'."); swf.registerWorkflowType(new RegisterWorkflowTypeRequest() .withDomain(DOMAIN) .withName(WORKFLOW) .withVersion(WORKFLOW_VERSION) .withDefaultChildPolicy(ChildPolicy.TERMINATE) .withDefaultTaskList(new TaskList().withName(TASKLIST)) .withDefaultTaskStartToCloseTimeout("30")); } catch (TypeAlreadyExistsException e) { System.out.println("** Workflow type already exists!"); }

+

アクティビティタイプと同様に、ワークフロータイプは名前バージョンによって識別され、設定可能なタイムアウトがあります。詳細については、「RegisterWorkflowTypeRequest」を参照してください。

+

登録しようとしているワークフロータイプが既に存在する場合は、TypeAlreadyExistsException が発生します。最後に、main メソッドを提供してクラスを実行可能にします。これはドメイン、アクティビティタイプ、およびワークフロータイプを登録します。

+

registerDomain(); registerWorkflowType(); registerActivityType();

ここで、アプリケーションを構築および実行して登録スクリプトを実行するか、アクティビティとワークフローワーカーのコーディングを続行できます。ドメイン、ワークフロー、およびアクティビティが登録されたら、これを再度実行する必要はありません。これらのタイプは、ユーザーが自ら非推奨とするまで保持されます。

アクティビティワーカーの実装

アクティビティは、ワークフローのワークの基本的な単位です。ワークフローは、ディシジョンタスクに応じて、ロジック、実行するスケジュールアクティビティ (または実行するその他のアクション) を提供します。通常、一般的なワークフローは、同期、非同期、またはそれらの組み合わせで実行できる数多くのアクティビティで構成されます。

アクティビティワーカーは、ワークフローの決定に応じて Amazon SWF によって生成されるアクティビティタスクをポーリングするコードです。アクティビティタスクを受け取ると、対応するアクティビティを実行し、ワークフローに成功/失敗の応答を返します。

単一のアクティビティを駆動するシンプルなアクティビティワーカーを実装します。

  1. テキストエディターを開き、ファイル ActivityWorker.java を作成して、共通のステップに従ってパッケージ宣言とインポートを追加します。

    import com.amazonaws.regions.Regions; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowClientBuilder; import com.amazonaws.services.simpleworkflow.model.*;
  2. ActivityWorker クラスをファイルに追加し、Amazon SWF を操作するために使用する SWF クライアントを保持するためのデータメンバーを提供します。

    private static final AmazonSimpleWorkflow swf = AmazonSimpleWorkflowClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
  3. アクティビティとして使用するメソッドを追加します。

    private static String sayHello(String input) throws Throwable { return "Hello, " + input + "!"; }

    アクティビティは単純に文字列を受け取り、それをあいさつに組み合わせて、結果を返します。このアクティビティで例外が発生する可能性はほとんどありませんが、何か問題が発生した場合にエラーを発生させるアクティビティを設計することをお勧めします。

  4. アクティビティタスクのポーリングメソッドとして使用する main メソッドを追加します。最初に、アクティビティタスクについてタスクリストをポーリングするコードを追加します。

    System.out.println("Polling for an activity task from the tasklist '" + HelloTypes.TASKLIST + "' in the domain '" + HelloTypes.DOMAIN + "'."); ActivityTask task = swf.pollForActivityTask( new PollForActivityTaskRequest() .withDomain(HelloTypes.DOMAIN) .withTaskList( new TaskList().withName(HelloTypes.TASKLIST))); String task_token = task.getTaskToken();

    アクティビティは SWF クライアントの pollForActivityTask メソッドを呼び出して Amazon SWF からタスクを受け取り、渡された PollForActivityTaskRequest で使用するドメインとタスクリストを指定します。

    タスクを受け取ったら、タスクの getTaskToken メソッドを呼び出して、その固有の識別子を取得します。

  5. 次に、入ってきたタスクを処理するコードを記述します。main メソッドで、タスクをポーリングし、タスクトークンを取得するコードの直後に以下を追加します。

    if (task_token != null) { String result = null; Throwable error = null; try { System.out.println("Executing the activity task with input '" + task.getInput() + "'."); result = sayHello(task.getInput()); } catch (Throwable th) { error = th; } if (error == null) { System.out.println("The activity task succeeded with result '" + result + "'."); swf.respondActivityTaskCompleted( new RespondActivityTaskCompletedRequest() .withTaskToken(task_token) .withResult(result)); } else { System.out.println("The activity task failed with the error '" + error.getClass().getSimpleName() + "'."); swf.respondActivityTaskFailed( new RespondActivityTaskFailedRequest() .withTaskToken(task_token) .withReason(error.getClass().getSimpleName()) .withDetails(error.getMessage())); } }

    タスクトークンが null でない場合、アクティビティメソッド (sayHello) の実行を開始し、タスクとともに送信された入力データを指定することができます。

    タスクが成功した場合 (エラーが生成されなかった場合)、ワーカーは、タスクトークンとアクティビティの結果データを含む RespondActivityTaskCompletedRequest オブジェクトを使用して SWF クライアントの respondActivityTaskCompleted メソッドを呼び出すことにより、SWF に応答します。

    一方、タスクが失敗した場合、respondActivityTaskFailedRespondActivityTaskFailedRequest オブジェクトとともに メソッドを呼び出し、タスクトークンとエラーに関する情報を渡して応答します。

注記

このアクティビティは、強制終了した場合は適切にシャットダウンしません。このチュートリアルの対象外ですが、このアクティビティワーカーの代替の実装が、付随するトピック「アクティビティおよびワークフローワーカーの適切なシャットダウン」で示されています。

ワークフローワーカーの実装

ワークフローは、ワークフローワーカーと呼ばれるコードに置かれます。ワークフローワーカーは、ドメイン内の Amazon SWF によって送信され、ワークフロータイプが登録されたデフォルトのタスクリスト上にある決定タスクをポーリングします。

ワークフローワーカーがタスクを受信すると、何らかの決定 (通常は新しいアクティビティタスクをスケジュールするかどうか) を行い、適切なアクション (アクティビティのスケジューリングなど) を実行します。

  1. テキストエディターを開き、ファイル WorkflowWorker.java を作成して、共通のステップに従ってパッケージ宣言とインポートを追加します。

  2. いくつかのインポートをファイルに追加します。

    import com.amazonaws.regions.Regions; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowClientBuilder; import com.amazonaws.services.simpleworkflow.model.*; import java.util.ArrayList; import java.util.List; import java.util.UUID;
  3. WorkflowWorker クラスを宣言し、SWF メソッドへのアクセスに使用する AmazonSimpleWorkflowClient クラスのインスタンスを作成します。

    private static final AmazonSimpleWorkflow swf = AmazonSimpleWorkflowClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
  4. main メソッドを追加します。このメソッドは連続してループし、SWF クライアントの pollForDecisionTask メソッドを使用して決定タスクをポーリングします。PollForDecisionTaskRequest によって詳細が提供されます。

    PollForDecisionTaskRequest task_request = new PollForDecisionTaskRequest() .withDomain(HelloTypes.DOMAIN) .withTaskList(new TaskList().withName(HelloTypes.TASKLIST)); while (true) { System.out.println( "Polling for a decision task from the tasklist '" + HelloTypes.TASKLIST + "' in the domain '" + HelloTypes.DOMAIN + "'."); DecisionTask task = swf.pollForDecisionTask(task_request); String taskToken = task.getTaskToken(); if (taskToken != null) { try { executeDecisionTask(taskToken, task.getEvents()); } catch (Throwable th) { th.printStackTrace(); } } }

    タスクを受け取ったら、その getTaskToken メソッドを呼び出します。これにより、タスクの識別に使用できる文字列が返されます。返されたトークンが null でない場合、executeDecisionTask メソッドでさらに処理し、タスクトークンおよびそのタスクで送信された HistoryEvent オブジェクトのリストを渡します。

  5. executeDecisionTask メソッドを追加し、タスクトークン (String) および HistoryEvent リストを受け取ります。

    List<Decision> decisions = new ArrayList<Decision>(); String workflow_input = null; int scheduled_activities = 0; int open_activities = 0; boolean activity_completed = false; String result = null;

    また、以下のような項目を追跡するためにいくつかのデータメンバーを設定します。

    • タスクの処理結果を報告するために使用される Decision オブジェクトのリスト。

    • "WorkflowExecutionStarted" イベントによって提供されるワークフロー入力を保持する文字列。

    • すでにスケジュールされているか、現在実行中の場合に、同じアクティビティのスケジュールを回避するためにスケジュールされ、開いている (実行中) のアクティビティの数。

    • アクティビティが完了したことを示すブール。

    • ワークフローの結果として返すためにアクティビティの結果を保持する文字列。

  6. 次に、executeDecisionTask メソッドによって報告されたイベントタイプに基づいて、タスクとともに送信された HistoryEvent オブジェクトを処理するコードを getEventType に追加します。

    System.out.println("Executing the decision task for the history events: ["); for (HistoryEvent event : events) { System.out.println(" " + event); switch(event.getEventType()) { case "WorkflowExecutionStarted": workflow_input = event.getWorkflowExecutionStartedEventAttributes() .getInput(); break; case "ActivityTaskScheduled": scheduled_activities++; break; case "ScheduleActivityTaskFailed": scheduled_activities--; break; case "ActivityTaskStarted": scheduled_activities--; open_activities++; break; case "ActivityTaskCompleted": open_activities--; activity_completed = true; result = event.getActivityTaskCompletedEventAttributes() .getResult(); break; case "ActivityTaskFailed": open_activities--; break; case "ActivityTaskTimedOut": open_activities--; break; } } System.out.println("]");

    ワークフローでは、以下が最も重要です。

    • ワークフローの実行が開始したことを示し (通常はワークフローの最初のアクティビティを実行する必要があることを意味します)、ワークフローに渡される最初の入力を提供する、"WorkflowExecutionStarted" イベント。この場合、これはあいさつの名前部分であるため、アクティビティの実行をスケジュールするときに使用する文字列に保存されます。

    • スケジュールされたアクティビティが完了すると送信される、"ActivityTaskCompleted" イベント。イベントデータには、完了したアクティビティの戻り値も含まれます。1 つのアクティビティのみがあるため、この値をワークフロー全体の結果として使用します。

    他のイベントタイプは、ワークフローで必要な場合に使用できます。各イベントタイプの詳細については、HistoryEvent クラスの説明を参照してください。

    + 注: switch ステートメントの文字列は Java 7 で導入されました。以前のバージョンの Java を使用している場合は、EventType クラスを使用して、history_event.getType() で返される String を列挙値に変換し、必要に応じて String に戻すことができます。

EventType et = EventType.fromValue(event.getEventType());
  1. switch ステートメントの後で、受け取ったタスクに応じて、適切な決定を使用して応答するコードを追加します。

    if (activity_completed) { decisions.add( new Decision() .withDecisionType(DecisionType.CompleteWorkflowExecution) .withCompleteWorkflowExecutionDecisionAttributes( new CompleteWorkflowExecutionDecisionAttributes() .withResult(result))); } else { if (open_activities == 0 && scheduled_activities == 0) { ScheduleActivityTaskDecisionAttributes attrs = new ScheduleActivityTaskDecisionAttributes() .withActivityType(new ActivityType() .withName(HelloTypes.ACTIVITY) .withVersion(HelloTypes.ACTIVITY_VERSION)) .withActivityId(UUID.randomUUID().toString()) .withInput(workflow_input); decisions.add( new Decision() .withDecisionType(DecisionType.ScheduleActivityTask) .withScheduleActivityTaskDecisionAttributes(attrs)); } else { // an instance of HelloActivity is already scheduled or running. Do nothing, another // task will be scheduled once the activity completes, fails or times out } } System.out.println("Exiting the decision task with the decisions " + decisions);
    • まだアクティビティがスケジュールされていない場合、ScheduleActivityTask 決定で応答します。これにより、Amazon SWF が次にスケジュールするアクティビティに関する情報が、Amazon SWF がアクティビティに送信するデータを含めて、ScheduleActivityTaskDecisionAttributes 構造で提供されます。

    • アクティビティが完了すると、全体のワークフローが完了したと見なし、CompletedWorkflowExecution 決定で応答します。CompleteWorkflowExecutionDecisionAttributes 構造に入力し、完了したワークフローに関する詳細を提供します。この場合、アクティビティの結果を返します。

    いずれの場合も、メソッドの先頭で Decision リストに決定情報が追加されます。

  2. タスクの処理中に収集された Decision オブジェクトのリストを返して、決定タスクを完了します。このコードを、これまで記述した executeDecisionTask メソッドの最後に追加します。

    swf.respondDecisionTaskCompleted( new RespondDecisionTaskCompletedRequest() .withTaskToken(taskToken) .withDecisions(decisions));

    SWF クライアントの respondDecisionTaskCompleted メソッドは、タスクと、Decision オブジェクトのリストを識別するタスクトークンを受け取ります。

ワークフロースターターの実装

最後に、ワークフロー実行を開始するコードを書きます。

  1. テキストエディターを開き、ファイル WorkflowStarter.java を作成して、共通のステップに従ってパッケージ宣言とインポートを追加します。

  2. WorkflowStarter クラスを追加します。

    package aws.example.helloswf; import com.amazonaws.regions.Regions; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowClientBuilder; import com.amazonaws.services.simpleworkflow.model.*; public class WorkflowStarter { private static final AmazonSimpleWorkflow swf = AmazonSimpleWorkflowClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build(); public static final String WORKFLOW_EXECUTION = "HelloWorldWorkflowExecution"; public static void main(String[] args) { String workflow_input = "{SWF}"; if (args.length > 0) { workflow_input = args[0]; } System.out.println("Starting the workflow execution '" + WORKFLOW_EXECUTION + "' with input '" + workflow_input + "'."); WorkflowType wf_type = new WorkflowType() .withName(HelloTypes.WORKFLOW) .withVersion(HelloTypes.WORKFLOW_VERSION); Run run = swf.startWorkflowExecution(new StartWorkflowExecutionRequest() .withDomain(HelloTypes.DOMAIN) .withWorkflowType(wf_type) .withWorkflowId(WORKFLOW_EXECUTION) .withInput(workflow_input) .withExecutionStartToCloseTimeout("90")); System.out.println("Workflow execution started with the run id '" + run.getRunId() + "'."); } }

    WorkflowStarter クラスは単一のメソッド main で構成されます。このメソッドはコマンドラインで渡されたオプションの引数を、ワークフローの入力データとして受け取ります。

    SWF のクライアントメソッド startWorkflowExecution は、StartWorkflowExecutionRequest オブジェクトを入力として受け取ります。ここで、ドメインと実行するワークフロータイプの指定に加えて、以下を指定します。

    • 人間が読み取れるワークフロー実行の名前

    • ワークフローの入力データ (この例のコマンドラインで提供)

    • ワークフロー全体の実行時間 (秒単位) を表すタイムアウト値

    が返す RunstartWorkflowExecution オブジェクトは、実行 ID を提供します。これは、ワークフロー実行の Amazon SWF の履歴でこの特定のワークフロー実行を識別するために使用できる値です。

    + 注: 実行 ID は Amazon SWF によって生成され、ワークフローの実行を開始するときに渡すワークフロー実行名と同じではありません

例の作成

Maven でサンプルプロジェクトを構築するには、helloswf ディレクトリに移動し、次のように入力します。

mvn package

結果的に生じる helloswf-1.0.jartarget ディレクトリに生成されます。

例の実行

この例は、4 つの異なる実行可能クラスで構成されます。これらは互いに独立して実行されます。

注記

Linux、macOS、または Unix システムを使用している場合、それらのすべてを 1 つずつ、1 つのターミナルウィンドウで実行できます。Windows を実行している場合は、2 つの追加インスタンスのコマンドラインを開き、それぞれの helloswf ディレクトリに移動します。

Java クラスパスの設定

Maven によって依存関係が処理されましたが、この例を実行するには、Java のクラスパスで AWS SDK ライブラリとその依存関係を指定する必要があります。CLASSPATH 環境変数を AWS SDK ライブラリの場所に設定し、必要な依存関係を含む SDK の third-party/lib ディレクトリに設定できます。

export CLASSPATH='target/helloswf-1.0.jar:/path/to/sdk/lib/*:/path/to/sdk/third-party/lib/*' java example.swf.hello.HelloTypes

または、 java コマンドの -cp オプションを使用して、各アプリケーションの実行中にクラスパスを設定できます。

java -cp target/helloswf-1.0.jar:/path/to/sdk/lib/*:/path/to/sdk/third-party/lib/* \ example.swf.hello.HelloTypes

使用するスタイルはユーザーが選択できます。コードが問題なく作成されても、例を実行しようとすると一連の "NoClassDefFound" エラーが表示される場合、クラスパスが正しく設定されていない可能性があります。

ドメイン、ワークフロー、およびアクティビティタイプの登録

ワーカーおよびワークフロースターターを実行する前に、ドメイン、ワークフロータイプ、およびアクティビティタイプを登録する必要があります。これを行うコードは、ドメイン、ワークフロー、およびアクティビティタイプの登録で実装しました。

構築後に CLASSPATH を設定した場合、次のコマンドを実行して登録コードを実行できます。

echo 'Supply the name of one of the example classes as an argument.'

アクティビティおよびワークフローワーカーの開始

これでタイプが登録されたため、アクティビティとワークフローワーカーを開始できます。これらは継続して実行され、強制終了されるまでタスクをポーリングするため、別のターミナルウィンドウで実行するか、Linux、macOS、または Unix で実行している場合は & 演算子を使用して、実行時にそれぞれが別のプロセスとして生成されるようにできます。

echo 'If there are arguments to the class, put them in quotes after the class name.' exit 1

別のウィンドウでこれらのコマンドを実行している場合は、各行から最終的な & 演算子を省略します。

ワークフロー実行の開始

これでアクティビティとワークフローワーカーがポーリングを実行しているため、ワークフロー実行を開始できます。このプロセスは、ワークフローが完了したステータスを返すまで実行されます。(& オペレーターを使用して新しく生成されたプロセスとしてワーカーを実行していない限り) このプロセスは新しいターミナルウィンドウで実行する必要があります。

fi
注記

独自の入力データを提供する場合 (最初にワークフロー、次にアクティビティに渡されます)、コマンドラインに追加します。例:

echo "## Running $className..."

ワークフロー実行を開始すると、両方のワーカーおよびワークフロー実行そのものによって提供された出力が表示され始めます。ワークフローが最終的に完了すると、その出力が画面に表示されます。

この例の完全なソース。

この例の完全なソースは、Github の aws-java-developer-guide レポジトリで参照できます。

詳細情報