

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

# シナリオの例
<a name="java-flow-making-changes-example-scenario"></a>

後方互換性のない変更とみなされるコードのクラスの変更があります。このような変更には、スケジュールされたタスクの数値、型、または順序を変更する更新などがあります。次の例を考えます。

2 つのタイマータスクをスケジュールするには、ディサイダーコードを記述します。実行をスタートし、ディシジョンを実行します。その結果、2 つのタイマータスクは、ID `1` と `2` でスケジュールされます。

次のディシジョンが実行される前に、ディサイダーコードを更新して 1 つのタイマーのみスケジュールする場合、次のディシジョンタスク時、ID `2` は、コードが生成されたどのタイマータスクとも一致しないため、フレームワークで 2 番目の `TimerFired` イベントを再生することはできません。

## シナリオの概要
<a name="example-scenario-outline"></a>

このシナリオのステップを以下の概要に示します。シナリオの最終目標は、システムに移行して 1 つのタイマーのみスケジュールすることですが、移行前にスタートした実行が失敗することはありません。

1. ディサイダーの初期バージョン

   1. ディサイダーを記述します。

   1. ディサイダーをスタートします。

   1. ディサイダーによって、2 つのタイマーがスケジュールされます。

   1. ディサイダーは、5 つの実行をスタートします。

   1. ディサイダーを停止します。

1. 後方互換性のないディサイダーの変更

   1. ディサイダーを変更します。

   1. ディサイダーをスタートします。

   1. ディサイダーによって、1 つのタイマーがスケジュールされます。

   1. ディサイダーは、5 つの実行をスタートします。

次のセクションには、このシナリオの実装方法を示す Java コードの例が含まれます。[ソリューション](java-flow-making-changes-solutions.md) セクションのコード例は、後方互換性のない変更を修正するさまざまな方法を示します。

