Erfassen Sie Ihre Fortschritte
Trailhead-Startseite
Trailhead-Startseite

Verwenden von Future-Methoden

Lernziele

Nachdem Sie diese Lektion abgeschlossen haben, haben Sie Folgendes gelernt:

  • Zeitpunkt für die Verwendung von Future-Methoden
  • Einschränkungen bei der Verwendung von Future-Methoden
  • Verwenden von Future-Methoden für Callouts
  • Future-Methoden – bewährte Vorgehensweisen

Future-Apex

Future-Apex wird verwendet, um Prozesse zu einem späteren Zeitpunkt in einem separaten Thread auszuführen, wenn Systemressourcen verfügbar werden.

Hinweis: Technisch gesehen, verwenden Sie die Anmerkung @future zur Kennzeichnung von Methoden, die asynchron ausgeführt werden. Da jedoch "mit der Anmerkung @future gekennzeichnete Methoden" als Bezeichnung ziemlich umständlich ist, werden sie gemeinhin als "Future-Methoden" bezeichnet und genau das tun wir auch im Rest dieses Moduls.

Bei Verwendung der synchronen Verarbeitung erfolgen alle Methodenaufrufe aus dem gleichen Thread, der auch den Apex-Code ausführt, und es ist keine weitere Verarbeitung möglich, bis der Prozess abgeschlossen ist. Sie können Future-Methoden für jeden Vorgang verwenden, den Sie asynchron in seinem eigenen Thread ausführen möchten. Dies hat zum einen den Vorteil, dass der Benutzer nicht an der Durchführung anderer Vorgänge gehindert wird, und zum anderen gelten für den Prozess höhere Obergrenzen für die Ausführung. Es profitieren also alle Seiten von der asynchronen Verarbeitung.

Future-Methoden werden meist für folgende Zwecke verwendet:
  • Callouts an externe Webservices. Wenn Sie Callouts von einem Auslöser aus oder nach der Durchführung eines DML-Vorgangs durchführen, müssen Sie eine Future- oder Queueable-Methode verwenden. Durch einen Callout in einem Auslöser würde die Datenbankverbindung für die gesamte Lebensdauer des Callouts aufrecht erhalten und das ist in einer mandantenfähigen Umgebung ein Tabu.
  • Vorgänge, die Sie in ihrem eigenen Thread ausführen möchten, wenn der Zeitpunkt günstig ist, wie z. B. eine ressourcenintensive Berechnung oder Datensatzverarbeitung.
  • Isolieren von DML-Vorgängen für verschiedene sObject-Typen, um den Mixed DML-Fehler zu vermeiden. Dieser Anwendungsfall tritt jedoch eher selten auf. Weitere Einzelheiten finden Sie unter sObjects That Cannot Be Used Together in DML Operations.

Syntax von Future-Methoden

Future-Methoden müssen statische Methoden sein und dürfen nur einen void-Typ zurückgeben. Die angegebenen Parameter müssen primitive Datentypen, Arrays aus primitiven Datentypen oder Sammlungen primitiver Datentypen sein. Vor allem dürfen bei Future-Methoden keine standardmäßigen oder benutzerdefinierten Objekte als Argumente angegeben werden. Im allgemeinen wird der Methode eine Liste mit Datensatz-IDs übergeben, die asynchron verarbeitet werden sollen.

global class SomeClass {
  @future
  public static void someFutureMethod(List<Id> recordIds) {
    List<Account> accounts = [Select Id, Name from Account Where Id IN :recordIds];
    // process account records to do awesome stuff
  }
}
Hinweis

Hinweis

Der Grund, aus dem Objekte nicht als Argumente an Future-Methoden übergeben werden dürfen, besteht darin, dass sich das Objekt zwischen dem Zeitpunkt des Methodenaufrufs und dem Zeitpunkt der eigentlichen Ausführung ändern kann. Sie erinnern sich? Future-Methoden werden ausgeführt, wenn Systemressourcen verfügbar werden. Die Future-Methode könnte sonst bei ihrer tatsächlichen Ausführung einen alten Objektwert enthalten, was alle möglichen negativen Auswirkungen haben könnte.

