Monday, 30 March 2020

Schedule Apex

What is 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.

Sample Code

This class queries for open opportunities that should have closed by the current date and creates a task on each one to remind the owner to update the opportunity.
global class RemindOpptyOwners implements Schedulable {
    global void execute(SchedulableContext ctx) {
        List<Opportunity> opptys = [SELECT Id, Name, OwnerId, CloseDate 
            FROM Opportunity 
            WHERE IsClosed = False AND 
            CloseDate < TODAY];
        // Create a task for each opportunity in the list
        TaskUtils.remindOwners(opptys);
    }
}
You can schedule your class to run either programmatically or from the Apex Scheduler UI.
Excuttion:
RemindOpptyOwners reminder = new RemindOpptyOwners();
// Seconds Minutes Hours Day_of_month Month Day_of_week optional_year
String sch = '20 30 8 10 2 ?';
String jobID = System.schedule('Remind Opp Owners', sch, reminder);
Interview quetions::
Q, How schedule a class in every 10 Min.??
System.schedule('Scheduled Job 1', '0 0 * * * ?', new scheduledTest());
System.schedule('Scheduled Job 2', '0 10 * * * ?', new scheduledTest());
System.schedule('Scheduled Job 3', '0 20 * * * ?', new scheduledTest());
System.schedule('Scheduled Job 4', '0 30 * * * ?', new scheduledTest());
System.schedule('Scheduled Job 5', '0 40 * * * ?', new scheduledTest());
System.schedule('Scheduled Job 6', '0 50 * * * ?', new scheduledTest());

Batch Apex Real time senarios

Q, Write a Batch apex class to automatically deactivate users when the user's 
      Last Login Date is greater  than 30 days.

    global class DeactivateUsers implements Database.Batchable<sObject> {
    
    global Database.QueryLocator start(Database.BatchableContext bc){
        string query = 'SELECT Name,isActive,LastLoginDate FROM User WHERE 
        LastLoginDate <     LAST_N_DAYS:30';
     return database.getQueryLocator(query);
    }
    
    global void execute(Database.BatchableContext bc, List<User> users){
        
        List<user> userlist = new List<User>();
        
        for(User u : users){
            u.IsActive = false;
            userlist.add(u);
        }
        
        update userlist;
        
    }
    
    global void finish(Database.BatchableContext bc){
        
    }

}


===========================================================================

Q, Write a Batch apex class to automatically delete the Leads whose Lead Status is 
      "Closed- Not Converted"

Explaination::

SELECT Id,Name,Status FROM Lead where Status = 'Closed - Not Converted'


DeleteLeadsNotConverted: Class must implement the global interface method: 

Iterable<SObject> start(Database.BatchableContext) 

from Database.Batchable<SObject>, 

DeleteLeadsNotConverted: Class must implement the global interface method: 

void execute(Database.BatchableContext, List<SObject>) 

from Database.Batchable<SObject>, 

DeleteLeadsNotConverted: Class must implement the global interface method: 

void finish(Database.BatchableContext) 

Coding::

global class DeleteLeadsNotConverted implements Database.Batchable<sObject> {
    
    global Database.QueryLocator start(Database.BatchableContext bc){
      string query = 'SELECT Id,Name,Status FROM Lead where Status = \'Closed - Not Converted\'';
      return database.getQueryLocator(query);
    }
    
    global void execute(Database.BatchableContext bc, List<Lead> leads){
        // Delete the Leads which are not converted.
        Delete Leads;
        // Removes the Leads from the Recycle Bin.
        database.emptyRecycleBin(leads);
    }
    
    
    global void finish(Database.BatchableContext bc) {
        
    }
   
}

==========================================================================

Q, Write a Batch Class to Update the Status of the Campaign to Completed if it is not Completed.

global class UpdateCampaignStatus implements Database.Batchable<sObject> {
    
    global Database.QueryLocator start(Database.BatchableContext bc) {
        string query = 'SELECT Id,Name,Enddate,Status FROM Campaign WHERE Enddate < TODAY';
     return database.getQueryLocator(query);
    }
    
    global void execute(Database.BatchableContext bc, List<Campaign> campaigns) {
        
        List<Campaign> camplist = new List<Campaign>();
        
        for(Campaign c :campaigns){
            // Check if the Status is not Completed
            if(c.status != 'Completed'){
                // Change the Status to Completed
                c.status = 'Completed';
                camplist.add(c);
            }
        }
        
        update camplist;   
    }
   
    global void finish(Database.BatchableContext bc) {
        
    }
}

==========================================================================

