Batch Apex:
Batch Apex is a powerful feature in Salesforce that enables developers to handle large amounts of data in a structured manner. This feature allows for the processing of data in manageable chunks, known as batches, which helps in optimizing performance and avoiding system limitations.
Developers can define a job using Batch Apex, which is then divided into smaller batches. Each batch can process a specific number of records, ensuring efficient execution. This feature is particularly useful when there is a need to perform operations such as data manipulation or database updates on a large number of records within the Salesforce platform.
Batch Apex is commonly used for various scenarios, including data migration, data cleansing, and complex data transformations. It provides developers with control over the processing logic and allows for error handling, monitoring, and asynchronous execution. By utilizing Batch Apex, developers can effectively process and manipulate large datasets in a scalable and efficient manner within the Salesforce platform.
The purpose of batch apex is to divide a large set of records into smaller batches, each containing a limited amount of data. These batches are then processed independently from one another, with each batch operating under its own set of governing limits. If you wish to execute an apex class in a similar manner to batch apex, the class must implement the "Database. Batchable" interface. This interface requires the implementation of three methods: Start, Execute, and Finish.
Start Method: The start method is invoked when the batch job begins and gathers the data that needs to be processed. Its syntax is as follows: Database.QueryLocator start(Database.BatchableContext bc) {} When you use a simple query (SELECT...) to generate a range of records on which batch jobs should be run, you should use Database.QueryLocator. If QueryLocator objects are used, the total number of governors is limited. The number of records retrieved by the SOQL query is bypassed, and we can obtain up to 50 million records in the SOQL query. However, if you are using Iterable, all governing limits will still be enforced. The start method breaks the list of records into batches and invokes the execute method on each batch.
Execute Method: The execute method is called by the start method for each batch of records. It contains the business logic that needs to be performed on the records fetched from the start method. Its syntax is as follows: global void execute(Database.BatchableContext bc, List<sObject> scope) {} The "scope" parameter in the execute method contains the list of records in the batch job on which this execute method is running. For example, if the start method fetched 1000 records and divided them into 5 batches with 200 records in each batch, the execute method will be called separately for each batch (5 times).
Finish Method: The finish method is called after executing all the execute methods. It is used for batch operations that involve sending confirmation emails or performing any other necessary tasks. Its syntax is as follows: global void finish(Database.BatchableContext bc) {}.
Limits of Batch Apex
- At a time only 5 batch jobs will run.
- At a time 100 jobs can be added to flexQueue.
- In a batch Job, if any one of the batch jobs fails, only that batch will fail and the rest of the batches will execute normally.
- If the finish method fails, only the finish method will fail and changes made by the execute method will be committed.
- We cannot call future methods from batch vertices.
- We can call the batch job from the completion method of another batch job.
- If you want to call web services from the batch apex, the apex class has to implement the “Database. allowscallouts” interface.
- If the start method returns a QueryLocator, the optional scope parameter of Database.executeBatch can have a maximum value of 2,000. If set to a higher value, Salesforce chunks the records returned by the QueryLocator into smaller batches of up to 2,000 records. If the start method returns an iterable, the scope parameter value has no upper limit; however, if you use a very high number, you may run into other limits.
- If no size is specified with the optional scope parameter of Database.executeBatch, Salesforce chunks the records returned by the start method into batches of 200, and then passes each batch to the execute method. Apex governor limits are reset for each execution of execute.
- The start, execute, and finish methods can implement up to 10 callouts each
- The maximum number of batch executions is 250,000 per 24 hours.
- Only one batch Apex job’s start method can run at a time in an organization. Batch jobs that haven’t started yet remain in the queue until they’re started. Note that this limit doesn’t cause any batch job to fail and execute methods of batch Apex jobs still run in parallel if more than one job is running.
Test class for a batch Apex class
To create a test class for a batch Apex class in Salesforce, follow these steps:
1. Begin by creating a new Apex class and add the "@isTest" annotation at the top. This annotation indicates that the class is a test class.
2. Instantiate the batch Apex class that you want to test and set any required variables or parameters. 3. Use the "Test.startTest()" and "Test.stopTest()" methods to create a new test context for the batch Apex class. This is necessary for batch Apex testing.
4. Utilize the "Database.executeBatch()" method to execute the batch Apex class, passing in the instance created in the previous step.
5. Employ the "System.assert()" methods to verify that the batch Apex class is functioning as expected. 6. If you are testing a batch with a query, you can utilize the "Test.loadData()" method to insert test data into the database.
Here's an example of a test class for a batch Apex class called MyBatchApex:
@isTest
public class MyBatchApexTest {
@isTest static void testBatchApex() {
// Insert test data
List<Account> accounts = new List<Account>();
for (Integer i = 0; i < 150; i++) {
Account a = new Account();
a.Name = 'Test Account ' + i;
accounts.add(a);
}
insert accounts;
// Create an instance of the batch Apex class
MyBatchApex myBatch = new MyBatchApex();
// Start the test context
Test.startTest();
// Execute the batch Apex class
Database.executeBatch(myBatch);
// Stop the test context
Test.stopTest();
// Verify that the expected results have occurred
List<Account> processedAccounts = [SELECT Id, Name FROM Account WHERE Processed__c = true];
System.assertEquals(150, processedAccounts.size(), 'All accounts should be processed');
}
}
It is important to note that you must create test data for the class to operate on. The size of this data should be equal to or greater than the batch size defined in your class. Otherwise, the test will not cover the entire logic of the class.
Summary
In this post, we learn about what is Batch Apex in Salesforce and when we should use Batch Apex. I hope this helped you learn how batch class is used to process millions of records within normal processing limits.
Apex Scheduler:
The Apex Scheduler lets you delay execution to run Apex classes at a specified time. To schedule jobs, write an Apex class that implements the Schedulable interface, then schedule it for execution on a specific schedule.
How: Reducing the amount of manual work required in daily tasks. Methods:
1. Updating daily logs through the user interface.
2. Running batch classes either daily or at a specific time.
3. Scheduling emails to be sent at a designated time.
4. Performing daily or weekly maintenance tasks.
Approaches:
1. Utilizing the user interface to streamline daily record-keeping.
2. Automating batch class runs through the system. schedule method.
3. Scheduling emails to be sent automatically at a set time.
4. Implementing regular maintenance tasks to minimise manual effort.
1. Schedulable Apex
To schedule any class or code you need to follow two steps :
1. First implement the Schedulable interface for the class
2. Schedule an instance of the class to run at a specific time using the System.schedule method.
global class SomeClass implements Schedulable {
global void execute(SchedulableContext ctx) {
// awesome code here
}
}
- Implementation
public class schedulableApexDemo implements Schedulable{
public void execute(SchedulableContext ctx) {
List<Account> acs = [SELECT Id, Name From Account where
CreatedDate <= TODAY];
for(Account a : acs)
{
a.type = 'Prospect';
}
update acs;
}
}
- Schedule a method
After you implement a class with the Schedulable interface, use the System.Schedule method to execute it. The System.Schedule method uses the user's timezone for the basis of all schedules.
schedulableApexDemo demoReminder = new schedulableApexDemo ();
// timezone in Seconds Minutes Hours Day_of_month Month Day_of_week optional_year
String sch = '0 0 0 * ? *'; // run class daily at 12 AM
String jobID = System.schedule('Update Accounts', sch, demoReminder);
2. Schedule a batch class
1. Create a batch class
2. Write a schedulable class and call batch class from it.
3. Schedule it.
- Creating a batch class
global class batchAccountUpdate implements Database.Batchable<sObject> {
global Database.QueryLocator start(Database.BatchableContext BC) {
String query = 'SELECT Id,Name FROM Contact';
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, List<Contact> lstContact) {
for(Contact a : lstContact) {
a.firstName = a.firstName + '-------';
}
update lstContact;
}
global void finish(Database.BatchableContext BC) {
// you can do batch chaining
}
}
- Write a schedulable class and call batch class from it
To write a schedulable class you need to implement schedulable interface and implement the execute method as well. So put your logic into execute method.
global class DemoScheduleClass implements Schedulable {
global void execute(SchedulableContext ctx) {
// awesome code here
batchAccountUpdate b =new batchAccountUpdate();
Database.executeBatch(b);
}
}
- Schedule the class
Now, write a cron expression and call the schedule method. Open the anonymous window and copy the below code:-
DemoScheduleClass obj = new DemoScheduleClass ();
// timezone in Seconds Minutes Hours Day_of_month Month Day_of_week optional_year
String sch = '0 0 2 * ? *'; // run class daily at 2 AM
String jobID = System.schedule('Update Accounts', sch, obj);
3. Schedule a Queueable Class
This is same as scheduling a batch class the difference is in this case you need to implement the queueable interface.
public class queueableDemo implements Queueable {
public void execute(QueueableContext context) {
Account a = new Account(Name='test',Phone='832323232');
insert a;
}
}
Schedulable class for above class
public class queueableScheduleDemo implements schedulable {
public void execute(SchedulableContext context) {
system.enqueueJob(new queueableDemo());
}
}
Now, As above mentioned write a cron expression and call the schedule method. Open the anonymous window and copy the below code:-
queueableScheduleDemo m = new queueableScheduleDemo();
String sch = '0 0 3 * * ?';
String jobID = system.schedule('Queue', sch, new queueableScheduleDemo());
How to schedule a class to run once at a specific time from apex?
Salesforce provides a built-in feature that allows you to schedule apex classes with certain limitations on frequency control. This can be accessed through the setup menu by navigating to apex classes and clicking on the "Schedule Apex" button. However, this method restricts the execution of apex classes to the beginning of each hour. If you require more precise scheduling for your apex classes, you can utilize custom CRON expressions. These expressions offer a more flexible approach to running scheduled apex classes at specific times.
//This can be any time in future
Datetime nextRun = System.now().addHours(2);
//Generating cron expression for next run time
String year = String.valueOf(nextRun.year());
String day = String.valueOf(nextRun.day());
String hour = String.valueOf(nextRun.hour());
String min = String.valueOf(nextRun.minute());
String sec = String.valueOf(nextRun.second());
String cronExp = sec + ' ' + min + ' ' + hour + ' '+day+' '+nextRun.format('MMM').toUpperCase()+' ? '+year;
//Scheduling at the specified time
TrackerSchedulable trackerJob = new TrackerSchedulable();
System.schedule('Tracker Job', cronExp, trackerJob);
0 Comments