

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.

# Wiederholen fehlgeschlagener Aktivitäten
<a name="features-retry"></a>

Gelegentlich schlagen Aktivitäten aus temporären Gründen fehl, z. B. aufgrund eines vorübergehenden Verbindungsverlusts. In anderen Fällen wird die Aktivität möglicherweise erfolgreich durchgeführt, daher besteht das geeignete Verfahren zum Umgang mit dem Aktivitätsfehler häufig im (ggf. mehrmaligen) Wiederholen der Aktivität. 

Es gibt verschiedene Strategien zum Wiederholen von Aktivitäten. Welche am besten geeignet ist, hängt von den Details in Ihrem Workflow ab. Die Strategien lassen sich grundsätzlich in drei Kategorien einteilen: 
+ Die retry-until-success Strategie wiederholt die Aktivität einfach so lange, bis sie abgeschlossen ist.
+ Die exponentielle Wiederholungsstrategie verlängert das Zeitintervall zwischen den Versuchen exponentiell, bis die Aktivität abgeschlossen wird oder der Vorgang eine bestimmte Stoppmarke erreicht, beispielsweise eine maximale Anzahl an Versuchen.
+ Die benutzerdefinierte Wiederholungsstrategie legt fest, ob und wie die Aktivität nach einem fehlgeschlagenen Versuch wiederholt wird.

In den folgenden Abschnitten wird die Implementierung dieser Strategien beschrieben. In diesem Beispiel nutzen die Workflow-Worker alle eine einzige Aktivität, `unreliableActivity`, die willkürlich eine der folgenden Verhaltensweisen zeigt: 
+ Wird umgehend abgeschlossen
+ Schlägt beabsichtigt fehl durch Überschreiten des Timeout-Wertes
+ Schlägt beabsichtigt fehl durch Ausgeben von `IllegalStateException` 

## Retry-Until-Success Strategie
<a name="features-retry-success"></a>

Die einfachste Wiederholungsstrategie besteht darin, die Aktivität nach jedem Fehler zu wiederholen, bis sie schließlich erfolgreich durchgeführt werden kann. Das grundlegende Muster ist:

1. Implementieren Sie eine verschachtelte `TryCatch`- oder `TryCatchFinally`-Klasse in die Eintrittspunktmethode Ihres Workflows.

1. Führen Sie die Aktivität in `doTry` aus.

1. Falls die Aktivität fehlschlägt, ruft das Framework `doCatch` auf, wodurch die Eintrittspunktmethode erneut ausgeführt wird.

1. Wiederholen Sie die Schritte 2 bis 3, bis die Aktivität erfolgreich abgeschlossen wird.

Der folgende Workflow implementiert die retry-until-success Strategie. Die Workflow-Schnittstelle wird in `RetryActivityRecipeWorkflow` implementiert und enthält die Methode `runUnreliableActivityTillSuccess`, die den Eintrittspunkt des Workflows darstellt. Der Workflow-Worker wird in `RetryActivityRecipeWorkflowImpl` wie folgt implementiert: 

```
public class RetryActivityRecipeWorkflowImpl
    implements RetryActivityRecipeWorkflow {

    @Override
    public void runUnreliableActivityTillSuccess() {
        final Settable<Boolean> retryActivity = new Settable<Boolean>();

        new TryCatch() {
            @Override
            protected void doTry() throws Throwable {
                Promise<Void> activityRanSuccessfully
                    = client.unreliableActivity();
                setRetryActivityToFalse(activityRanSuccessfully, retryActivity);
            }

            @Override
            protected void doCatch(Throwable e) throws Throwable {
                retryActivity.set(true);
            }
        };
        restartRunUnreliableActivityTillSuccess(retryActivity);
    }

    @Asynchronous
    private void setRetryActivityToFalse(
            Promise<Void> activityRanSuccessfully,
            @NoWait Settable<Boolean> retryActivity) {
        retryActivity.set(false);
    }

    @Asynchronous
    private void restartRunUnreliableActivityTillSuccess(
            Settable<Boolean> retryActivity) {
        if (retryActivity.get()) {
            runUnreliableActivityTillSuccess();
        }
    }
}
```