Hier muss unbedingt darauf hingewiesen werden, dass es nicht garantiert ist, dass Future-Methoden in derselben Reihenfolge ausgeführt werden, in der sie aufgerufen wurden. Und noch einmal, weil es so wichtig ist: Es ist nicht garantiert, dass Future-Methoden in derselben Reihenfolge ausgeführt werden, in der sie aufgerufen wurden. Falls Sie diese Art der Funktionalität nicht brauchen, ist eventuell Queueable Apex die bessere Lösung für Sie. Bei der Verwendung von Future-Methoden besteht zudem die Möglichkeit, dass zwei Future-Methoden gleichzeitig ausgeführt werden. Dies kann zu einer Datensatzsperre und einem unschönen Laufzeitfehler führen, wenn die beiden Methoden denselben Datensatz aktualisieren.

Callout-Beispielcode

Wenn Sie einen Webservice-Callout zu einem externen Service oder einer API durchführen möchten, erstellen Sie eine Apex-Klasse mit einer Future-Methode, die mit (callout=true) gekennzeichnet ist. Die nachfolgende Klasse enthält zwei Methoden: eine für die synchrone und eine für die asynchrone Callout-Durchführung, sofern synchrone Callouts nicht zulässig sind. Wir fügen einen Datensatz in ein benutzerdefiniertes Protokollobjekt ein, um den Status des Callouts nachzuverfolgen. Warum? Weil Protokollieren einfach immer Spaß macht!

public class SMSUtils {

    // Call async from triggers, etc, where callouts are not permitted.
    @future(callout=true)
    public static void sendSMSAsync(String fromNbr, String toNbr, String m) {
        String results = sendSMS(fromNbr, toNbr, m);
        System.debug(results);
    }

    // Call from controllers, etc, for immediate processing
    public static String sendSMS(String fromNbr, String toNbr, String m) {
        // Calling 'send' will result in a callout
        String results = SmsMessage.send(fromNbr, toNbr, m);
        insert new SMS_Log__c(to__c=toNbr, from__c=fromNbr, msg__c=results);
        return results;
    }

}

Testklassen

Das Testen von Future-Methoden unterscheidet sich etwas vom normalen Apex-Testen. Zum Testen von Future-Methoden fügen Sie Ihren Testcode zwischen die Testmethoden startTest und stopTest ein. Das System sammelt alle asynchronen Aufrufe, die nach 'startTest' durchgeführt werden. Wenn stopTest ausgeführt wird, werden alle diese gesammelten, asynchronen Prozesse synchron ausgeführt. Sie können dann sicherstellen, dass der asynchrone Aufruf richtig funktioniert hat.

Hinweis

Hinweis

Da der Testcode keine echten Callouts an externe Systeme senden kann, müssen Sie den Callout für die Testabdeckung simulieren. Ausführliche Details zum Simulieren von Callouts beim Testen finden Sie im Modul Apex-Integrationsservices.

Hier sehen Sie unsere simulierte Callout-Klasse, die beim Testen verwendet wird. Das Apex-Test-Framework nutzt diese "simulierte" Antwort, anstelle den tatsächlichen Callout an den REST API-Endpunkt durchzuführen.

@isTest
global class SMSCalloutMock implements HttpCalloutMock {
    global HttpResponse respond(HttpRequest req) {
        // Create a fake response
        HttpResponse res = new HttpResponse();
        res.setHeader('Content-Type', 'application/json');
        res.setBody('{"status":"success"}');
        res.setStatusCode(200);
        return res; 
    }
}

Die Testklasse enthält eine einzige Testmethode, die sowohl die asynchrone als auch die synchrone Methode testet, da die asynchrone die synchrone Methode aufruft.

@IsTest
private class Test_SMSUtils {

