Scheduled Apex:
Scheduled
apex is all about to run a piece of apex code at some particular time within a
period of time. Schedule apex in Salesforce is a class that runs at a regular
interval of time. To schedule an apex class, we need to implement an interface
Schedulable.
global class SampleSchedulerClass implements Schedulable {
global void execute(SchedulableContext SC) {
//Some code that would be called
}
}
Apex Scheduler Limits
1. You can only have 100
scheduled Apex jobs at one time.
2. The maximum number of scheduled Apex
executions per a 24-hour period is 250,000 or the number of user licenses in
your organization multiplied by 200, whichever is greater.
3. Synchronous Web
service callouts are not supported from Scheduled Apex.
What is an Apex Scheduler?
Apex Scheduler is an ability to invoke an
Apex class to run at specific times.
To schedule an apex class, we need to implement an interface Schedulable.
What could be the use cases for Apex Scheduler?
1. Sending Periodic notifications to
users.
2. Tasks related to real-time updates.
3. Newsletter's on the 15th of every
month.
Ok. So, what are the prerequisites for the apex scheduler?
The apex class needs to implement the
Salesforce-provided interface Schedulable and override it’s execute()
method.
What is the parameter of the execute method ? - SchedulableContext
What is SchedulableContext?
Represents the parameter type of a method
in a class that implements the Schedulable interface and contains the scheduled
job ID using the getTriggerID() method. This interface is
implemented internally by Apex.
And what would be the use of that Job ID?
With that ID, we can track the Progress
of a Scheduled Job through a query on CronTrigger. The ID is of
type CronTrigger.
Moreover, we can go to Setup
---> Scheduled Jobs too, for monitoring.
What happens after the class is scheduled?
After a class has been scheduled, a CronTrigger object is created that represents the scheduled
job. It provides a getTriggerId method that returns the ID of a CronTrigger API object.
So, How can I schedule the apex class?
Once you are done with the
implementation. You can schedule it either through the
Developer console using system.schedule method.
|
|
SampleSchedulerClass
obj = new
SampleSchedulerClass(); String CRON_EXP = '20
30 8 10 2 ?'; String jobID =
system.schedule(‘Sample Scheduler Job’, CRON_EXP, obj); |
Here:
20 represents seconds
30 represents minutes
8 represents hour of the day
10 represents 10th day of month
2 represents month of the year
? represents day of the month
–> Go to Setup --->Apex Classes
You will see a “Schedule Apex” button.
You can set up the timing from there.
The difference between the two ways is
that in the system.schedule method we can also specify the minutes and
seconds as well but using the UI we can just mention the hour of the day.
What are the arguments of the System.Schedule method?
Once you are implemented schedulable
interface use system.schedulable method to execute the class.
system.schedule() method takes 3 parameters :
1. Name of the job.
2. An expression that is used to represent the time and date of the operation.
3. The object of the class which you want to execute.
What is return type of system.schedule?
System.schedule method returns the job ID in string format.
|
1 |
String jobID =
system.schedule(‘Sample Scheduler Job’, CRON_EXP, obj); |
As you mentioned that the jobID can be used to query the
progress, how can we track it?
We can simply fire a query to get
information about current job.
|
|
CronTrigger ct =
[SELECT CronExpression, CronJobDetailId, PreviousFireTime, TimesTriggered,
NextFireTime, State, StartTime, EndTime FROM CronTrigger
WHERE Id =: jobID]; |
What is this CronJobDetailId?
CronJobDetail is the parent CronTrigger
that saves a job’s information like Name, JobType, etc.
we can get these details too using the
same CronTrigger query.
|
1 2 |
CronTrigger job =
[SELECT Id, CronJobDetail.Id, CronJobDetail.Name, CronJobDetail.JobType FROM CronTrigger
where Id =: jobId]; |
OR
Can query on CronJobDetail with CronJobDetailId.
|
1 2 |
CronJobDetail ctd =
[SELECT Id, Name, JobType FROM CronJobDetail
WHERE Id = :CronJobDetailId]; |
what is CRON_EXP?
It is called CRON EXPRESSION which
is used to define the scheduling time. it has 6 to 7 inputs.
An expression is written in the form
of 'Seconds, Minutes, Hours, Day_of_month, Month, Day_of_week,
optional_year'.
it uses some special characters too
? — No Value
* — All Values
? — Specifies no specific value
/-Specifies increments. The number before the slash specifies when the
intervals will begin, and the number after the slash is the interval amount.
#-Specifies the nth day of the month, in the format weekday#day_of_month
L-Specifies the end of a range (last)
W-Specifies the nearest weekday(Monday-Friday) of the given day
Why is the purpose of special characters?
The purpose of special characters is to
define a range or interval. They are like wildcard characters in database
queries.
For example, If I want to run a job at 12
midnight on the 1st of every month in 2022.
My CRON_EXP would be : “0 0 0 1 * 2022”
Where * = all values possible for a month
i.e. 1–12
So let's say, I have scheduled an apex class to run at 7 pm
today, and at 7 pm, some batches are already running. How will your apex class
code run at 7 pm?
It will get scheduled on time because
Salesforce schedules the class for execution at the specified time, But
the Actual execution may be
delayed based on service availability. So, it will run once everything is done.
Cool, let’s say, I have scheduled an apex class to run at 3 pm
today, and at 3:15 pm, downtime occurred. What will happen now?
There could be 2 cases:
1. Before starting the job, downtime
occurred, in this case, Apex jobs will be scheduled to run after the service
comes back up, when system resources become available.
2. If a scheduled Apex job was running when
downtime occurred, the job is rolled back and scheduled again after the service
comes back up.
What async processes, I can schedule?
1. Batch Apex (can call a batch from
Scheduled Apex)
2. Future Method (can call future from Scheduled Apex)
3. Queueable Apex (can call queueable form Scheduled Apex)
Which of the above can cause an issue?
Calling the Future methods from scheduled
apex can cause some issue:
1. The future won’t guarantee it’s
execution on time, so tracking is not possible. Also, we lose transaction
control because the scheduled apex gets over as soon as it fires the future
method call.
2. There is a limit to the number of
future calls based on your number of licenses.
Want to schedule batch job at one time only and not again. How
to do it?
System.scheduleBatch() is used to run a schedule a batch job only once
for a future time. This method has got 3 parameters.
param 1 : Instance of a class that
implements Database.Batchable interface.
param 2 : Job name.
param 3 : Time interval after which the job should start executing.
param 4 : It’s an optional parameter
which will define the no. of that processed at a time.
The system.scheduleBatch() returns the scheduled job Id.We can use the job
Id to abort the job.
This method returns the scheduled
job ID also called CronTrigger ID.
|
|
String cronID =
System.scheduleBatch(reassign, 'job example', 1); CronTrigger ct = [SELECT Id, TimesTriggered, NextFireTime FROM
CronTrigger WHERE Id = :cronID]; |
This method is available only for batch
classes and doesn’t require the implementation of the Schedulable interface.
This makes it easy to schedule a batch job for one execution.
How to get count of Apex Scheduled Job programmatically?
You can programmatically query the CronTrigger and CronJobDetail objects
to get the count of Apex scheduled jobs.
If there are one or more active scheduled jobs for an Apex
class, can you update the class or any classes referenced in Salesforce UI?
If there are one or more active scheduled
jobs for an Apex class, you cannot update the class or any classes referenced
by this class through the Salesforce user interface. However, you can enable
deployments to update the class with active scheduled jobs by using the
Metadata API
Maximum, How many jobs can be scheduled at any point in time?
You can only have 100 scheduled Apex jobs
at one time. Either we can verify the count by viewing the Scheduled Jobs page.
OR
we can simply query with CronJobDetail.JobType as
7 (scheduled Apex) on CronTrigger>
|
|
SELECT COUNT() FROM
CronTrigger WHERE CronJobDetail.JobType = ‘7’ |
How to Call batch apex from schedulable class?
Create instance of batchClass and then
pass the instance in database.executebatch.
|
|
batchable b = new
batchable(); database.executebatch(b); |
An easier way to schedule a batch job is
to call the System.scheduleBatch method without having to implement the
Schedulable interface.
How to get Job name and job type for Scheduled jobs?
You can get job’s name and the job’s type
from the CronJobDetail record associated with the CronTrigger record.
Callout is not supported in Scheduled Apex so what is the
alternative?
Synchronous Web service callouts are not
supported from scheduled Apex. To be able to make callouts, make an asynchronous
callout by placing the callout in a method annotated with @future(callout=true)
and call this method from scheduled Apex. However, if your scheduled Apex
executes a batch job, callouts are supported from the batch class.
How can you stop the execution of a job that has already been
scheduled?
To stop the execution of a job that has
been scheduled, use the System.abortJob method with the ID
returned by the getTriggerID method.
Can we write a Unit test case for a scheduled Apex?
Yes we can.
Use the Test methods startTest and stopTest around
the System.schedule method to ensure it finishes before
continuing your test.
All asynchronous calls made after
the startTest method are collected by the system.
When stopTest is
executed, all asynchronous processes are run synchronously.
If you don’t include the System.schedule method
within the startTest and stopTest methods,
the scheduled job executes at the end of your test method
Apex Class:
|
|
global class
ScheduledApexTestExample implements Schedulable { // This test runs a scheduled job at midnight Sept. 19th. 2022 public static String CRON_EXP = '0 0 0 19 9 ? 2022'; global void execute(SchedulableContext ctx) { } } |
Test Class:
|
|
@istest class
TestClass { static
testmethod void test() { Test.startTest(); String jobId = System.schedule('testBasicScheduledApex', ScheduledApexTestExample.CRON_EXP, new
ScheduledApexTestExample()); // Get the information from the CronTrigger API object CronTrigger ct = [SELECT Id, CronExpression,
TimesTriggered, NextFireTime FROM CronTrigger WHERE id = :jobId]; // Verify the expressions are the same System.assertEquals(ScheduledApexTestExample.CRON_EXP,
ct.CronExpression); Test.stopTest(); } } |
Can you tell Best Practices to be followed while using Scheduled
Apex?
1. Synchronous Web service callouts are
not supported from scheduled Apex. To be able to make callouts, make an
asynchronous callout.
2. While scheduling a job from the
trigger, we must be able to guarantee that the trigger won’t add more scheduled
classes than the limit.
In a set list of
emails are stored in execute method. In the finish method that set is not
having any emails. What is the reason?
By default batch class is stateless. Emails which are
added to set can be remembered only in execute method. If we try to access the
set in finish method you won't see those emails. In finish method if you want
to access those emails of that set we should inherit the interface called Database.Stateful.
How to schedule batch
apex in minutes/hours?
To schedule the batch class in minutes/hours, in the
finish method we should use System.schedule method
which will take 3 parameters Job
Name, Crone Expression and schedulable class instance name respectively.
|
|
SchedulableUsage su = new SchedulableUsage(); //Preparing chron_exp Datetime sysTime = System.now(); sysTime = sysTime.addminutes(6); String chron_exp = '' +
sysTime.second() + ' '
+ sysTime.minute() + ' ' + sysTime.hour() + ' ' +
sysTime.day() + ' '
+ sysTime.month() + ' ? ' +
sysTime.year(); System.schedule('Dep Update'+sysTime.getTime(),chron_exp,
su); |
No comments:
Post a Comment