Sunday, November 18, 2012

Batch Classes in Salesforce

This post related to batch covers following points mentioned below:--
     
  •          Introduction to Batch Apex
  •          How to delete contact records through batch
  •          How to execute a batch through custom button
  •          How to get status of Errors
  •          How to get success and error count for records 
  •          How to send user a Email having success and error count

Introduction to Batch Apex:--

A developer can now employ batch Apex to build complex, long-running processes
on the Force.com platform. For example, a developer could build an archiving:--

Using Batch Apex solution that runs on a nightly basis, looking for records past a certain date and
understanding Apex Managed Sharing adding them to an archive. Or a developer could build a data cleansing operation that goes through all Accounts and Opportunities on a nightly basis and reassigns
them if necessary, based on custom criteria.

Batch Apex is exposed as an interface that must be implemented by the developer. Batch jobs can be programmatically invoked at runtime using Apex.

You can only have five queued or active batch jobs at one time. You can evaluate your current count by viewing the Scheduled Jobs page in Salesforce or programmatically using the Force.com Web services API to query the AsyncApexJob object.

To use batch Apex, you must write an Apex class that implements the Salesforce-provided interface Database.Batchable and then invoke the class programmatically.

Implementing the Database.Batchable Interface

The Database.Batchable interface contains three methods that must be implemented:

• start method

global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {}

The start method is called at the beginning of a batch Apex job. Use the start method to collect the records or objects to be passed to the interface method execute. This method returns either a Database.QueryLocator object or an iterable that contains the records or objects being passed into the job.

• execute method:

global void execute(Database.BatchableContext BC, list<P>) {}

The execute method is called for each batch of records passed to the method. Use this method to do all required processing for each chunk of data.

• finish method

global void finish(Database.BatchableContext BC){}

The finish method is called after all batches are processed. Use this method to send confirmation emails or execute post-processing operations.


How to delete Contact records using Batch:---


/*
* Description   : This is Batch to Perform delete operation on Contact Records.
* 
* Created By    : Abhinav Sharma
*
* Created Date  : 11/18/2012
*
* Version       : v1.0 - Create 
*/
//Batch Class
global class Batch_DeleteContact implements Database.Batchable<sObject>,Database.stateful {
  
  //Variable to count Success and Error Records
    public Integer successCounter = 0;
    public Integer failureCounter = 0; 
         
    //Start Method 
    global Database.QueryLocator start(Database.BatchableContext BC) { 
    
        //Query to Fetch Records
        return Database.getQueryLocator([SELECT ID FROM Contact]);
   
    }
    
    //Execute Method
    global void  execute(Database.BatchableContext BC, List<Contact> scope) {
      
    //Delete the Records those are in Contexts
        Database.DeleteResult[] delresults = Database.delete((scope),false);
        
        //Loop through records giong to be deleted
        for(Database.DeleteResult dr : delResults){
        
            //If record is not successfully deleted
            if(!dr.isSuccess()){
            
                //List to hold Error
                Database.Error[] errs = dr.getErrors();
                
                //Loop through list of Error
                for(Database.Error err : errs) {
                    
                    //Debug to get Error Status
                    System.debug('$#$#$#$' + err.getStatusCode() + ' - ' + err.getMessage());
                    
                    //Debug to get Error Message
                    System.debug('ErrorMessage##########'+ err.getMessage());
                }
                
                //Increase counter for Failure
                 failureCounter++;
            }
            
            else {
            
                successCounter++;
            }
        }      
    }
    
    //Finish Method
    global void finish(Database.BatchableContext BC){
      
      // Query the AsyncApexJob object to retrieve the current job's information.
        AsyncApexJob a = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed,
        TotalJobItems, CreatedBy.Email
        FROM AsyncApexJob WHERE Id = :BC.getJobId()];
        
        // Send an email to the Apex job's submitter notifying of job completion.
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        String[] toAddresses = new String[] {a.CreatedBy.Email};
        mail.setToAddresses(toAddresses);
        mail.setSubject('Apex Job ' + a.Status);
        mail.setPlainTextBody
        ('Apex job has been completed.There were total' + a.TotalJobItems 
              + ' batches with ' + successCounter + ' success and ' + failureCounter
              + 'failures.');
        Messaging.sendEmail(new Messaging.SingleEmailMessage[]{mail});
    }
}

Apex class which is further call by Custom List Button for execution of Batch :---


global with sharing class Batch_ExectionController {
//This method is to get the view mode  
webservice static ID executeBatchForDeletionOfContact() {            
Id batchProcessId;                
//Calling Constructor for Batch Execution      
Batch_DeletePropertyOpportunities dc = new Batch_DeletePropertyOpportunities();  
batchProcessId = Database.executeBatch(dc);        
System.debug('Returned batch process ID:@@@@@@@@@@@@@@@@@@ ' + batchProcessId);          return batchProcessId;  
}
}
Custom List Button Code:-- (Location:-- List view Page - Contact) {!REQUIRESCRIPT("/soap/ajax/10.0/connection.js")} {!REQUIRESCRIPT("/soap/ajax/10.0/apex.js")}
//Calling Class and Method var contextUser = sforce.apex.execute("Batch_ExectionController", "executeBatchForDeletionOfContact", {});
window.alert('Now Please check Debug logs');
Once user click on list button it ultimate call that class which have execution code for batch and as a result of this once batch completed successfully all max possible contacts get deleted and an email will be there on user mail box having success and error count. Governor limits always play an important role in case of Batch Apex therefore always keep these limits in mind.
Enjoy Coding.....