Empiece a realizar un seguimiento de su progreso
Inicio de Trailhead
Inicio de Trailhead

Usar métodos futuros

Objetivos de aprendizaje

Después de completar esta unidad, tendrá conocimientos sobre lo siguiente:

  • Cuándo usar los métodos futuros.
  • Limitaciones de uso de métodos futuros.
  • Cómo usar métodos futuros para llamadas.
  • Mejores prácticas para métodos futuros.

Apex futuro

Apex futuro se usa para ejecutar procesos en un subproceso independiente y en un momento posterior en el que los recursos del sistema estén disponibles.

Nota: Técnicamente, debe usar la anotación @future para identificar los métodos que se ejecutan de forma asíncrona. No obstante, dado que los "métodos identificados con la anotación @future" son laboriosos, se suelen llamar "métodos futuros" y así es como haremos referencia a ellos en el resto de este módulo.

Cuando se usa el procesamiento síncrono, todas las llamadas a métodos se realizan desde el mismo subproceso que ejecuta el código Apex y no se realiza ningún procesamiento adicional hasta que el proceso finaliza. Puede usar métodos futuros para cualquier operación que desee ejecutar de forma asíncrona en su propio subproceso. Las ventajas son que de este modo no se impide al usuario que realice otras operaciones y además se aplican límites reguladores y de ejecución superiores al proceso. Por lo tanto, todo son ventajas en el caso del procesamiento asíncrono.

Los métodos futuros se suelen usar para lo siguiente:
  • Llamadas a servicios web externos. Si va a hacer llamadas desde un desencadenador o después de realizar una operación DML, debe usar un método futuro o válido para la inclusión en cola. Una llamada en un desencadenador mantendría abierta la conexión con la base de datos durante todo el transcurso de la llamada, lo cual es inaceptable en el caso de un entorno de múltiples arrendatarios.
  • Operaciones que desea ejecutar en su propio subproceso si el tiempo lo permite, como determinados tipos de cálculo o procesamiento de registros que requieren un uso intensivo de los recursos.
  • Aislamiento de operaciones DML en distintos tipos de sObject para evitar un error de mezcla de DML. Aunque se trata en cierto modo de un caso extremo, podría encontrarse con este problema ocasionalmente. Consulte sObjects que no pueden utilizarse juntos en operaciones DML para obtener más información.

Sintaxis de métodos futuros

Los métodos futuros deben ser métodos estáticos y solo pueden devolver un tipo nulo. Los parámetros especificados deben ser tipos de datos primitivos, matrices de tipos de datos primitivos o colecciones de tipos de datos primitivos. En concreto, los métodos futuros no pueden usar objetos estándar o personalizados como argumentos. Un patrón común es pasar al método una lista de los Id. de registro que desea procesar de forma asíncrona.

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

Nota

El motivo por el que no se pueden pasar objetos como argumentos a los métodos futuros es que un objeto puede cambiar entre el momento en el que llama al método y el momento en el que este se ejecuta realmente. Recuerde que los métodos futuros se ejecutan cuando los recursos del sistema están disponibles. En este caso, el método futuro puede incluir el valor de un objeto anterior cuando se ejecuta realmente, lo que puede provocar un auténtico desastre.

Es importante tener en cuenta que no se garantiza la ejecución de los métodos futuros en el mismo orden que en la llamada. Repetimos, no se garantiza la ejecución de los métodos futuros en el mismo orden que en la llamada. Si necesita este tipo de funcionalidad, el uso de Apex para la inclusión en cola puede ser una solución mejor. Cuando se usan métodos futuros, también es posible que dos métodos futuros se ejecuten simultáneamente, lo que puede provocar el bloqueo de registros y un error de tiempo de ejecución grave si ambos métodos actualizan el mismo registro.

Código de llamada de ejemplo

Para hacer una llamada de servicio web a un servicio o una API externos, debe crear una clase de Apex con un método futuro marcado con (callout=true). La clase siguiente incluye métodos para hacer la llamada de forma síncrona y de forma asíncrona, aunque las llamadas no se permiten. En realidad, hemos insertado un registro en un objeto de registro personalizado para hacer un seguimiento del estado de la llamada por el mero hecho de que las tareas de registro siempre son divertidas.

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

}

