How do I schedule APEX programmatically?
Scheduled APEX is great. In fact, in the Salesforce world itโs the only way to queue up code to be run repeatedly at a set time of day / week / month / year. Itโs like a cron job. It even uses a cron-like notation. Suppose you want to run a monthly job on the first of every month that loads any Opportunities that are open but have passed their close date, and for each one creates a high priority task for its owner requesting an update. This would be a perfect time to use Scheduled Apex. In this case youโd probably want to marry it with Batchable Apex too, incidentally, to avoid limits.
A scheduled job can be enqueued via the setup menu, or via code. This is about doing it via code. Why do it like this? Because if you do it in the setup menu you have to specify an end date so you canโt schedule a job indefinitely.
Yes, you need to create a class that implements the Schedulable interface. We could show you, but Salesforce has already done a good job of thatโฆ thereโs good documentation on doing that in the Apex Developer Guide, and thereโs a Trailhead Module that covers it.
Well, according to Salesforce, something like this:
MySchedulableClass sched = new MySchedulableClass();
String cronExp = '0 30 8 1 * * *'; // 8:30am every 1st day of the month
String jobID = System.schedule('Something descriptive', cronExp, sched);
This is great, open up your Developer Console, pop that into anonymous APEX and away you go. The Salesforce docs give you a lot of warnings about being careful where you call this code, particularly with Triggers, as you could wind up running the same thing multiple times which would be a Bad Thingโข. So donโt, especially if this is a repeating task, just do it in the Developer Console.
Funny you should ask. Not only is this a fair bit to type, you may also find yourself having to remember it quite often, as youโll see in a minute. First though, hereโs the pattern we use for Schedulable classes (batchable class example included for completeness):
global class MyJobSchedulable implements Schedulable {
/*
Run at 8:30 am on the first of every month. Remember this is
Scheduled in the Userโs timezone who schedules the job, not UTC
*/
public static final String CRON_EXPR = โ0 30 8 1 * * *โ;
/*
Call this from Anonymous Apex to schedule at the default regularity
*/
global static String scheduleIt() {
MyJobSchedulable job = new MyJobSchedulable();
return System.schedule(โSomething Descriptiveโ, CRON_EXPR, job);
}
global void execute(SchedulableContext sc) {
// This is good practice if you are likely to be processing a
// lot of records at a time
MyJobBatchable b = new MyJobBatchable();
Database.executeBatch(b);
}
}
With this setup you can avoid having to remember all the incantations, and simply run the following in anonymous apex instead
MyJobSchedulable.scheduleIt();
Done. Easy. The something descriptive string is shown in the scheduled jobs list so make it something that summarises to future you what it is your job is doing.
Hereโs one of the gotchas of scheduled Apex jobs:
You cannot release updated versions of any code that is used by your scheduled job without first deleting your scheduled job.
This includes the Schedulable class itself, the Batchable class (if youโre using one) and any service classes that you might be delegating the work out to. If you like to create reusable, shared code, to reduce duplication and the risk of code rot, then this is likely to be a problem for you. This makes having a simple to remember, difficult to get wrong pattern (like the above) for scheduling your job almost critical.
Firstly, Salesforce makes no promises that your scheduled job will run at exactly the time specified (from the docs):
โSalesforce schedules the class for execution at the specified time. Actual execution may be delayed based on service availability.โ
If this isnโt the case, then itโs likely that the user you used to schedule the job has a different time zone set on their profile to the one you are expecting your job to run in. For example, If your user has the GMT time zone set, then the example above will run at 8:30am GMT. If you are in the USA, on EST the job will run at 3:30am. This gets EVEN more confused based on daylight savings. But I wonโt go into that here because time zones are hard
Tom
Our independent tech team has been servicing enterprise clients for over 15 years from our HQ in Bristol, UK. Let’s see how we can work together and get the most out of your Salesforce implementation.