Der Workflow funktioniert folgendermaßen: 

1. `runUnreliableActivityTillSuccess` erstellt ein `Settable<Boolean>`-Objekt namens `retryActivity`, das verwendet wird, um anzugeben, ob die Aktivität fehlgeschlagen ist und erneut getestet werden sollte. `Settable<T>` ist von `Promise<T>` abgeleitet und funktioniert zwar ähnlich, jedoch legen Sie den Wert eines `Settable<T>`-Objekts manuell fest.

1. `runUnreliableActivityTillSuccess` implementiert eine anonyme verschachtelte `TryCatch`-Klasse zur Verarbeitung von Ausnahmen, die von der `unreliableActivity`-Aktivität ausgegeben werden. Weitere Informationen zum Umgang mit Ausnahmen, die von asynchronem Code ausgegeben werden, finden Sie unter [Fehlerbehandlung](errorhandling.md).

1. `doTry` führt die `unreliableActivity`-Aktivität aus, die ein `Promise<Void>`-Objekt namens `activityRanSuccessfully` zurückgibt.

1. `doTry` ruft die asynchrone `setRetryActivityToFalse`-Methode auf, die zwei Parameter umfasst:
   + `activityRanSuccessfully` übernimmt das `Promise<Void>`-Objekt, das von der `unreliableActivity`-Aktivität zurückgegeben wird.
   + `retryActivity` übernimmt das `retryActivity`-Objekt.

   Bei Abschluss von `unreliableActivity` wird `activityRanSuccessfully` einsatzbereit und `setRetryActivityToFalse` legt `retryActivity` auf "false" fest. Andernfalls wird `activityRanSuccessfully` nicht einsatzbereit und `setRetryActivityToFalse` wird nicht ausgeführt.

1. Wenn `unreliableActivity` eine Ausnahme ausgibt, ruft das Framework `doCatch` auf und übergibt es an das Ausnahmeobjekt. `doCatch` legt `retryActivity` auf "true" fest.

1. `runUnreliableActivityTillSuccess` ruft die asynchrone `restartRunUnreliableActivityTillSuccess`-Methode auf und übergibt ihr das `retryActivity`-Objekt. Da `retryActivity` ein `Promise<T>`-Typ ist, verschiebt `restartRunUnreliableActivityTillSuccess` die Ausführung, bis `retryActivity` einsatzbereit ist. Dies ist der Fall, sobald `TryCatch` abgeschlossen wird. 

1. Wenn `retryActivity` einsatzbereit ist, extrahiert `restartRunUnreliableActivityTillSuccess` den Wert.
   + Wenn der Wert `false` ist, war die Wiederholung erfolgreich. `restartRunUnreliableActivityTillSuccess` unternimmt nichts und die Wiederholungssequenz wird beendet.
   + Wenn als Wert "true" ausgegeben wird, ist der Wiederholungsversuch fehlgeschlagen. `restartRunUnreliableActivityTillSuccess` ruft `runUnreliableActivityTillSuccess` auf, um die Aktivität erneut auszuführen.

1. Die Schritte 1 bis 7 werden wiederholt, bis `unreliableActivity` abgeschlossen wird. 

**Anmerkung**  
`doCatch` verarbeitet die Ausnahme nicht, sondern legt nur das `retryActivity`-Objekt auf "true" fest, um anzugeben, dass die Aktivität fehlgeschlagen ist. Die Wiederholung wird von der asynchronen `restartRunUnreliableActivityTillSuccess`-Methode verarbeitet, die die Ausführung verschiebt, bis `TryCatch` abgeschlossen wird. Der Grund für diesen Ansatz ist, dass Sie eine Aktivität, die Sie in `doCatch` wiederholen, nicht beenden können. Wenn die Aktivität in `restartRunUnreliableActivityTillSuccess` wiederholt wird, können Sie Aktivitäten ausführen, die sich beenden lassen. 