**注記**  
このコードを実行するには、最新バージョンの [AWS SDK for Java](https://aws.amazon.com/sdk-for-java/) を使用します。

## 共通コード
<a name="common-code"></a>

次の Java コードによって、このシナリオの例が変更されることはありません。

`SampleBase.java`

```
package sample;
 
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
 
import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow;
import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowClientBuilder;
import com.amazonaws.services.simpleworkflow.flow.JsonDataConverter;
import com.amazonaws.services.simpleworkflow.model.DescribeWorkflowExecutionRequest;
import com.amazonaws.services.simpleworkflow.model.DomainAlreadyExistsException;
import com.amazonaws.services.simpleworkflow.model.RegisterDomainRequest;
import com.amazonaws.services.simpleworkflow.model.Run;
import com.amazonaws.services.simpleworkflow.model.StartWorkflowExecutionRequest;
import com.amazonaws.services.simpleworkflow.model.TaskList;
import com.amazonaws.services.simpleworkflow.model.WorkflowExecution;
import com.amazonaws.services.simpleworkflow.model.WorkflowExecutionDetail;
import com.amazonaws.services.simpleworkflow.model.WorkflowType;
 
public class SampleBase {
 
    protected String domain = "DeciderChangeSample";
    protected String taskList = "DeciderChangeSample-" + UUID.randomUUID().toString();
    protected AmazonSimpleWorkflow service = AmazonSimpleWorkflowClientBuilder.defaultClient();
    {
        try {
            AmazonSimpleWorkflowClientBuilder.defaultClient().registerDomain(new RegisterDomainRequest().withName(domain).withDescription("desc").withWorkflowExecutionRetentionPeriodInDays("7"));
        } catch (DomainAlreadyExistsException e) {
        }
    }
 
    protected List<WorkflowExecution> workflowExecutions = new ArrayList<>();
 
    protected void startFiveExecutions(String workflow, String version, Object input) {
        for (int i = 0; i < 5; i++) {
            String id = UUID.randomUUID().toString();
            Run startWorkflowExecution = service.startWorkflowExecution(
                    new StartWorkflowExecutionRequest().withDomain(domain).withTaskList(new TaskList().withName(taskList)).withInput(new JsonDataConverter().toData(new Object[] { input })).withWorkflowId(id).withWorkflowType(new WorkflowType().withName(workflow).withVersion(version)));
            workflowExecutions.add(new WorkflowExecution().withWorkflowId(id).withRunId(startWorkflowExecution.getRunId()));
            sleep(1000);
        }
    }
 
    protected void printExecutionResults() {
        waitForExecutionsToClose();
        System.out.println("\nResults:");
        for (WorkflowExecution wid : workflowExecutions) {
            WorkflowExecutionDetail details = service.describeWorkflowExecution(new DescribeWorkflowExecutionRequest().withDomain(domain).withExecution(wid));
            System.out.println(wid.getWorkflowId() + " " + details.getExecutionInfo().getCloseStatus());
        }
    }
 
    protected void waitForExecutionsToClose() {
        loop: while (true) {
            for (WorkflowExecution wid : workflowExecutions) {
                WorkflowExecutionDetail details = service.describeWorkflowExecution(new DescribeWorkflowExecutionRequest().withDomain(domain).withExecution(wid));
                if ("OPEN".equals(details.getExecutionInfo().getExecutionStatus())) {
                    sleep(1000);
                    continue loop;
                }
            }
            return;
        }
    }
 
    protected void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
 
}
```

`Input.java`

```
package sample;
 
public class Input {
 
    private Boolean skipSecondTimer;
 
    public Input() {
    }
 
    public Input(Boolean skipSecondTimer) {
        this.skipSecondTimer = skipSecondTimer;
    }
 
    public Boolean getSkipSecondTimer() {
        return skipSecondTimer != null && skipSecondTimer;
    }
 
    public Input setSkipSecondTimer(Boolean skipSecondTimer) {
        this.skipSecondTimer = skipSecondTimer;
        return this;
    }
 
}
```

## 最初のディサイダーコードを記述する
<a name="writing-initial-decider-code"></a>

ディサイダーの最初の Java コードは以下のとおりです。これは、バージョン `1` として登録され、5 秒のタイマータスクが 2 つスケジュールされます。

`InitialDecider.java`

```
package sample.v1;
 
import com.amazonaws.services.simpleworkflow.flow.DecisionContext;
import com.amazonaws.services.simpleworkflow.flow.DecisionContextProviderImpl;
import com.amazonaws.services.simpleworkflow.flow.WorkflowClock;
import com.amazonaws.services.simpleworkflow.flow.annotations.Execute;
import com.amazonaws.services.simpleworkflow.flow.annotations.Workflow;
import com.amazonaws.services.simpleworkflow.flow.annotations.WorkflowRegistrationOptions;
 
import sample.Input;
 
@Workflow
@WorkflowRegistrationOptions(defaultExecutionStartToCloseTimeoutSeconds = 60, defaultTaskStartToCloseTimeoutSeconds = 5)
public interface Foo {
 
    @Execute(version = "1")
    public void sample(Input input);
 
    public static class Impl implements Foo {
 
        private DecisionContext decisionContext = new DecisionContextProviderImpl().getDecisionContext();
        private WorkflowClock clock = decisionContext.getWorkflowClock();
 
        @Override
        public void sample(Input input) {
            System.out.println("Decision (V1) WorkflowId: " + decisionContext.getWorkflowContext().getWorkflowExecution().getWorkflowId());
            clock.createTimer(5);
            clock.createTimer(5);
        }
 
    }
}
```

## 後方互換性のない変更のシミュレーション
<a name="simulate-non-backwards-compatible-change"></a>

次のディサイダーの変更された Java コードは、後方互換性のない変更を示す良い例です。コードは、バージョン `1` として登録されますが、スケジュールされるタイマーは 1 つのみです。

`ModifiedDecider.java`

```
package sample.v1.modified;
 
import com.amazonaws.services.simpleworkflow.flow.DecisionContext;
import com.amazonaws.services.simpleworkflow.flow.DecisionContextProviderImpl;
import com.amazonaws.services.simpleworkflow.flow.WorkflowClock;
import com.amazonaws.services.simpleworkflow.flow.annotations.Execute;
import com.amazonaws.services.simpleworkflow.flow.annotations.Workflow;
import com.amazonaws.services.simpleworkflow.flow.annotations.WorkflowRegistrationOptions;
 
import sample.Input;
 
@Workflow
@WorkflowRegistrationOptions(defaultExecutionStartToCloseTimeoutSeconds = 60, defaultTaskStartToCloseTimeoutSeconds = 5)
public interface Foo {
 
    @Execute(version = "1")
    public void sample(Input input);
 
    public static class Impl implements Foo {
 
        private DecisionContext decisionContext = new DecisionContextProviderImpl().getDecisionContext();
        private WorkflowClock clock = decisionContext.getWorkflowClock();
 
        @Override
        public void sample(Input input) {
            System.out.println("Decision (V1 modified) WorkflowId: " + decisionContext.getWorkflowContext().getWorkflowExecution().getWorkflowId());
            clock.createTimer(5);
        }
 
    }
}
```

次の Java コードでは、変更後のディサイダーを実行して、後方互換性のない変更が行われる問題をシミュレートします。

`RunModifiedDecider.java`

```
package sample;
 
import com.amazonaws.services.simpleworkflow.flow.WorkflowWorker;
 
public class BadChange extends SampleBase {
 
    public static void main(String[] args) throws Exception {
        new BadChange().run();
    }
 
    public void run() throws Exception {
        // Start the first version of the decider
        WorkflowWorker before = new WorkflowWorker(service, domain, taskList);
        before.addWorkflowImplementationType(sample.v1.Foo.Impl.class);
        before.start();
 
        // Start a few executions
        startFiveExecutions("Foo.sample", "1", new Input());
 
        // Stop the first decider worker and wait a few seconds 
        // for its pending pollers to match and return
        before.suspendPolling();
        sleep(2000);
 
        // At this point, three executions are still open, with more decisions to make
 
        // Start the modified version of the decider
        WorkflowWorker after = new WorkflowWorker(service, domain, taskList);
        after.addWorkflowImplementationType(sample.v1.modified.Foo.Impl.class);
        after.start();
 
        // Start a few more executions
        startFiveExecutions("Foo.sample", "1", new Input());
 
        printExecutionResults();
    }
 
}
```

このプログラムを実行すると、失敗する 3 つの実行は、初期バージョンのディサイダーでスタートされ、移行後も継続します。