

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

# Lösungen
<a name="java-flow-making-changes-solutions"></a>

Verwenden Sie eine der folgenden Lösungen, um abwärtsinkompatible Änderungen zu vermeiden. Weitere Informationen finden Sie unter [Vornehmen von Änderungen am Entscheidercode](java-flow-making-changes-decider-code.md) und [Beispielszenario](java-flow-making-changes-example-scenario.md).

## Verwenden von Versioning
<a name="use-versioning"></a>

Für diese Lösung kopieren Sie den Entscheider in eine neue Klasse, modifizieren ihn und registrieren den Entscheider dann unter einer neuen Workflow-Version.

`VersionedDecider.java`

```
package sample.v2;
 
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 = "2")
    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 (V2) WorkflowId: " + decisionContext.getWorkflowContext().getWorkflowExecution().getWorkflowId());
            clock.createTimer(5);
        }
 
    }
 
}
```

Im aktualisierten Java-Code führt der zweite Entscheiderauftragnehmer beide Versionen des Workflows aus. Dadurch können laufende Ausführungen unabhängig von den Änderungen in Version `2` fortgesetzt werden.

`RunVersionedDecider.java`

```
package sample;
 
import com.amazonaws.services.simpleworkflow.flow.WorkflowWorker;
 
public class VersionedChange extends SampleBase {
 
    public static void main(String[] args) throws Exception {
        new VersionedChange().run();
    }
 
    public void run() throws Exception {
        // Start the first version of the decider, with workflow version 1
        WorkflowWorker before = new WorkflowWorker(service, domain, taskList);
        before.addWorkflowImplementationType(sample.v1.Foo.Impl.class);
        before.start();
 
        // Start a few executions with version 1
        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 a worker with both the previous version of the decider (workflow version 1) 
        // and the modified code (workflow version 2)
        WorkflowWorker after = new WorkflowWorker(service, domain, taskList);
        after.addWorkflowImplementationType(sample.v1.Foo.Impl.class);
        after.addWorkflowImplementationType(sample.v2.Foo.Impl.class);
        after.start();
 
        // Start a few more executions with version 2
        startFiveExecutions("Foo.sample", "2", new Input());
 
        printExecutionResults();
    }
 
}
```

Wenn Sie das Programm ausführen, werden alle Ausführungen erfolgreich abgeschlossen.

## Verwenden von Funktions-Flags
<a name="use-feature-flags"></a>

Eine weitere Lösung für Probleme mit der Abwärtskompatibilität besteht darin, den Code basierend auf Eingabedaten anstelle von Workflow-Versionen in zwei Implementierungen in derselben Klasse aufzuteilen.

Wenn Sie diesen Ansatz wählen, fügen Sie Ihren Eingabeobjekten jedes Mal, wenn Sie sensible Änderungen vornehmen, Felder hinzu (oder modifizieren vorhandene Felder Ihrer Eingabeobjekte). Für Ausführungen, die vor der Migration beginnen, enthält das Eingabeobjekt das Feld nicht (oder es enthält einen anderen Wert). Daher müssen Sie die Versionsnummer nicht erhöhen.

**Anmerkung**  
Wenn Sie neue Felder hinzufügen, stellen Sie sicher, dass der JSON-Deserialisierungsprozess abwärtskompatibel ist. Objekte, die vor der Einführung des Felds serialisiert wurden, sollten nach der Migration weiterhin erfolgreich deserialisiert werden können. Da JSON einen `null`-Wert festlegt, wenn ein Feld fehlt, verwenden Sie grundsätzlich gepackte Typen (`Boolean` anstelle von `boolean`) und verarbeiten Sie Fälle, in denen der Wert `null` ist.

`FeatureFlagDecider.java`

```
package sample.v1.featureflag;
 
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 feature flag) WorkflowId: " + decisionContext.getWorkflowContext().getWorkflowExecution().getWorkflowId());
            clock.createTimer(5);
            if (!input.getSkipSecondTimer()) {
                clock.createTimer(5);
            }
        }
 
    }
}
```

Im aktualisierten Java-Code ist der Code beider Versionen des Workflows weiterhin für Version `1` registriert. Nach der Migration beginnen neue Ausführungen dagegen mit dem Feld `skipSecondTimer` der Eingabedaten mit dem Wert `true`.

`RunFeatureFlagDecider.java`

```
package sample;
 
import com.amazonaws.services.simpleworkflow.flow.WorkflowWorker;
 
public class FeatureFlagChange extends SampleBase {
 
    public static void main(String[] args) throws Exception {
        new FeatureFlagChange().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 a new version of the decider that introduces a change 
        // while preserving backwards compatibility based on input fields
        WorkflowWorker after = new WorkflowWorker(service, domain, taskList);
        after.addWorkflowImplementationType(sample.v1.featureflag.Foo.Impl.class);
        after.start();
 
        // Start a few more executions and enable the new feature through the input data
        startFiveExecutions("Foo.sample", "1", new Input().setSkipSecondTimer(true));
 
        printExecutionResults();
    }
 
}
```

Wenn Sie das Programm ausführen, werden alle Ausführungen erfolgreich abgeschlossen.