## Exponentielle Wiederholungsstrategie
<a name="features-retry-exponential"></a>

Bei der exponentiellen Wiederholungsstrategie führt das Framework eine fehlgeschlagene Aktivität nach einem festgelegten Zeitraum (N Sekunden) erneut aus. Schlägt dieser Versuch fehl, wiederholt das Framework die Aktivität nach 2N Sekunden, dann nach 4N Sekunden usw. Da die Wartezeit sehr lang werden kann, werden Sie die Wiederholungen nicht endlos fortsetzen, sondern den Vorgang irgendwann beenden.

Das Framework bietet drei Möglichkeiten zur Implementierung einer exponentiellen Wiederholungsstrategie:
+ Die `@ExponentialRetry`-Anmerkung ist der einfachste Ansatz. Sie müssen die Wiederholungsoptionen jedoch bei der Kompilierung festlegen.
+ Die `RetryDecorator`-Klasse ermöglicht es Ihnen, die Wiederholungskonfiguration zur Laufzeit festzulegen und bei Bedarf zu ändern.
+ Die `AsyncRetryingExecutor`-Klasse ermöglicht es Ihnen, die Wiederholungskonfiguration zur Laufzeit festzulegen und bei Bedarf zu ändern. Darüber hinaus ruft das Framework eine vom Benutzer implementierte `AsyncRunnable.run`-Methode zur Ausführung jedes neuen Versuchs auf.

Alle Ansätze unterstützen folgende Konfigurationsoptionen, wobei die Werte für die Zeit in Sekunden angegeben werden: 
+ Die erste Wiederholungswartezeit.
+ Den Backoff-Koeffizienten, der verwendet wird, um die Wiederholungsintervalle folgendermaßen zu errechnen:

  ```
  retryInterval = initialRetryIntervalSeconds * Math.pow(backoffCoefficient, numberOfTries - 2)
  ```

  Der Standardwert lautet 2.0.
+ Die maximale Anzahl an Wiederholungen. Der Standardwert ist unbegrenzt.
+ Das maximale Wiederholungsintervall. Der Standardwert ist unbegrenzt.
+ Die Ablaufzeit. Es werden keine Wiederholungen mehr ausgeführt, wenn die Gesamtdauer des Vorgangs diesen Wert übersteigt. Der Standardwert ist unbegrenzt.
+ Die Ausnahmen, die den Wiederholungsvorgang auslösen. Standardmäßig löst jede Ausnahme den Wiederholungsvorgang aus.
+ Die Ausnahmen, die keinen Wiederholungsvorgang auslösen. Standardmäßig sind keine Ausnahmen ausgeschlossen.

In den folgenden Abschnitten werden die verschiedenen Methoden zur Implementierung einer exponentiellen Wiederholungsstrategie beschrieben.

### Exponentieller Wiederholungsversuch mit @ ExponentialRetry
<a name="features-retry-exponential-annotation"></a>

Die einfachste Möglichkeit zur Implementierung einer exponentiellen Wiederholungsstrategie für eine Aktivität ist die Anwendung einer `@ExponentialRetry `-Anmerkung auf die Aktivität in der Schnittstellendefinition. Schlägt die Aktivität fehl, verarbeitet das Framework den Wiederholungsvorgang automatisch basierend auf den festgelegten Optionen. Das grundlegende Muster ist:

1. Wenden Sie `@ExponentialRetry` auf die entsprechenden Aktivitäten an und legen Sie die Wiederholungskonfiguration fest.

1. Schlägt eine mit einer Anmerkung versehene Aktivität fehl, wiederholt das Framework die Aktivität automatisch basierend auf der durch die Anmerkungsargumente festgelegten Konfiguration. 

