

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# HelloWorldWorkflow 應用程式
<a name="getting-started-example-helloworldworkflow"></a>

雖然基本 [HelloWorld](getting-started-example-helloworld.md) 範例的結構類似於工作流程，但它與 Amazon SWF 工作流程有幾個關鍵方面不同：


**傳統和 Amazon SWF 工作流程應用程式**  

| HelloWorld | Amazon SWF 工作流程 | 
| --- | --- | 
| 以單一程序在本機執行。 | 以多個程序的形式執行，這些程序可以分散到多個系統，包括 Amazon EC2 執行個體、私有資料中心、用戶端電腦等。甚至不必執行相同的作業系統。 | 
| 活動為同步的方法，完成後才予以解鎖。 | 活動由非同步方法代表，其會立即傳回，並於等待活動完成期間，允許工作流程執行其他任務。 | 
| 工作流程工作者透過呼叫合適的方法與活動工作者互動。 | 工作流程工作者使用 HTTP 請求與活動工作者互動，Amazon SWF 充當中介裝置。 | 
| 工作流程啟動者透過呼叫合適的方法與工作流程工作者互動。 | 工作流程入門使用 HTTP 請求與工作流程工作者互動，Amazon SWF 充當中介裝置。 | 

您可以從頭開始實作分散式非同步工作流程應用程式，例如讓您的工作流程工作者透過 Web 服務呼叫，直接與活動工作者互動。但是，您必須接著實作所有必要的複雜程式碼，藉以管理多項活動的非同步執行、處理資料流程等。 AWS Flow Framework 適用於 Java 和 Amazon SWF 的 負責處理所有這些詳細資訊，這可讓您專注於實作商業邏輯。

HelloWorldWorkflow 是 HelloWorld 的修改版本，作為 Amazon SWF 工作流程執行。下圖摘要說明這兩個應用程式的運作方式。