  @IsTest
  private static void testSendSms() {
    Test.setMock(HttpCalloutMock.class, new SMSCalloutMock());
    Test.startTest();
      SMSUtils.sendSMSAsync('111', '222', 'Greetings!');
    Test.stopTest();
    // runs callout and check results
    List<SMS_Log__c> logs = [select msg__c from SMS_Log__c];
    System.assertEquals(1, logs.size());
    System.assertEquals('success', logs[0].msg__c);
  }

}

Bewährte Vorgehensweisen

Da bei jedem Aufruf einer Future-Methode eine Anforderung zur asynchronen Warteschlange hinzugefügt wird, sollten Sie Designmuster vermeiden, bei denen in einem kurzen Zeitraum viele Future-Anforderungen hinzugefügt werden. Wenn Ihr Design das Potenzial hat, 2000 oder mehr Anforderungen gleichzeitig hinzuzufügen, könnten Anforderungen aufgrund der Datenflusssteuerung verzögert werden. Hier sind einige bewährte Vorgehensweisen, die Sie im Hinterkopf behalten sollten:
  • Stellen Sie sicher, dass Future-Methoden so schnell wie möglich ausgeführt werden.
  • Versuchen Sie bei der Verwendung von Webservice-Callouts, alle Callouts innerhalb derselben Future-Methode zu bündeln, anstatt für jeden Callout eine separate Future-Methode zu verwenden.
  • Führen Sie gründliche Tests in der gewünschten Skalierung durch. Testen Sie, ob ein Auslöser, der die @future-Aufrufe in die Warteschlange einreiht, eine Auslösersammlung von 200 Datensätzen verarbeiten kann. Damit können Sie die Wahrscheinlichkeit von Verzögerungen für das Design mit dem aktuellen und künftigen Volumen feststellen.
  • Ziehen Sie die Verwendung von Batch-Apex anstelle von Future-Methoden für die asynchrone Verarbeitung großer Datensatzmengen in Erwägung. Dies ist effizienter als die Erstellung einer Future-Anforderung für jeden Datensatz.

Wichtige Punkte

Future-Methoden sind ein mächtiges Tool, doch große "Macht" bedeutet auch große Verantwortung. Hier sind einige Punkte, die Sie bei der Arbeit mit Future-Methoden beachten sollten:
  • Methoden mit der Anmerkung "future" müssen statische Methoden sein und dürfen nur einen void-Typ zurückgeben.
  • Die angegebenen Parameter müssen primitive Datentypen, Arrays aus primitiven Datentypen oder Sammlungen primitiver Datentypen sein. Bei Future-Methoden dürfen keine Objekte als Argumente angegeben werden.
  • Future-Methoden werden nicht zwingend in der Reihenfolge ausgeführt, in der sie aufgerufen werden. Es besteht zudem die Möglichkeit, dass zwei Future-Methoden gleichzeitig ausgeführt werden. Dies kann zu einer Datensatzsperre führen, wenn die beiden Methoden denselben Datensatz aktualisieren.
  • Future-Methoden können weder in Visualforce-Steuerfeldern in getMethodName() oder setMethodName() noch im Konstruktor verwendet werden.
  • Eine Future-Methode kann nicht innerhalb einer Future-Methode aufgerufen werden. Sie können auch nicht während der Ausführung einer Future-Methode einen Auslöser aufrufen, der eine Future-Methode aufruft. Weitere Informationen zur Vermeidung rekursiver Aufrufe von Future-Methode finden Sie unter dem im Abschnitt "Ressourcen" angegebenen Link.
  • Die Methoden getContent() und getContentAsPDF() dürfen in Methoden mit der Anmerkung "future" nicht verwendet werden.
  • Pro Apex-Aufruf dürfen maximal 50 Future-Methoden aufgerufen werden. Zusätzlich gibt es noch ein Limit für die Anzahl der Aufrufe innerhalb von 24 Stunden. Weitere Informationen zu Limits finden Sie unter dem unten angegebenen Link.

Ressourcen

Hinweis

Hinweis

Nicht vergessen: Dieses Modul bezieht sich auf Salesforce Classic. Wenn Sie Ihre Übungs-Organisation starten, wechseln Sie zu Salesforce Classic, um diese Aufgabe abzuschließen.