Der `ExponentialRetryAnnotationWorkflow`-Workflow-Worker implementiert die exponentielle Wiederholungsstrategie durch Verwendung einer `@ExponentialRetry`-Anmerkung. Er verwendet eine `unreliableActivity`-Aktivität, deren Schnittstellendefinition wie folgt in `ExponentialRetryAnnotationActivities` implementiert wird:

```
@Activities(version = "1.0")
@ActivityRegistrationOptions(
    defaultTaskScheduleToStartTimeoutSeconds = 30,
    defaultTaskStartToCloseTimeoutSeconds = 30)
public interface ExponentialRetryAnnotationActivities {
    @ExponentialRetry(
        initialRetryIntervalSeconds = 5,
        maximumAttempts = 5,
        exceptionsToRetry = IllegalStateException.class)
    public void unreliableActivity();
}
```

Die `@ExponentialRetry`-Optionen legen folgende Strategie fest: 
+ Nur wiederholen, wenn die Aktivität `IllegalStateException` ausgibt.
+ Eine erste Wartezeit von 5 Sekunden verwenden.
+ Nicht mehr als 5 Wiederholungen. 

Die Workflow-Schnittstelle wird in `RetryWorkflow` implementiert und enthält die Methode `process`, die den Eintrittspunkt des Workflows darstellt. Der Workflow-Worker wird in `ExponentialRetryAnnotationWorkflowImpl` wie folgt implementiert: 

```
public class ExponentialRetryAnnotationWorkflowImpl implements RetryWorkflow {
    public void process() {
        handleUnreliableActivity();
    }

    public void handleUnreliableActivity() {
        client.unreliableActivity();
    }
}
```

Der Workflow funktioniert folgendermaßen: 

1. `process` führt die synchrone `handleUnreliableActivity`-Methode aus.

1. `handleUnreliableActivity` führt die `unreliableActivity`-Aktivität aus. 

Schlägt die Aktivität fehl, indem `IllegalStateException` ausgegeben wird, führt das Framework automatisch die in `ExponentialRetryAnnotationActivities` festgelegte Wiederholungsstrategie aus.

### Exponentielle Wiederholung mit der Klasse RetryDecorator
<a name="features-retry-exponential-decorator"></a>

`@ExponentialRetry` ist benutzerfreundlich. Allerdings ist die Konfiguration statisch und wird bei der Kompilierung festgelegt, sodass das Framework bei jedem Fehler der Aktivität dieselbe Wiederholungsstrategie anwendet. Sie können eine flexiblere exponentielle Wiederholungsstrategie implementieren, indem Sie die `RetryDecorator`-Klasse verwenden, mit der Sie die Konfiguration zur Laufzeit festlegen und bei Bedarf ändern können. Das grundlegende Muster ist:

1. Erzeugen und konfigurieren Sie ein `ExponentialRetryPolicy`-Objekt, das die Wiederholungskonfiguration festlegt.

1. Erzeugen Sie ein `RetryDecorator`-Objekt und geben Sie das `ExponentialRetryPolicy`-Objekt aus Schritt 1 an den Konstruktor weiter.

1. Wenden Sie das Decorator-Objekt auf die Aktivität an, indem Sie den Klassennamen des Aktivitäts-Clients auf die Ausstattungsmethode des `RetryDecorator`-Objekts übergeben.

1. Führen Sie die Aktivität aus.

Schlägt die Aktivität fehl, wiederholt das Framework die Aktivität basierend auf der `ExponentialRetryPolicy`-Objektkonfiguration. Sie können die Wiederholungskonfiguration bei Bedarf ändern, indem Sie dieses Objekt anpassen. 

**Anmerkung**  
Die `@ExponentialRetry`-Anmerkung und die `RetryDecorator`-Klasse schließen sich gegenseitig aus. Sie können `RetryDecorator` nicht verwenden, um eine Wiederholungsrichtlinie, die von einer `@ExponentialRetry`-Anmerkung festgelegt wird, dynamisch zu überschreiben. 