![\[Hello World 的 Conventional 和 Amazon SWF 版本！\]](http://docs.aws.amazon.com/zh_tw/amazonswf/latest/awsflowguide/images/workflow_conceptual_welcome.png)


HelloWorld 以單一程序執行，且啟動者、工作流程工作者與活動工作者使用傳統的方法呼叫互動。透過 `HelloWorldWorkflow`，啟動者、工作流程工作者和活動工作者是使用 HTTP 請求透過 Amazon SWF 互動的分散式元件。Amazon SWF 會透過維護工作流程和活動任務的清單來管理互動，而這些任務會分派至各自的元件。本節說明 HelloWorldWorkflow 的框架運作方式。

HelloWorldWorkflow 的實作方式是使用 AWS Flow Framework 適用於 Java 的 API，可處理在背景中與 Amazon SWF 互動的有時複雜詳細資訊，並大幅簡化開發程序。您可以使用與 HelloWorld 相同的專案，HelloWorld 已針對 Java 應用程式設定 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 註冊 Amazon SWF 帳戶。 [https://aws.amazon.com/swf/](https://aws.amazon.com/swf/)
+ 登入 AWS 管理主控台 ，然後選取 Amazon SWF 服務。
+ 選擇右上角的**管理網域**並註冊新的 Amazon SWF 網域。「網域」**是應用程式資源的邏輯容器，例如工作流程和活動類型及工作流程執行。您可使用任何便利的網域名稱，在演練時會使用 "helloWorldWalkthrough"。

若要實作 HelloWorldWorkflow，請在您的專案目錄中建立 helloWorld.HelloWorld 套件的副本，並命名為 helloWorld.HelloWorldWorkflow。下列各節說明如何修改原始 HelloWorld 程式碼以使用 AWS Flow Framework 適用於 Java 的 ，並以 Amazon SWF 工作流程應用程式的形式執行。

## HelloWorldWorkflow 活動工作者
<a name="getting-started-example-helloworldworkflow.activities"></a>

HelloWorld 實作其活動工作者為單一類別。 AWS Flow Framework 適用於 Java 的 活動工作者有三個基本元件：
+ 執行實際任務*的活動方法*是在 界面中定義，並在相關類別中實作。
+ [ActivityWorker](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/simpleworkflow/flow/ActivityWorker.html) 類別會管理活動方法和 Amazon SWF 之間的互動。
+ 「活動主機」**應用程式會註冊活動工作者並予以啟動，且會處理清理。

本節將討論活動方法，其他兩個類別待後文討論。

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 不需要此界面，但適用於 Java AWS Flow Framework 應用程式的 。請注意，界面定義本身並未變更。不過，您必須將 Java 註釋 AWS Flow Framework 的兩個 [@ActivityRegistrationOptions](annotations.md#annotations-activityregistration)和 [@Activities](annotations.md#annotations-activities)套用至界面定義。註釋提供組態資訊，並指示 AWS Flow Framework for Java 註釋處理器使用介面定義來產生*活動用戶端*類別，稍後會進行討論。

`@ActivityRegistrationOptions` 有數個具名值，用以設定活動行為。HelloWorldWorkflow 指定兩種逾時：
+ `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 工作流程工作者有三個基本元件。
+ 「工作流程實作」**類別，會執行工作流程相關的任務。
+ 「活動用戶端」**類別，基本上為活動類別的代理，而工作流程實作會用以非同步執行活動方法。
+ [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 對於適用於 Java 的 應用程式而言至關重要。您必須[@WorkflowRegistrationOptions](annotations.md#annotations-workflowregistrationoptions)將 Java 註釋 AWS Flow Framework 的兩個 [@工作流程](annotations.md#annotations-workflow)和 套用至工作流程界面定義。註釋提供組態資訊，並指示 AWS Flow Framework for Java 註釋處理器根據界面產生工作流程用戶端類別，如稍後所討論。

`@Workflow` 有一個選用參數 *dataConverter*，通常與其預設值 NullDataConverter 搭配使用，這表示應使用 JsonDataConverter。

`@WorkflowRegistrationOptions` 也有數個選擇性參數，可用以設定工作流程工作者。在這裡，我們將工作流程執行`defaultExecutionStartToCloseTimeoutSeconds`的時間設定為 3600 秒 (1 小時）。

`GreeterWorkflow` 界面定義和 HelloWorld 有一項重大差異：[@Execute](annotations.md#annotations-execute) 註釋。工作流程界面指定可由應用程式呼叫的方法 (例如工作流程啟動者)，並限定在少數幾個方法，各有特定的角色。框架不會指定工作流程界面方法的名稱或參數清單；您可以使用適合您工作流程的名稱和參數清單，並套用 AWS Flow Framework 適用於 Java 的 註釋來識別方法的角色。

`@Execute` 有兩個用途：
+ 將 `greet` 識別為工作流程的進入點，即為工作流程啟動者呼叫以啟動工作流程的方法。一般而言，進入點可採用一或多個參數，讓啟動者初始化工作流程，但此範例不需要初始化。
+ 指出工作流程的版本編號，能夠讓您追蹤所產生的不同工作流程實作。若要在向 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，但有兩項重要差異。
+ `GreeterWorkflowImpl` 建立 `GreeterActivitiesClientImpl` 的執行個體 (活動用戶端)，不是 `GreeterActivitiesImpl` 的執行個體，並在用戶端物件上呼叫方法來執行活動。
+ 名稱和歡迎活動傳回 `Promise<String>` 物件，不是 `String` 物件。

HelloWorld 為在本機以單一程序執行的標準 Java 應用程式，所以 `GreeterWorkflowImpl` 可以僅透過建立 `GreeterActivitiesImpl` 執行個體、依序呼叫方法，並將傳回值從一個活動傳遞到下一個活動，藉此實作工作流程拓撲。使用 Amazon SWF 工作流程時，活動的任務仍會由來自 的活動方法執行`GreeterActivitiesImpl`。不過，方法不一定會在和工作流程相同的程序中執行 (甚至可能不在同一個系統中執行)，且工作流程需非同步執行活動。這些要求會引起下列問題：
+ 如何執行可能在不同程序，甚或是不同系統中執行的活動方法。
+ 如何非同步執行活動方法。
+ 如何管理活動的輸入和傳回值。例如，如果活動 A 的傳回值是活動 B 的輸入，您必須確保活動 B 不會在活動 A 完成前執行。

您可以使用熟悉的 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** 對話方塊的 **Order and Export** 索引標籤頂端。

工作流程工作者透過呼叫對應的用戶端方法執行活動。方法是非同步的，並會立即傳回 `Promise<T>` 物件，其中 `T` 是活動的傳回類型。傳回的 `Promise<T>` 物件基本上是活動方法最終傳回值的預留位置。
+ 當活動用戶端方法傳回時，`Promise<T>` 物件一開始是「未就緒狀態」**，表示物件尚未能代表有效的傳回值。
+ 當對應的活動方法完成其任務並傳回之後，框架會將傳回值指派給 `Promise<T>` 物件，讓物件進入「就緒狀態」**。

### Promise<T> 類型
<a name="getting-started-example-helloworldworkflow.workflow.promise"></a>

`Promise<T>` 物件的主要用途為管理非同步元件間的資料流程，並控制其執行的時機。此物件讓您的應用程式不必明確管理同步，或依賴計時器等機制確保非同步元件不提前執行。當您呼叫活動用戶端方法時，其會立即傳回，但框架會延遲執行對應的活動方法，直到任何輸入 `Promise<T>` 物件就緒且代表有效的資料為止。

就 `GreeterWorkflowImpl` 而言，這三個活動用戶端方法都會立即傳回。就 `GreeterActivitiesImpl` 而言，框架在 `name` 完成前不會呼叫 `getGreeting`，在 `getGreeting` 完成前不會呼叫 `say`。

使用 `Promise<T>` 將資料從一項活動傳遞到下一項活動，`HelloWorldWorkflow` 不僅能確保活動方法不嘗試使用無效的資料，還能控制何時執行活動及暗示定義工作流程拓撲。將每項活動的 `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)

若要建立活動和工作流程實作與對應之工作者物件的關聯，您要實作可執行下列作業的一或多個工作者應用程式：
+ 向 Amazon SWF 註冊工作流程或活動。
+ 建立工作者物件並建立其與工作流程或活動工作者實作的關聯。
+ 引導工作者物件開始與 Amazon SWF 通訊。

如果您想要將工作流程和活動執行為不同的程序，您必須實作不同的工作流程和活動工作者主機。如需範例，請參閱「[HelloWorldWorkflowDistributed 應用程式](getting-started-example-helloworldworkflowdistributed.md)」。為簡化起見，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 = "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();
   }
}
```

`GreeterWorker` 沒有 HelloWorld 相應實物，所以您必須將名為 `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` 定義兩個字串常數。
+ `domain` 是您設定 Amazon SWF 帳戶時建立的工作流程的 Amazon SWF 網域名稱。 `HelloWorldWorkflow` 假設您正在 "helloWorldWalkthrough" 網域中執行工作流程。
+ `taskListToPoll` 是 Amazon SWF 用來管理工作流程和活動工作者之間通訊的任務清單名稱。您可將名稱設成任何方便的字串。HelloWorldWorkflow 的工作流程和活動任務清單都使用 "HelloWorldList"。在幕後，名稱會以不同的命名空間作結，因此這兩份清單是截然不同的。

`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`清單中選取 。如果您在**導覽**窗格中選擇**工作流程類型**，您應該會看到 `GreeterWorkflow.greet`：

![\[HelloWorldWorkflow 工作流程類型\]](http://docs.aws.amazon.com/zh_tw/amazonswf/latest/awsflowguide/images/Workflow_Type.png)


如果您選擇 **Activity Types** (活動類型)，即會顯示 `GreeterActivities` 方法：

![\[HelloWorldWorkflow 活動類型\]](http://docs.aws.amazon.com/zh_tw/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 網域名稱傳遞給建構函式。用戶端 factory 物件是由框架的註釋處理器所建立，只要將 "ClientExternalFactoryImpl" 附加至工作流程界面名稱後面即可建立物件名稱。

1. 透過呼叫 factory 物件的 `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 執行工作流程，您需要回到 factory 並使用另外指定的 ID 建立新的用戶端。

