Apex Scheduling

How do I schedule APEX programmatically?

Wait… What even is it?

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.

I haven’t created my schedulable class yet, can you help?

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.

Get to the point, how do I schedule 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.

That’s quite a bit to remember and type correctly, got anything better?

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.

What’s that about remembering the incantation to schedule my job?

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.

Help, my scheduled job is running at the wrong time what’s going on?

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 Blockley, Salesforce DeveloperThanks!

Tom

Amy Grenham October 17, 2017

8 thoughts on “How do I schedule APEX programmatically?

  • Nice post Tom! Do you know what the apex code is to cancel a batch job?

    I’m trying to figure it out and this code I’m using produces the error below:

    string SCHEDULE_NAME = ‘MergeMetricsCalculationBatchable’;
    System.abortJob(SCHEDULE_NAME);

    Execute Anonymous Error
    Line: 2, Column: 1
    System.StringException: Only CronTrigger IDs and batch, future, and queueable job IDs are supported.

    Any help on this would help. I’ve been searching everwhere and seems the suggestions aren’t working for me.

    Thanks!

    • Hi Nick,

      I believe that abortJob requires a Job Id not a job name. So you would need to pass it the jobID provided by:
      String jobID = System.schedule('Something descriptive', cronExp, sched);

      You could store that in Salesforce somewhere if you wanted to use it later. Alternatively, I believe that you can query Salesforce to get the Id of a scheduled job via SOQL through the CronJobDetail and CronTrigger objects.

      I haven’t tried this myself as as I’ve never needed to, but this discussion in the Developer Forum has a number of suggestions. In particular you might try KGalant’s answer towards the bottom.

  • How we csn schedule a job to run only on working days . Suppose is monday is holiday how we can make job to run on tuesday not on weekend ( sat sun )and monday(holiday).

Leave a Reply

Your email address will not be published. Required fields are marked *