Die folgende Workflow-Implementierung zeigt, wie die `RetryDecorator`-Klasse verwendet wird, um eine exponentielle Wiederholungsstrategie zu implementieren. Sie verwendet eine `unreliableActivity`-Aktivität, die nicht über eine `@ExponentialRetry`-Anmerkung verfügt. Die Workflow-Schnittstelle wird in `RetryWorkflow` implementiert und enthält die Methode `process`, die den Eintrittspunkt des Workflows darstellt. Der Workflow-Worker wird in `DecoratorRetryWorkflowImpl` wie folgt implementiert: 

```
public class DecoratorRetryWorkflowImpl implements RetryWorkflow {
   ...
  public void process() {
      long initialRetryIntervalSeconds = 5;
      int maximumAttempts = 5;
      ExponentialRetryPolicy retryPolicy = new ExponentialRetryPolicy(
              initialRetryIntervalSeconds).withMaximumAttempts(maximumAttempts);

      Decorator retryDecorator = new RetryDecorator(retryPolicy);
      client = retryDecorator.decorate(RetryActivitiesClient.class, client);
      handleUnreliableActivity();
  }

  public void handleUnreliableActivity() {
      client.unreliableActivity();
  }
}
```

Der Workflow funktioniert folgendermaßen: 

1. `process` erzeugt und konfiguriert ein `ExponentialRetryPolicy`-Objekt folgendermaßen: 
   + Das erste Wiederholungsintervall wird an den Konstruktor übergeben.
   + Aufrufen der `withMaximumAttempts`-Methode des Objekts, um die maximale Anzahl der Versuche auf 5 festzulegen. `ExponentialRetryPolicy` zeigt andere `with`-Objekte an, mit denen Sie andere Konfigurationsoptionen angeben können.

1. `process` erzeugt ein `RetryDecorator`-Objekt namens `retryDecorator` und übergibt das `ExponentialRetryPolicy`-Objekt aus Schritt 1 an den Konstruktor.

1. `process` wendet den Decorator auf die Aktivität an, indem es die `retryDecorator.decorate`-Methode aufruft und ihr den Klassennamen des Aktivitäts-Clients übergibt.

1. `handleUnreliableActivity` führt die Aktivität aus. 

Schlägt die Aktivität fehl, wiederholt das Framework sie basierend auf der in Schritt 1 festgelegten Konfiguration.

**Anmerkung**  
Einige `with`-Methoden der `ExponentialRetryPolicy`-Klasse besitzen eine entsprechende `set`-Methode, die Sie jederzeit aufrufen können, um die entsprechende Konfigurationsoption anzupassen: `setBackoffCoefficient`, `setMaximumAttempts`, `setMaximumRetryIntervalSeconds` und `setMaximumRetryExpirationIntervalSeconds`. 

### Exponentielle Wiederholung mit der Klasse AsyncRetryingExecutor
<a name="features-retry-exponential-async"></a>

Die `RetryDecorator`-Klasse bietet mehr Flexibilität bei der Konfiguration des Wiederholungsvorgangs als `@ExponentialRetry`, allerdings führt das Framework dennoch automatisch die Wiederholungen basierend auf der aktuellen Konfiguration des `ExponentialRetryPolicy`-Objekts aus. Ein flexiblerer Ansatz ist die Verwendung der `AsyncRetryingExecutor`-Klasse. Sie haben nicht nur die Möglichkeit, den Wiederholungsvorgang zur Laufzeit zu konfigurieren, sondern das Framework ruft zudem eine vom Benutzer implementierte `AsyncRunnable.run`-Methode zur Ausführung jeder Wiederholung auf, statt die Aktivität einfach auszuführen.

Das grundlegende Muster ist: 

1. Erzeugen und konfigurieren Sie ein `ExponentialRetryPolicy`-Objekt, um die Wiederholungskonfiguration festzulegen.

