This quick test is made to test your basic understanding of Batch Apex.

  • You can look at the syntax, bonus points if you don’t.
  • The test should ideally not take more than 15 minutes to solve.
  • All the criterias must be met.
  • The answer is available at Admin2Dev GitHub Repo.
  • The answer and complete breakdown of the program is available at the end of this page.

The Test

Question

  • Insert 250 contacts with the last name "Test n" where n is a number starting from 1. For reference, the names should look like Test 1, Test 2 .. .Test 250.
  • If a Contact with the last name DeleteBatch is created, it should run a Batch Apex Class that deletes all contacts with the last name "Test n" where n is a number.
  • When the Batch Apex finishes running, it should update the description of "Delete" contact with "Deleted records with ID JobID" where JobID should be the ID of the Batch Apex Class.
Hint
  • Use getJobID() method on Database.batchableContext variable to get the Job ID.
  • Use the escape character \ to add ' to your Strings. So to write 'Test', you have to write \'Test\' instead.
  • The changes may not be visible instantly. Give it about 5 minutes before you see contacts being deleted and description updates.

Start a timer and note how long you take to solve. Ideally, it should take ~15 minutes, but don’t worry if you go overboard.


Answer

Inserting 250 records

  • You can either create a class and call it from Anon Exec Window, or directly insert 250 records without classes.
List<Contact> finalList = new List<Contact>();

for(Integer i = 1; i<=250; i++){
    Contact con = new Contact();
    con.lastName = 'Test ' + i;
    finalList.add(con);
}
insert finalList;

System.debug('Inserted ' + finalList.size() + ' records.');

Batch Apex

  • My Batch Class is named batchDeleter.
global class batchDeleter implements Database.Batchable<sObject> {

    global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator('SELECT Id, LastName FROM Contact WHERE LastName LIKE \'Test%\'');
    }

    global void execute(Database.BatchableContext bc, List<sObject> deleteList){
        delete deleteList;
    }
    global void finish(Database.BatchableContext bc){
        List<Contact> con = [SELECT Id, LastName FROM Contact WHERE LastName = 'DeleteBatch' LIMIT 1];
        List<Contact> finalList = new List<Contact>();
        for (Contact iterator: con){
            iterator.Description = 'Deleted records with ID ' + bc.getJobId();
            finalList.add(iterator);
        }
        update finalList;

    }
}
  • First we return all values that have Last Name Test% where % is a wildcard.
  • In the execute method, we simply delete the entire list.
  • In the finish method, we select the 'DeleteBatch' contact and to be really sure we get only 1 value, we use Limit keyword.
  • Now we iterate over our list and update it's description to match the batch job id.
    • bc comes from the method parameter Database.BatchableContext bc and running .getJobId() returns the ID.
  • Then the values are commited to the database using the update statement.

Trigger

  • We want the Batch Class to be executed when the record is finished inserting, so writing a trigger with a helper class is the only way we can control our batch class execution.

Trigger File

trigger LastName on Contact(after insert){
    if (Trigger.isAfter){
        if (Trigger.isInsert){
            LastNameHelper.deleteContacts(trigger.new);
        }
    }
}

Tigger Helper File

public class LastNameHelper{

    public static void deleteContacts(List<Contact> newList){

        for(Contact iterator: newList){
            if (iterator.LastName == 'DeleteBatch'){
                batchDeleter runBatch = new batchDeleter();
                Database.executeBatch(runBatch);

            }
        }

    }
}
  • In our Helper Class, every time a new contact is inserted we use Trigger.new to pass all records, and in the helper class check for last name. If the last name matches our condition, we run the Batch Class.
Day 16: Advanced SOQL