Clases de prueba

La prueba de métodos futuros varía ligeramente en comparación con la prueba de Apex típica. Para probar métodos futuros, incluya el código de prueba entre los métodos de prueba startTest y stopTest. El sistema recopila todas las llamadas asíncronas realizadas después de startTest. Cuando se ejecuta stopTest, todos estos procesos asíncronos recopilados se ejecutan de forma síncrona. A continuación, puede confirmar que la llamada asíncrona ha funcionado correctamente.

Nota

Nota

Dado que el código de prueba no puede realmente enviar llamadas a sistemas externos, debe ‘simular’ la llamada para la cobertura de prueba. Consulte el módulo Servicios de integración de Apex para obtener información detallada sobre las llamadas simuladas para pruebas.

Esta es la clase de llamada simulada que hemos usado para las pruebas. El marco de pruebas de Apex usa esta respuesta ‘simulada’ en lugar de hacer una llamada real al extremo de la API de 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 clase de prueba contiene un solo método de prueba, lo que permite probar los métodos asíncrono y síncrono cuando el primero llama al último.

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

}

Mejores prácticas

Dado que cada invocación de un método futuro agrega una única solicitud a la cola asíncrona, evite patrones de diseño que agreguen un gran número de solicitudes futuras en un breve periodo de tiempo. Si el diseño tiene capacidad para agregar 2000 o más solicitudes a la vez, estas solicitudes se podrían retrasar debido al control de flujo. Estas son algunas mejores prácticas que debe tener en cuenta:
  • Asegúrese de que los métodos futuros se ejecuten lo más rápidamente posible.
  • Si va a usar llamadas de servicio web, procure agrupar todas las llamadas del mismo método futuro en lugar de usar un método futuro independiente para cada llamada.
  • Realice pruebas exhaustivas a escala. Realice una prueba para determinar si un desencadenador que pone en cola las llamadas @future tiene capacidad para procesar una colección de desencadenador de 200 registros. Esto ayuda a determinar si se pueden producir retrasos debido al diseño con los volúmenes actuales y futuros.
  • Considere la posibilidad de usar Apex por lotes en lugar de métodos futuros para procesar un gran número de registros de forma asíncrona. Esta opción es más eficiente que crear una solicitud futura para cada registro.

Aspectos que recordar

Los métodos futuros son una herramienta excelente, pero su amplia capacidad implica una gran responsabilidad. Estos son algunos de los aspectos que debe tener en cuenta cuando use estos métodos:
  • Los métodos anotados como futuros deben ser métodos estáticos y solo pueden devolver un tipo void.
  • Los parámetros especificados deben ser tipos de datos primitivos, matrices de tipos de datos primitivos o colecciones de tipos de datos primitivos. Los métodos futuros no pueden usar objetos como argumentos.
  • Los métodos futuros no se ejecutan necesariamente en el mismo orden que en la llamada. Además, es posible que dos métodos futuros se ejecuten simultáneamente, lo que puede provocar el bloqueo de registros si ambos métodos actualizan el mismo registro.
  • Los métodos futuros no se pueden usar en controladores de Visualforce en getMethodName(), setMethodName() ni en el constructor.
  • No se puede llamar a un método futuro desde un método futuro. Además, no puede invocar un desencadenador que llame a un método futuro mientras se ejecuta un método futuro. Consulte el vínculo de la sección Recursos para obtener información sobre cómo evitar las llamadas a métodos futuros recurrentes.
  • Los métodos getContent() y getContentAsPDF() no se pueden usar en métodos anotados como futuros.
  • El límite es de 50 llamadas a métodos futuros por cada invocación de Apex y se aplica un límite adicional al número de llamadas en un periodo de 24 horas. Para obtener más información sobre los límites, consulte el vínculo incluido a continuación.

Recursos

Nota

Nota

Recuerde, este módulo está pensado para Salesforce Classic. Cuando inicie su organización para realizar prácticas, cambie a Salesforce Classic para completar este reto.