1. Erzeugen Sie ein `AsyncRetryingExecutor`-Objekt und übergeben Sie ihm das `ExponentialRetryPolicy`-Objekt und eine Instanz der Workflow-Uhr.

1.  Implementieren Sie eine anonyme verschachtelte `TryCatch`- oder `TryCatchFinally`-Klasse.

1. Implementieren Sie eine anonyme `AsyncRunnable`-Klasse und überschreiben Sie die `run`-Methode, um den benutzerdefinierten Code zur Ausführung der Aktivität zu implementieren.

1.  Überschreiben Sie `doTry`, um die `execute`-Methode des `AsyncRetryingExecutor`-Objekts aufzurufen, und übergeben Sie ihr die `AsyncRunnable`-Klasse aus Schritt 4. Das `AsyncRetryingExecutor`-Objekt ruft `AsyncRunnable.run` auf, um die Aktivität auszuführen.

1. Schlägt die Aktivität fehl, ruft das `AsyncRetryingExecutor`-Objekt in Einklang mit der Wiederholungsrichtlinie, die in Schritt 1 festgelegt wurde, die `AsyncRunnable.run`-Methode erneut auf. 

Der folgende Workflow zeigt, wie die `AsyncRetryingExecutor`-Klasse verwendet wird, um eine exponentielle Wiederholungsstrategie zu implementieren. Er verwendet dieselbe `unreliableActivity`-Aktivität wie der zuvor behandelte `DecoratorRetryWorkflow`-Workflow. Die Workflow-Schnittstelle wird in `RetryWorkflow` implementiert und enthält die Methode `process`, die den Eintrittspunkt des Workflows darstellt. Der Workflow-Worker wird in `AsyncExecutorRetryWorkflowImpl` wie folgt implementiert: 

```
public class AsyncExecutorRetryWorkflowImpl implements RetryWorkflow {
  private final RetryActivitiesClient client = new RetryActivitiesClientImpl();
  private final DecisionContextProvider contextProvider = new DecisionContextProviderImpl();
  private final WorkflowClock clock = contextProvider.getDecisionContext().getWorkflowClock();

  public void process() {
      long initialRetryIntervalSeconds = 5;
      int maximumAttempts = 5;
      handleUnreliableActivity(initialRetryIntervalSeconds, maximumAttempts);
  }
  public void handleUnreliableActivity(long initialRetryIntervalSeconds, int maximumAttempts) {

      ExponentialRetryPolicy retryPolicy = new ExponentialRetryPolicy(initialRetryIntervalSeconds).withMaximumAttempts(maximumAttempts);
      final AsyncExecutor executor = new AsyncRetryingExecutor(retryPolicy, clock);

      new TryCatch() {
          @Override
          protected void doTry() throws Throwable {
              executor.execute(new AsyncRunnable() {
                  @Override
                  public void run() throws Throwable {
                      client.unreliableActivity();
                  }
              });
          }
          @Override
          protected void doCatch(Throwable e) throws Throwable {
          }
      };
  }
}
```

Der Workflow funktioniert folgendermaßen: 

1. `process` ruft die `handleUnreliableActivity`-Methode auf und übergibt ihr die Konfigurationseinstellungen.

1. `handleUnreliableActivity` verwendet die Konfigurationseinstellungen aus Schritt 1, um das `ExponentialRetryPolicy`-Objekt `retryPolicy` zu erzeugen.

1. `handleUnreliableActivity` erzeugt das `AsyncRetryExecutor`-Objekt `executor` und übergibt das `ExponentialRetryPolicy`-Objekt aus Schritt 2 und eine Instanz der Workflow-Uhr an den Konstruktor.

1.  `handleUnreliableActivity` implementiert eine anonyme verschachtelte `TryCatch`-Klasse und überschreibt die `doTry`- und `doCatch`-Methode, um die Wiederholungen auszuführen und mögliche Ausnahmen zu verarbeiten.