Aditional information::

Test.StartTest() and Test.StopTest() are the Test methods Which are used to test the asynchronous processes like

Batch Apex,Schedule Apex,Queueable Apex and future methods.

After the Call to the Test.stopTest() the code gets executed synchronously.


A separate set of Governor Limits are Introduced for the code in between the Test.StartTest() and Test.StopTest() Methods.

==================================================================

// Executing a Batch Class
// Create an Instance of the Batch Class
UpdateCampaignStatus obj = new UpdateCampaignStatus();
// Call the Batch
Database.executeBatch(obj,200);


Friday, 27 March 2020

Asynchronous apex (Batch Apex )

Asynchronous Apex

1) Batch Apex 2) Schedule Apex 3) Future Methods 4) Queueable Apex

Batch Apex:

Batch Apex can be used to process records step by step. In order to Implement Batch Apex an Apex Class has to implement Database.Batchable<sObject> Interface. There are 3 methods in a batch apex class: 1) Start method 2) Execute Method 3) Finish Method Start method is called at the start of the batch Apex. In Start method, we will prepare the data or query the data from database and send this to execute method. The return type of Start Method is Iterable or Database.querylocator We can Process up to 50,000 Records When the return Type is taken as 50,000. We can Process up to 50 Million Records When the return Type is taken as Database.QueryLocator. Execute method is called after the start method, it receives the list of record which can be processed as required. The return type of Execute Method is Void. Finish method is called at last after all the batch processes are finished. Finish method can be left blank if not required or can be used to send the email confirmations. The return type of Finish Method is Void. The default Batch size is 200. The minimum size of a Batch is 1. The maximum size of a Batch is 2000. Batch Apex is used for Processing Huge Amount of Data. 10 Lakh Records Batches 200 Records ------------------------------------------------------------------------------- If the Annual Revenue of an Account is more than 50 Lakhs Update those account's rating to Hot. global class UpdateAccountBatch implements Database.batchable<sObject>{ global Database.QueryLocator start(Database.BatchableContext bc) { string query = 'SELECT Id,Name,Rating,AnnualRevenue FROM Account WHERE AnnualRevenue > 5000000'; return database.getQueryLocator(query); } global void execute(Database.BatchableContext bc, List<Account> accounts){ List<Account> acclist = new List<Account>(); for(Account a: accounts){ a.rating = 'Hot'; acclist.add(a); } update acclist; } global void finish(Database.BatchableContext bc) { } } --------------------------------------------------------------------------- @isTest public class UpdateAccountBatchTest { public static testMethod void unitTest(){ // Query Used in the Batch Job string query = 'SELECT Id,Name,Rating,AnnualRevenue FROM Account WHERE AnnualRevenue > 5000000'; List<Account> accounts = new List<Account>(); // Create 200 Test Records to test the Batch Class for(Integer i = 0; i < 200 ; i++){ Account a = new Account(); a.name = 'Account' + i; a.Rating = 'Cold'; a.AnnualRevenue = 6000000; a.Phone = '09876543210'; accounts.add(a); } if(accounts != Null && accounts.size() > 0){ insert accounts; } Test.startTest(); // Create an Instance of the Batch Class UpdateAccountBatch obj = new UpdateAccountBatch(); // Call the Batch Class Database.executeBatch(obj,200); Test.stopTest(); // Verify the Results Integer i = [SELECT COUNT() FROM Account WHERE Rating = 'Hot']; system.assertEquals(200, i); } } -------------------------------------------------------------------------------------- // Create an Instance of the Batch Class UpdateAccountBatch obj = new UpdateAccountBatch(); // Call the Batch Database.executeBatch(obj,200);

========================================================================

Interview Questions::



Can we call a batch class from another batch class?
Yes, we can call one batch class from another batch class but only if it is called from its finish method.

Can we call a Future method from batch class?
no, we cannot directly call a future method from a batch class.

What is Database.Stateful used for in batch class?
As batch class runs asynchronously, to maintain the state of a variable across each batch we implement Database.Stateful.

How many can concurrent batch jobs be added to the queue?
At most, there can be 5 bath jobs queued at a time.

How can we track the status of the current running batch job?
The job Id returned by the batchable context variable helps us in finding the status of a batch through AsyncApexJob.Status.

Q . What is the purpose of start method in Batch Class?
Start object returns the list or group of records on which we are going to make changes.

What is database.getQuerylocator and what are its advantages?
It is used to fetch records from the database, if used in batch class it can fetch up to 50 millions records.
                                              
                                                                                                                                                             --Manu