Suivez votre progression
Accueil Trailhead
Accueil Trailhead

Utilisation de méthodes futures

Objectifs de formation

Dans cette unité, vous allez découvrir :

  • Quand utiliser des méthodes futures
  • Les limitations d’utilisation de méthodes futures
  • Comment utiliser des méthodes futures pour des appels externes
  • Les meilleures pratiques d’utilisation de méthodes futures

Apex futur

Un code Apex futur est utilisé pour exécuter des processus ultérieurement dans un thread distinct, lorsque les ressources système sont disponibles.

Remarque : Techniquement, vous utilisez l’annotation @future pour identifier les méthodes exécutées de façon asynchrone. Cependant, l’expression « méthode identifiée avec l’annotation @future » est laborieuse. Par conséquent, elles sont communément appelées « méthodes futures », expression que nous allons employer dans ce module.

Lors de l’utilisation d’un traitement synchrone, tous les appels de méthode proviennent du même thread qui exécute le code Apex, et aucun traitement supplémentaire ne peut être effectué avant la fin du processus. Vous pouvez utiliser des méthodes futures pour toute opération que vous souhaitez exécuter de façon asynchrone dans son propre thread. Avec les méthodes futures, l’utilisateur peut exécuter d’autres opérations, et vous pouvez définir des limitations du gouverneur et d’exécution supérieures pour le processus. Le traitement asynchrone satisfait tout le monde.

Les méthodes futures sont généralement utilisées pour les opérations suivantes :
  • Des appels externes à des services Web externes. Si vous effectuez des appels externes à partir d’un déclencheur ou après l’exécution d’une opération DML, vous devez utiliser une méthode future ou pour file d'attente. Un appel externe dans un déclencheur garderait la connexion à la base de données ouverte pendant la durée de vie de l’appel externe, ce qui est interdit dans un environnement mutualisé.
  • Les opérations que vous souhaitez exécuter dans leur propre thread, lorsque les conditions sont favorables, par exemple un calcul ou un traitement d’enregistrements qui mobilise des ressources importantes.
  • L’isolation des opérations DML sur différents types de sObject afin d’éviter l’erreur d’opérations DML mixtes. Il s’agit d’un cas extrême, mais vous pouvez parfois rencontrer cette erreur. Pour plus informations, reportez-vous à sObjects That Cannot Be Used Together in DML Operations (en anglais).

Syntaxe d'une méthode future

Les méthodes futures sont des méthodes statiques qui peuvent renvoyer uniquement un type void. Les paramètres spécifiés doivent être des types de données primitifs, des groupes de types de données primitifs ou des collections de types de données primitifs. En particulier, les méthodes futures ne peuvent pas accepter des objets standard ou personnalisés en tant qu’arguments. Un modèle courant consiste à transmettre à la méthode une liste d’ID d’enregistrement que vous souhaitez traiter de façon asynchrone.

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
  }
}
Remarque

Remarque

Un objet ne peut pas être transmis à des méthodes futures en tant qu’argument, car il peut changer entre l’appel de la méthode et son exécution. Souvenez-vous que les méthodes futures sont exécutées lorsque les ressources système sont disponibles. Dans ce cas, la méthode future peut inclure une ancienne valeur d’objet lors de son exécution, ce qui peut entraîner divers problèmes.

Il est important de noter que les méthodes futures ne sont pas nécessairement exécutées dans l’ordre dans lequel elles sont appelées. Insistons sur ce point, l’ordre d’exécution des méthodes futures n’est pas garanti. Si vous avez besoin de ce type de fonctionnalité, un code Apex pour file d'attente est probablement une meilleure solution. Lors de l’utilisation de méthodes futures, il se peut également que deux méthodes futures soient exécutées simultanément, ce qui peut entraîner un verrouillage d’enregistrement et une erreur d’exécution si les deux méthodes mettent à jour le même enregistrement.

Exemple de code d’appel externe

Pour exécuter un appel externe de service Web à un service externe ou une API, vous créez une classe Apex avec une méthode future marquée avec (callout=true). La classe ci-dessous contient les méthodes d’exécution de l’appel de façon synchrone et asynchrone lorsque les appels externes ne sont pas autorisés. Nous insérons un enregistrement dans un objet de journal personnalisé pour suivre le statut de l’appel externe, simplement parce que la consignation est toujours intéressante !

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;
    }

}