工作流程用戶端公開 `GreeterMain` 呼叫以開始工作流程的 `greet` 方法，因為 `greet()` 是以 `@Execute` 註釋指定的方法。

**注意**  
註釋處理器也會建立內部用戶端 factory 物件，用以建立子工作流程。如需詳細資訊，請參閱[子工作流程執行](childworkflow.md)。

如果 `GreeterWorker` 還在執行，請暫時予以關機，然後執行 `GreeterMain`。您現在應該會在 Amazon SWF 主控台的作用中工作流程執行清單中看到 someID：。

![\[HelloWorldWorkflow 工作流程執行\]](http://docs.aws.amazon.com/zh_tw/amazonswf/latest/awsflowguide/images/Active_Execution.png)


如果您選擇 `someID` 和選擇 **Events** (事件) 標籤，即會顯示事件：

![\[HelloWorldWorkflow 初始工作流程事件\]](http://docs.aws.amazon.com/zh_tw/amazonswf/latest/awsflowguide/images/Events1.png)


**注意**  
如果之前已啟動 `GreeterWorker`，且其還在執行，您會看到一份較長的事件清單，內含最近討論過的原因。停止 `GreeterWorker` 並再次嘗試執行 `GreaterMain`。

**Events** (事件) 標籤只顯示兩個事件：
+ `WorkflowExecutionStarted` 表示工作流程已開始執行。
+ `DecisionTaskScheduled` 表示 Amazon SWF 已將第一個決策任務排入佇列。

在第一個決策任務封鎖工作流程的原因是，工作流程分散到兩個應用程式 `GreeterMain` 和 `GreeterWorker`。`GreeterMain`​ 已啟動工作流程執行，但 `GreeterWorker`​ 未執行，所以工作者未輪詢清單與執行任務。應用程式 您可單獨執行任一應用程式，但工作流程執行需要兩者，才能在第一項決策任務後繼續進行。如果您現在執行 `GreeterWorker`，則工作流程和活動工作者會開始輪詢，各種任務會迅速完成。如果您現在勾選 `Events` (事件) 標籤，即會顯示第一批次的事件。

![\[HelloWorldWorkflow 完成工作流程事件\]](http://docs.aws.amazon.com/zh_tw/amazonswf/latest/awsflowguide/images/Events2.png)


您可以選擇個別事件以取得詳細資訊。當您完成查看時，工作流程應該已列印「Hello World！」 至您的 主控台。

工作流程完成後，即不會出現在作用中的執行清單上。但您若想予以檢閱，請選擇 **Closed** (已結束) 執行狀態按鈕，然後選擇 **List Executions** (列出執行)。這會顯示指定網域 (`helloWorldWalkthrough`) 中所有已完成但未超過保留期的工作流程執行個體，其中保留期已於您建立網域時指定。

![\[HelloWorldWorkflow 已完成工作流程\]](http://docs.aws.amazon.com/zh_tw/amazonswf/latest/awsflowguide/images/Closed_Workflows.png)


請注意，每個工作流程執行個體都有唯一的 **Run ID** (執行 ID) 值。您可以將相同的工作流程 ID 用於不同的工作流程執行個體，但一次只能用於一個作用中的執行。