

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

# 工作流程實作
<a name="workflowimpl"></a>

若要實作工作流程，您可以撰寫可實作所需 `@Workflow` 界面的類別。例如，可以如下述實作範例工作流程界面 (`MyWorkflow`)：

```
public class MyWFImpl implements MyWorkflow
{
  MyActivitiesClient client = new MyActivitiesClientImpl();
  @Override
  public void startMyWF(int a, String b){
    Promise<Integer> result = client.activity1();
    client.activity2(result);
  }
  @Override
  public void signal1(int a, int b, String c){
    //Process signal
     client.activity2(a + b);
  }
}
```

此類別中的 `@Execute` 方法是工作流程邏輯的進入點。由於架構會在處理決策任務時使用重播來重建物件狀態，因此會為每個決策任務建立新的物件。

在 `@Workflow` 界面的 `@Execute` 方法中，不允許使用 `Promise<T>` 做為參數。這麼做的原因是進行非同步呼叫純粹是發起人的決策。工作流程實作本身不是取決於呼叫是同步還是非同步。因此，產生的用戶端界面具有採用 `Promise<T>` 參數的多載，以非同步呼叫這些方法。

`@Execute` 方法的傳回類型只能是 `void` 或 `Promise<T>`。請注意，對應外部用戶端的傳回類型是 `void`，而不是 `Promise<>`。由於外部用戶端不適用於非同步程式碼，因此外部用戶端不會傳回`Promise`物件。若要取得外部陳述的工作流程執行結果，您可以設計工作流程，透過 活動更新外部資料存放區中的狀態。Amazon SWF 的可見APIs 也可用於擷取工作流程結果以進行診斷。不建議您使用可見性 APIs 擷取工作流程執行的結果作為一般實務，因為 Amazon SWF 可能會調節這些 API 呼叫。可見度 API 需要您使用 `WorkflowExecution` 結構來識別工作流程執行。您可以呼叫 `getWorkflowExecution` 方法，以從產生的工作流程用戶端取得此結構。此方法會傳回 `WorkflowExecution` 結構，其對應至用戶端所繫結的工作流程執行。如需可見性 [API 的詳細資訊，請參閱 Amazon Simple Workflow Service API 參考](https://docs.aws.amazon.com/amazonswf/latest/apireference/)。 APIs 

從工作流程實作呼叫活動時，您應該使用產生的活動用戶端。同樣地，若要傳送訊號，請使用產生的工作流程用戶端。

## 決策內容
<a name="workflowimpl.decisioncontext"></a>

只要框架執行工作流程程式碼，框架就會提供環境內容。此內容提供可在工作流程實作 (例如建立計時器) 中存取的內容專屬功能。如需詳細資訊，請參閱「[執行內容](executioncontext.md)」小節。

## 公開執行狀態
<a name="workflowimpl.executionstate"></a>

Amazon SWF 可讓您在工作流程歷史記錄中新增自訂狀態。工作流程執行報告的最新狀態會透過對 Amazon SWF 服務和 Amazon SWF 主控台的可見性呼叫傳回給您。例如，在訂單處理工作流程中，您可以報告不同階段的訂單狀態，例如「收到訂單」、「送出訂單」等等。在 AWS Flow Framework 適用於 Java 的 中，這會透過工作流程界面上標註註釋的方法來完成`@GetState`。決策者完成決策任務的處理時，就會呼叫此方法以從工作流程實作取得最新狀態。除了可見度呼叫之外，也可以使用產生的外部用戶端 (在內部使用可見度 API 呼叫) 來擷取狀態。

下列範例示範如何設定執行內容。

```
@Workflow
@WorkflowRegistrationOptions(defaultExecutionStartToCloseTimeoutSeconds = 60,
               defaultTaskStartToCloseTimeoutSeconds = 10)
public interface PeriodicWorkflow {

    @Execute(version = "1.0")
    void periodicWorkflow();

    @GetState
    String getState();
}

@Activities(version = "1.0")
@ActivityRegistrationOptions(defaultTaskScheduleToStartTimeoutSeconds = 300,
                             defaultTaskStartToCloseTimeoutSeconds = 3600)
public interface PeriodicActivity {
    void activity1();

}

public class PeriodicWorkflowImpl implements PeriodicWorkflow {

    private DecisionContextProvider contextProvider
               = new DecisionContextProviderImpl();

    private WorkflowClock clock
               = contextProvider.getDecisionContext().getWorkflowClock();

    private PeriodicActivityClient activityClient
               = new PeriodicActivityClientImpl();

    private String state;

    @Override
    public void periodicWorkflow() {
        state = "Just Started";
        callPeriodicActivity(0);
    }

    @Asynchronous
    private void callPeriodicActivity(int count,
                                      Promise<?>... waitFor)
    {
        if(count == 100) {
            state = "Finished Processing";
            return;
        }

        // call activity
        activityClient.activity1();

        // Repeat the activity after 1 hour.
        Promise<Void> timer = clock.createTimer(3600);
        state = "Waiting for timer to fire. Count = "+count;
        callPeriodicActivity(count+1, timer);
    }

    @Override
    public String getState() {
        return state;
    }
}

public class PeriodicActivityImpl implements PeriodicActivity
{
@Override
      public static void activity1()
   {
      ...
    }
}
```

隨時可以使用產生的外部用戶端來擷取工作流程執行的最新狀態。

```
PeriodicWorkflowClientExternal client
        = new PeriodicWorkflowClientExternalFactoryImpl().getClient();
System.out.println(client.getState());
```

在上述範例中，會報告各種階段的執行狀態。工作流程執行個體啟動時，`periodicWorkflow` 會將初始狀態報告為「剛啟動」('Just Started')。每個 `callPeriodicActivity` 呼叫接著都會更新工作流程狀態。呼叫 `activity1` 100 次之後，會傳回方法，並完成工作流程執行個體。

## 工作流程區域變數
<a name="workflowimpl.workflowlocals"></a>

您有時可能需要在工作流程實作中使用靜態變數。例如，您可能想要在工作流程實作中，存放能從多種位置 (類別可能不同) 存取的計數器。不過，您無法依賴工作流程中的靜態變數，原因是靜態變數是在多個執行緒之間共享，而這會發生問題，因為工作者可能會同時處理不同執行緒上的不同決策任務。或者，您可以將這類狀態存放在工作流程實作的欄位中，但您接著需要傳遞實作物件。為了解決此需求，框架會提供 `WorkflowExecutionLocal<?>` 類別。任何需要具有靜態變數 (例如語意) 的狀態都應該使用 `WorkflowExecutionLocal<?>` 保持為執行個體區域變數。您可以宣告和使用這類型的靜態變數。例如，在下列程式碼片段中，`WorkflowExecutionLocal<String>` 會用以存放使用者名稱。

```
public class MyWFImpl implements MyWF {
  public static WorkflowExecutionLocal<String> username
      = new WorkflowExecutionLocal<String>();

  @Override
  public void start(String username){
    this.username.set(username);
    Processor p = new Processor();
    p.updateLastLogin();
    p.greetUser();
   }

  public static WorkflowExecutionLocal<String> getUsername() {
    return username;
  }

  public static void setUsername(WorkflowExecutionLocal<String> username) {
    MyWFImpl.username = username;
  }
}

public class Processor {
  void updateLastLogin(){
    UserActivitiesClient c = new UserActivitiesClientImpl();
    c.refreshLastLogin(MyWFImpl.getUsername().get());
  }
   void greetUser(){
    GreetingActivitiesClient c = new GreetingActivitiesClientImpl();
    c.greetUser(MyWFImpl.getUsername().get());
  }
}
```