1. `doTry` erzeugt eine anonyme `AsyncRunnable`-Klasse und überschreibt die `run`-Methode, um den benutzerdefinierten Code zur Ausführung von `unreliableActivity` zu implementieren. Der Einfachheit halber führt `run` nur die Aktivität aus, Sie können bei Bedarf jedoch komplexere Ansätze implementieren.

1. `doTry` ruft `executor.execute` auf und übergibt es an das `AsyncRunnable`-Objekt. `execute` ruft die `run`-Methode des `AsyncRunnable`-Objekts auf, um die Aktivität auszuführen.

1. Schlägt die Aktivität fehl, ruft der Executor erneut `run` auf, basierend auf der Konfiguration des `retryPolicy`-Objekts. 

Weitere Informationen zur Verwendung der `TryCatch`-Klasse zur Fehlerbehandlung finden Sie unter [AWS Flow Framework für Java-Ausnahmen](errorhandling.exceptions.md). 

## Benutzerdefinierte Wiederholungsstrategie
<a name="custom-retry-strategy"></a>

Der flexibelste Ansatz zur Wiederholung fehlgeschlagener Aktivitäten ist eine benutzerdefinierte Strategie, bei der rekursiv eine asynchrone Methode aufgerufen wird, die den Wiederholungsversuch ausführt, ähnlich wie bei der Strategie. retry-until-success Statt die Aktivität einfach erneut auszuführen, implementieren Sie jedoch eine benutzerdefinierte Logik, die entscheidet, ob und wie jede Wiederholung ausgeführt werden soll. Das grundlegende Muster ist: 

1. Erzeugen Sie ein `Settable<T>`-Statusobjekt, das verwendet wird, um anzugeben, ob die Aktivität fehlgeschlagen ist.

1. Implementieren Sie eine verschachtelte `TryCatch`- oder `TryCatchFinally`-Klasse.

1. `doTry` führt die Aktivität aus.

1. Schlägt die Aktivität fehl, legt `doCatch` das Statusobjekt fest, um anzugeben, dass die Aktivität fehlgeschlagen ist.

1. Rufen Sie eine asynchrone Fehlerbehandlungsmethode auf und übergeben Sie ihr das Statusobjekt. Die Methode verschiebt die Ausführung, bis `TryCatch` oder `TryCatchFinally` abgeschlossen wird.

1. Die Fehlerbehandlungsmethode entscheidet, ob und wann die Aktivität wiederholt werden soll.

Der folgende Workflow zeigt, wie eine benutzerdefinierte Wiederholungsstrategie implementiert wird. Er verwendet dieselbe `unreliableActivity`-Aktivität wie der `DecoratorRetryWorkflow`- und `AsyncExecutorRetryWorkflow`-Workflow. Die Workflow-Schnittstelle wird in `RetryWorkflow` implementiert und enthält die Methode `process`, die den Eintrittspunkt des Workflows darstellt. Der Workflow-Worker wird in `CustomLogicRetryWorkflowImpl` wie folgt implementiert: 

```
public class CustomLogicRetryWorkflowImpl implements RetryWorkflow {
  ...
  public void process() {
      callActivityWithRetry();
  }
  @Asynchronous
  public void callActivityWithRetry() {
      final Settable<Throwable> failure = new Settable<Throwable>();
      new TryCatchFinally() {
          protected void doTry() throws Throwable {
              client.unreliableActivity();
          }
          protected void doCatch(Throwable e) {
              failure.set(e);
          }
          protected void doFinally() throws Throwable {
              if (!failure.isReady()) {
                  failure.set(null);
              }
          }
      };
      retryOnFailure(failure);
  }
  @Asynchronous
  private void retryOnFailure(Promise<Throwable> failureP) {
      Throwable failure = failureP.get();
      if (failure != null && shouldRetry(failure)) {
          callActivityWithRetry();
      }
  }
  protected Boolean shouldRetry(Throwable e) {
      //custom logic to decide to retry the activity or not
      return true;
  }
}
```

