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.
Siga el proceso con Trail Together
¿Desea seguir el proceso con un instructor a medida que realiza este paso? Eche un vistazo a este video, que forma parte de la serie Trail Together en Trailhead Live.
(Este video comienza en el minuto 01:09:53 a.m., en caso de que desee rebobinar y mirar el comienzo del paso nuevamente).
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 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().
public class SomeClass implements Schedulable {
public 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.
public class RemindOpptyOwners implements Schedulable {
public 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
List<Task> tasks = new List<Task>();
for (Opportunity opp : opptys) {
Task newTask = new Task(
Subject = 'Update the Opportunity!',
Priority ='Normal',
Status = 'Not Started',
WhatId = opp.Id
);
tasks.add(newTask);
}
insert tasks;
}
}
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, independientemente de si el usuario tiene o no permiso para ejecutar las clases.
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 programada del trabajo, y una instancia de una clase que implemente la interfaz Schedulable.
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.
- En Setup (Configuración), ingrese
Jobs(Trabajos) en el cuadro de búsqueda rápida y, a continuación, seleccione Scheduled Jobs (Trabajos programados). - Haga clic en Programar Apex.
- Para el nombre del trabajo, ingrese algo parecido a
Daily Oppty Reminder(Recordatorio diario de oportunidades). - 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. - Seleccione
Weekly(Semanal) oMonthly(Mensual) para establecer la frecuencia que desee. - Seleccione las fechas de inicio y finalización, y una hora de inicio preferida.
- Haga clic en Guardar.
Prueba de Apex programado
Al igual que con otros métodos Apex 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 finalice antes de realizar las pruebas.
@IsTest
private class RemindOppyOwnersTest {
// Placeholder CRON expression: midnight on March 15.
// Because this is a test, job executes
// immediately after Test.stopTest(), not at the time set in the CRON expression
public static String CRON_EXP = '0 0 0 15 3 ? 2042';
@IsTest
static 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');
// Check the scheduled time
List<CronTrigger> ct = [SELECT Id, TimesTriggered, NextFireTime
FROM CronTrigger WHERE Id = :jobId];
System.debug('Next Fire Time ' + ct[0].NextFireTime);
}
}Aspectos que recordar
En el caso de Apex programado, hay una serie de aspectos que debe conocer (cuando pueda, consulte programador de Apex para obtener una lista completa). 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 período de 24 horas. Consulte Límites de ejecución y reguladores para obtener detalles.
- 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 síncronas 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
- Guía del desarrollador de Apex: Apex Scheduler
- Guía del desarrollador de Apex: Límites de ejecución y reguladores
