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

Programar trabajos con el programador de Apex

Objetivos de aprendizaje

Después de completar esta unidad, tendrá conocimientos sobre lo siguiente:
  • Cuándo usar Apex programado.
  • Cómo monitorear trabajos programados.
  • Sintaxis de Apex programado.
  • Mejores prácticas para métodos programados.

Apex programado

El programador de Apex permite retrasar la ejecución para que pueda ejecutar clases de Apex en un momento especificado. Esta opción es ideal para tareas de mantenimiento diarias o semanales mediante Apex por lotes. Para aprovechar las ventajas del programador, escriba una clase de Apex que implemente la interfaz Schedulable (programable) y, a continuación, prográmela para la ejecución según una programación específica.

Sintaxis de Apex programado

Para invocar clases de Apex para su ejecución en momentos específicos, primero debe implementar la interfaz Schedulable para la clase correspondiente. A continuación, programe una instancia de la clase para su ejecución en un momento específico mediante el método System.schedule.

global class SomeClass implements Schedulable {
    global void execute(SchedulableContext ctx) {
        // awesome code here
    }
}

La clase implementa la interfaz Schedulable y debe implementar el único método que contiene esta interfaz, que en este caso es el método execute.

El parámetro de este método es un objeto SchedulableContext. Una vez que se ha programado una clase, se crea un objeto CronTrigger que representa el trabajo programado. En este caso, se proporciona un método getTriggerId que devuelve el Id. de un objeto de API CronTrigger.

Código de ejemplo

Esta clase consulta las oportunidades abiertas que deberían estar cerradas en la fecha actual y crea una tarea en cada caso para recordar al propietario que actualice la oportunidad.

global class RemindOpptyOwners implements Schedulable {

    global void execute(SchedulableContext ctx) {
        List<Opportunity> opptys = [SELECT Id, Name, OwnerId, CloseDate 
            FROM Opportunity 
            WHERE IsClosed = False AND 
            CloseDate < TODAY];
        // Create a task for each opportunity in the list
        TaskUtils.remindOwners(opptys);
    }
    
}

Puede programar la clase para que se ejecute mediante programación o bien en la interfaz de usuario del programador de Apex.

Uso del método System.Schedule

Después de implementar una clase con la interfaz Schedulable, use el método System.Schedule para ejecutarla. El método System.Schedule usa la zona horaria del usuario como la base de todas las programaciones, pero se ejecuta en el modo del sistema. Es decir, se ejecutan todas las clases con independencia de que el usuario tenga o no permiso para ejecutar las clases.

Nota

Nota

Extreme la precaución si su plan es programar una clase desde un desencadenador. Debe poder garantizar que el desencadenador no agregará un número de clases de trabajo programadas superior al límite. En concreto, debe considerar la posibilidad de usar actualizaciones masivas de la API, asistentes de importación, cambios de registros masivos mediante la interfaz de usuario y todos los casos en los que es posible actualizar más de un registro a la vez.

El método System.Schedule usa tres argumentos: un nombre para el trabajo, una expresión CRON para representar la hora y la fecha de la ejecución del trabajo programada, y el nombre de la clase.

RemindOpptyOwners reminder = new RemindOpptyOwners();
// Seconds Minutes Hours Day_of_month Month Day_of_week optional_year
String sch = '20 30 8 10 2 ?';
String jobID = System.schedule('Remind Opp Owners', sch, reminder);

Para obtener más información sobre el uso de la expresión CRON para la programación consulte la sección sobre el uso del método System.Schedule en Apex Scheduler.

Programación de un trabajo en la interfaz de usuario

Otra opción es programar una clase mediante la interfaz de usuario.
  1. En Configuración, ingrese Apex en el cuadro Búsqueda rápida y, a continuación, seleccione Clases de Apex.
  2. Haga clic en Programar Apex.
  3. Para el nombre del trabajo, ingrese algo parecido a Daily Oppty Reminder.
  4. Haga clic en el botón de búsqueda junto a la clase de Apex e ingrese * como término de búsqueda para obtener una lista de todas las clases que se pueden programar. En los resultados de la búsqueda, haga clic en el nombre de la clase programada.
  5. Seleccione Semanal o Mensual para establecer la frecuencia que desee.
  6. Seleccione las fechas de inicio y finalización, y una hora de inicio preferida.
  7. Haga clic en Guardar.

Prueba de Apex programado

Al igual que ocurre con otros métodos asíncronos que hemos descrito, en el caso de Apex programado también debe asegurarse de que el trabajo programado haya finalizado antes de realizar pruebas con los resultados. Para ello, use startTest y stopTest de nuevo con el método System.schedule para asegurarse de que el proceso ha finalizado antes de realizar las pruebas.

@isTest
private class RemindOppyOwnersTest {

    // Dummy CRON expression: midnight on March 15.
    // Because this is a test, job executes
    // immediately after Test.stopTest().
    public static String CRON_EXP = '0 0 0 15 3 ? 2022';

    static testmethod void testScheduledJob() {

        // Create some out of date Opportunity records
        List<Opportunity> opptys = new List<Opportunity>();
        Date closeDate = Date.today().addDays(-7);
        for (Integer i=0; i<10; i++) {
            Opportunity o = new Opportunity(
                Name = 'Opportunity ' + i,
                CloseDate = closeDate,
                StageName = 'Prospecting'
            );
            opptys.add(o);
        }
        insert opptys;
        
        // Get the IDs of the opportunities we just inserted
        Map<Id, Opportunity> opptyMap = new Map<Id, Opportunity>(opptys);
        List<Id> opptyIds = new List<Id>(opptyMap.keySet());

        Test.startTest();
        // Schedule the test job
        String jobId = System.schedule('ScheduledApexTest',
            CRON_EXP, 
            new RemindOpptyOwners());         
        // Verify the scheduled job has not run yet.
        List<Task> lt = [SELECT Id 
            FROM Task 
            WHERE WhatId IN :opptyIds];
        System.assertEquals(0, lt.size(), 'Tasks exist before job has run');
        // Stopping the test will run the job synchronously
        Test.stopTest();
        
        // Now that the scheduled job has executed,
        // check that our tasks were created
        lt = [SELECT Id 
            FROM Task 
            WHERE WhatId IN :opptyIds];
        System.assertEquals(opptyIds.size(), 
            lt.size(), 
            'Tasks were not created');

    }
}

Aspectos que recordar

En el caso de Apex programado, hay una serie de aspectos que debe conocer (consulte la información sobre el programador de Apex en la sección Recursos para ver la lista completa cuando tenga tiempo). En líneas generales, debe prestar atención a lo siguiente:
  • Solo puede tener 100 trabajos de Apex programados a la vez y hay un número máximo de ejecuciones de Apex programadas durante cada periodo de 24 horas. Consulte los límites de ejecución y reguladores en la sección Recursos para obtener información detallada.
  • Extreme la precaución si su plan es programar una clase desde un desencadenador. Debe poder garantizar que el desencadenador no agregará un número de trabajos programados superior al límite.
  • Las llamadas de servicio web no son compatibles con Apex programado. Para poder hacer llamadas, realice una llamada asíncrona mediante la inclusión de la llamada en un método anotado con @future(callout=true) y llame a este método desde Apex programado. Sin embargo, si Apex programado ejecuta un trabajo por lotes, las llamadas son compatibles con la clase por lotes.

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.