Der Workflow funktioniert folgendermaßen:

1. `process` ruft die asynchrone `callActivityWithRetry`-Methode auf.

1. `callActivityWithRetry` erstellt ein `Settable<Throwable>`-Objekt namens "failure" (Fehler), mit dem angezeigt wird, dass die Aktivität fehlgeschlagen ist. `Settable<T>` ist von `Promise<T>` abgeleitet und funktioniert zwar ähnlich, jedoch legen Sie den Wert eines `Settable<T>`-Objekts manuell fest.

1. `callActivityWithRetry` implementiert eine anonyme verschachtelte `TryCatchFinally`-Klasse zur Verarbeitung von Ausnahmen, die von `unreliableActivity` ausgegeben werden. Weitere Informationen zum Umgang mit Ausnahmen, die von asynchronem Code ausgegeben werden, finden Sie unter [AWS Flow Framework für Java-Ausnahmen](errorhandling.exceptions.md).

1. `doTry` führt `unreliableActivity` aus.

1. Wenn `unreliableActivity` eine Ausnahme auslöst, ruft das Framework `doCatch` auf und übergibt sie an das Ausnahmeobjekt. `doCatch` legt `failure` auf das Ausnahmeobjekt fest, was anzeigt, dass die Aktivität fehlgeschlagen ist, und versetzt das Objekt in einen betriebsbereiten Zustand.

1. `doFinally` überprüft, ob `failure` einsatzbereit ist, was nur der Fall ist, wenn `failure` von `doCatch` festgelegt wurde.
   + Wenn es bereit `failure` ist, tut es nichts. `doFinally`
   + Wenn `failure` nicht einsatzbereit ist, wird die Aktivität abgeschlossen und `doFinally` legt "failure" auf `null` fest. 

1. `callActivityWithRetry` ruft die asynchrone `retryOnFailure`-Methode auf und übergibt ihr "failure". Da "failure" ein `Settable<T>`-Typ ist, verschiebt `callActivityWithRetry` die Ausführung, bis "failure" einsatzbereit ist. Dies ist der Fall, sobald `TryCatchFinally` abgeschlossen wird.

1. `retryOnFailure` ruft den Wert von "failure" ab.
   + Wenn der Fehler auf Null gesetzt ist, war der Wiederholungsversuch erfolgreich. `retryOnFailure` unternimmt nichts, wodurch der Wiederholungsprozess beendet wird.
   + Wenn "failure" auf ein Ausnahmeobjekt festgelegt ist und `shouldRetry` "true" zurückgibt, ruft `retryOnFailure` `callActivityWithRetry` auf, um die Aktivität zu wiederholen. 

     `shouldRetry` implementiert eine benutzerdefinierte Logik, um zu entscheiden, ob eine fehlgeschlagene Aktivität wiederholt werden soll. Der Einfachheit halber gibt `shouldRetry` immer `true` zurück und `retryOnFailure` führt die Aktivität sofort aus, Sie können bei Bedarf jedoch eine komplexere Logik implementieren. 

1. Die Schritte 2—8 werden wiederholt, bis der Vorgang `unreliableActivity` abgeschlossen ist oder `shouldRetry` beendet werden soll. 

**Anmerkung**  
`doCatch` verarbeitet den Wiederholungsvorgang nicht, sondern legt nur "failure" fest, um anzugeben, dass die Aktivität fehlgeschlagen ist. Der Wiederholungsvorgang wird von der asynchronen `retryOnFailure`-Methode verarbeitet, die die Ausführung verschiebt, bis `TryCatch` abgeschlossen wird. Der Grund für diesen Ansatz ist, dass Sie eine Aktivität, die Sie in `doCatch` wiederholen, nicht beenden können. Wenn die Aktivität in `retryOnFailure` wiederholt wird, können Sie Aktivitäten ausführen, die sich beenden lassen. 