Classes de test

Le test de méthodes futures est légèrement différent que le test Apex classique. Pour tester des méthodes futures, insérez votre code test entre les méthodes de test startTest et stopTest. Le système collecte tous les appels asynchrones effectués après startTest. Lorsque stopTest est exécuté, tous ces processus asynchrones collectés sont exécutés de façon synchrone. Vous pouvez ensuite affirmer que l’appel asynchrone fonctionne correctement.

Remarque

Remarque

Le code test ne peut pas envoyer d’appels externes à des systèmes externes. Par conséquent, vous devez « simuler » l’appel externe pour la couverture de test. Pour des informations complètes sur la simulation d’appels externes à des fins de tests, consultez le module Apex Integration Services.

Notre classe d’appel externe fictive pour le test se présente comme suit. L’infrastructure de test Apex utilise cette réponse fictive au lieu de transmettre l’appel externe au point de terminaison de l’API REST.

@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; 
    }
}

La classe de test contient une seule méthode de test. Elle teste la méthode asynchrone et la méthode synchrone, la première appelant la dernière.

@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);
  }

}

Meilleures pratiques

L’invocation de chaque méthode future ajoute une requête à la file d’attente asynchrone. Par conséquent, évitez les modèles de conception qui ajoutent un nombre important de requêtes futures sur une courte période. Si votre conception peut ajouter 2000 requêtes ou plus à la fois, les requêtes peuvent être retardées en raison du contrôle du flux. Tenez compte des pratiques recommandées ci-dessous :
  • Assurez-vous que les méthodes futures sont exécutées aussi rapidement que possibles.
  • Si vous utilisez des appels externes de service Web, essayez de regrouper tous les appels externes de la même méthode future au lieu d’utiliser une méthode future séparée pour chaque appel externe.
  • Effectuez des tests complets à l’échelle. Effectuez un test pour déterminer si un déclencheur mettant en file d’attente des appels @future peut gérer une collection de déclencheur de 200 enregistrements. Vous pouvez ainsi déterminer si la conception des volumes actuels et futurs entraîne des délais.
  • Utilisez un code Apex par lot plutôt que des méthodes futures pour traiter simultanément un grand nombre d’enregistrements. Cette solution est plus efficace que la création d’une requête future pour chaque enregistrement.

À retenir

Les méthodes futures sont très efficaces, mais leur puissance doit être contrôlée. Lors de l’utilisation de méthodes futures, tenez compte des points suivants :
  • Les méthodes avec une annotation future doivent être statiques et peuvent renvoyer uniquement un type void.
  • Les paramètres spécifiés doivent être des types de données primitifs, des groupes de types de données primitifs ou des collections de types de données primitifs. Les méthodes futures ne peuvent pas accepter des objets en tant qu’arguments.
  • L’ordre d’exécution des méthodes futures ne correspond pas nécessairement à l’ordre dans lequel elles sont appelées. En outre, deux méthodes futures peuvent être exécutées simultanément, ce qui peut entraîner un verrouillage d’enregistrement si les deux méthodes mettent à jour le même enregistrement.
  • Les méthodes futures ne peuvent pas être utilisées dans des contrôleurs Visualforce dans getMethodName(), setMethodName(), ni dans le constructeur.
  • Vous ne pouvez pas appeler une méthode future à partir d’une méthode future. Vous ne pouvez pas non plus invoquer un déclencheur qui appelle une méthode future tout en exécutant une méthode future. Pour empêcher les appels de méthode future récursifs, suivez le lien « Preventing Recursive Future Method Calls in Salesforce » dans la section Ressources.
  • Les méthodes getContent() et getContentAsPDF() ne peuvent pas être utilisées dans des méthodes avec une annotation future.
  • Vous êtes limité(e) à 50 appels futurs par invocation Apex avec une limite supplémentaire en nombre d’appels par période de 24 heures. Pour plus d’informations sur ces limitations, suivez le lien ci-dessous.

Ressources

Remarque

Remarque

N’oubliez pas que ce module est conçu pour Salesforce Classic. Lorsque vous lancez votre organisation d’exercice, basculez vers Salesforce Classic pour relever ce défi.