Using Batch Apex

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

To monitor or stop the execution of the batch Apex job, from Setup, click Monitoring | Apex Jobs or Jobs | Apex Jobs.

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.

    Use the Database.QueryLocator object when you are using a simple query (SELECT) to generate the scope of objects used in the batch job. If you use a querylocator object, the governor limit for the total number of records retrieved by SOQL queries is bypassed. For example, a batch Apex job for the Account object can return a QueryLocator for all account records (up to 50 million records) in an organization. Another example is a sharing recalculation for the Contact object that returns a QueryLocator for all account records in an organization.

    Use the iterable when you need to create a complex scope for the batch job. You can also use the iterable to create your own custom process for iterating through the list.
    Important
    If you use an iterable, the governor limit for the total number of records retrieved by SOQL queries is still enforced.
  • 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.

    This method takes the following:
    • A reference to the Database.BatchableContext object.
    • A list of sObjects, such as List<sObject>, or a list of parameterized types. If you are using a Database.QueryLocator, the returned list should be used.

    Batches of records execute in the order they are received from the start method.

  • 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.

Each execution of a batch Apex job is considered a discrete transaction. For example, a batch Apex job that contains 1,000 records and is executed without the optional scope parameter from Database.executeBatch is considered five transactions of 200 records each. The Apex governor limits are reset for each transaction. If the first transaction succeeds but the second fails, the database updates made in the first transaction are not rolled back.

Using Database.BatchableContext

All of the methods in the Database.Batchable interface require a reference to a Database.BatchableContext object. Use this object to track the progress of the batch job.

The following is the instance method with the Database.BatchableContext object:
NameArgumentsReturnsDescription
getJobIDIDReturns the ID of the AsyncApexJob object associated with this batch job as a string. Use this method to track the progress of records in the batch job. You can also use this ID with the System.abortJob method.

The following example uses the Database.BatchableContext to query the AsyncApexJob associated with the batch job.

global void finish(Database.BatchableContext BC){
   // Get the ID of the AsyncApexJob representing this batch job
   // from Database.BatchableContext.
   // 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 Sharing Recalculation ' + a.Status); mail.setPlainTextBody ('The batch Apex job processed ' + a.TotalJobItems + ' batches with '+ a.NumberOfErrors + ' failures.'); Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail }); }

Using Database.QueryLocator to Define Scope

The start method can return either a Database.QueryLocator object that contains the records to be used in the batch job or an iterable.

The following example uses a Database.QueryLocator:
global class SearchAndReplace implements Database.Batchable<sObject>{

   global final String Query;
   global final String Entity;
   global final String Field;
   global final String Value;

   global SearchAndReplace(String q, String e, String f, String v){

      Query=q; Entity=e; Field=f;Value=v;
   }

   global Database.QueryLocator start(Database.BatchableContext BC){
      return Database.getQueryLocator(query);
   }

   global void execute(Database.BatchableContext BC, List<sObject> scope){
     for(sobject s : scope){
     s.put(Field,Value); 
     }
     update scope;
    }

   global void finish(Database.BatchableContext BC){
   }
}

Using an Iterable in Batch Apex to Define Scope

The start method can return either a Database.QueryLocator object that contains the records to be used in the batch job, or an iterable. Use an iterable to step through the returned items more easily.

global class batchClass implements Database.batchable{ 
   global Iterable start(Database.BatchableContext info){ 
       return new CustomAccountIterable(); 
   }     
   global void execute(Database.BatchableContext info, List<Account> scope){
       List<Account> accsToUpdate = new List<Account>();
       for(Account a : scope){ 
           a.Name = 'true'; 
           a.NumberOfEmployees = 70; 
           accsToUpdate.add(a); 
       } 
       update accsToUpdate; 
   }     
   global void finish(Database.BatchableContext info){     
   } 
}

Using the Database.executeBatch Method to Submit Batch Jobs

You can use the Database.executeBatch method to programmatically begin a batch job.
Important
When you call Database.executeBatch, Salesforce only adds the process to the queue. Actual execution may be delayed based on service availability.
The Database.executeBatch method takes two parameters:
  • An instance of a class that implements the Database.Batchable interface.
  • The Database.executeBatch method takes an optional parameter scope. This parameter specifies the number of records that should be passed into the execute method. Use this parameter when you have many operations for each record being passed in and are running into governor limits. By limiting the number of records, you are thereby limiting the operations per transaction. This value must be greater than zero. If the start method of the batch class 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 of the batch class 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.
The outcome of Database.executeBatch is as follows:
  • If the limit of five queued or active batch job hasn’t been reached, the batch job is queued for execution and its status is Queued.
  • If the batch job limit has been reached, Database.executeBatch throws a LimitException and doesn’t add the job to the queue.
The Database.executeBatch method returns the ID of the AsyncApexJob object, which can then be used to track the progress of the job. For example:
ID batchprocessid = Database.executeBatch(reassign);

AsyncApexJob aaj = [SELECT Id, Status, JobItemsProcessed, TotalJobItems, NumberOfErrors 
                    FROM AsyncApexJob WHERE ID =: batchprocessid ];

You can also use this ID with the System.abortJob method.

For more information about the AsyncApexJob object, see AsyncApexJob in the Object Reference for Salesforce and Force.com.

Running Batch Jobs with Apex Flex Queue (Pilot)

Note
This feature is currently available to select customers through a pilot program. To be nominated to join this pilot program, contact Salesforce. Additional terms and conditions may apply to participate in the pilot program. Please note that pilot programs are subject to change, and as such, we cannot guarantee acceptance into this pilot program or a particular time frame that this feature can be enabled. Any unreleased services or features referenced in this or other press releases or public statements are not currently available and may not be delivered on time or at all. Customers who purchase our services should make their purchase decisions based upon features that are currently available.

Holding Batch Jobs in the Queue

If Apex Flex Queue is enabled in your organization, you can submit up to 100 batch jobs without getting an error.

The outcome of Database.executeBatch is as follows:
  • The batch job is placed in the Apex flex queue and its status is set to Holding as long as the number of jobs in the flex queue hasn’t reached the maximum of 100.
  • If the Apex flex queue has the maximum number of jobs, Database.executeBatch throws a LimitException and doesn’t add the job to the queue.

Reordering Jobs in the Apex Flex Queue

While submitted jobs have a status of Holding, you can reorder them in the Salesforce user interface. To do so, from Setup, click Jobs | Apex Flex Queue.

Without administrator intervention, jobs are processed first-in first-out—in the order in which they’re submitted. Administrators can modify the order of jobs that are held in the Apex flex queue to control when they get processed by the system. For example, you can move a batch job up to the first position in the holding queue so that it’s the first job that gets processed when the system fetches the next held job from the flex queue.

When system resources become available, the system picks up the next job from the top of the Apex flex queue and moves it to the batch job queue. The status of these moved jobs changes from Holding to Queued. Queued jobs get executed when the system is ready to process new jobs. You can monitor queued jobs in the Apex Jobs page.

Batch Job Statuses

The following table lists all possible statuses for a batch job along with a description of each.

Status Description
Holding 1 Job has been submitted and is held until system resources are freed up.
Queued Job is awaiting execution.
Preparing The start method of the job has been invoked. This status might last a few minutes depending on the size of the batch of records.
Processing Job is being processed.
Aborted Job was aborted by a user.
Completed Job completed with or without failures.
Failed Job experienced a system failure.

Using the System.scheduleBatch Method

You can use the System.scheduleBatch method to schedule a batch job to run once at a future time.

The System.scheduleBatch method takes the following parameters.
  • An instance of a class that implements the Database.Batchable interface.
  • The job name.
  • The time interval, in minutes, after which the job should start executing.
  • An optional scope value. This parameter specifies the number of records that should be passed into the execute method. Use this parameter when you have many operations for each record being passed in and are running into governor limits. By limiting the number of records, you are thereby limiting the operations per transaction. This value must be greater than zero. If the start method returns a QueryLocator, the optional scope parameter of System.scheduleBatch 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.

The System.scheduleBatch method returns the scheduled job ID (CronTrigger ID).

This example schedules a batch job to run one minute from now by calling System.scheduleBatch. The example passes this method an instance of a batch class (the reassign variable), a job name, and a time interval of one minute. The optional scope parameter has been omitted. The method call returns the scheduled job ID, which is used to query CronTrigger to get the status of the corresponding scheduled job.
String cronID = System.scheduleBatch(reassign, 'job example', 1);

CronTrigger ct = [SELECT Id, TimesTriggered, NextFireTime
                FROM CronTrigger WHERE Id = :cronID];

// TimesTriggered should be 0 because the job hasn't started yet.
System.assertEquals(0, ct.TimesTriggered);
System.debug('Next fire time: ' + ct.NextFireTime); 
// For example:
// Next fire time: 2013-06-03 13:31:23

For more information about CronTrigger, see CronTrigger in the Object Reference for Salesforce and Force.com.

Note
Some things to note about System.scheduleBatch:
  • When you call System.scheduleBatch, Salesforce schedules the job for execution at the specified time. Actual execution might be delayed based on service availability.
  • The scheduler runs as system—all classes are executed, whether or not the user has permission to execute the class.
  • All scheduled Apex limits apply for batch jobs scheduled using System.scheduleBatch. After the batch job starts executing, all batch job limits apply and the job no longer counts toward scheduled Apex limits.
  • After calling this method and before the batch job starts, you can use the returned scheduled job ID to abort the scheduled job using the System.abortJob method.

Batch Apex Examples

The following example uses a Database.QueryLocator:
global class UpdateAccountFields implements Database.Batchable<sObject>{
   global final String Query;
   global final String Entity;
   global final String Field;
   global final String Value;

   global UpdateAccountFields(String q, String e, String f, String v){
             Query=q; Entity=e; Field=f;Value=v;
   }

   global Database.QueryLocator start(Database.BatchableContext BC){
      return Database.getQueryLocator(query);
   }

   global void execute(Database.BatchableContext BC, 
                       List<sObject> scope){
      for(Sobject s : scope){s.put(Field,Value); 
      }      update scope;
   }

   global void finish(Database.BatchableContext BC){

   }

}
The following code can be used to call the above class:
// Query for 10 accounts
String q = 'SELECT Industry FROM Account LIMIT 10'; String e = 'Account'; String f = 'Industry'; String v = 'Consulting'; Id batchInstanceId = Database.executeBatch(new UpdateAccountFields(q,e,f,v), 5);
To exclude accounts that were deleted and that are still in the Recycle Bin, append isDeleted=false in the SOQL query WHERE clause as shown in the query in this modified sample.
// Query for accounts that aren't in the Recycle Bin
String q = 'SELECT Industry FROM Account WHERE isDeleted=false LIMIT 10'; String e = 'Account'; String f = 'Industry'; String v = 'Consulting'; Id batchInstanceId = Database.executeBatch(new UpdateAccountFields(q,e,f,v), 5);
To exclude invoices that were deleted and that are still in the Recycle Bin, append isDeleted=false in the SOQL query WHERE clause as shown in the query in this modified sample.
// Query for invoices that aren't in the Recycle Bin
String q = 'SELECT Description__c FROM Invoice_Statement__c WHERE isDeleted=false LIMIT 10'; String e = 'Invoice_Statement__c'; String f = 'Description__c'; String v = 'Updated description'; Id batchInstanceId = Database.executeBatch(new UpdateInvoiceFields(q,e,f,v), 5);
The following class uses batch Apex to reassign all accounts owned by a specific user to a different user.
global class OwnerReassignment implements Database.Batchable<sObject>{
String query;
String email;
Id toUserId;
Id fromUserId;

global Database.querylocator start(Database.BatchableContext BC){
            return Database.getQueryLocator(query);}

global void execute(Database.BatchableContext BC, List<sObject> scope){
    List<Account> accns = new List<Account>();

   for(sObject s : scope){Account a = (Account)s;
        if(a.OwnerId==fromUserId){
            a.OwnerId=toUserId;
            accns.add(a);
            }
        }

update accns;
    
}
global void finish(Database.BatchableContext BC){
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();

mail.setToAddresses(new String[] {email});
mail.setReplyTo('batch@acme.com');
mail.setSenderDisplayName('Batch Processing');
mail.setSubject('Batch Process Completed');
mail.setPlainTextBody('Batch Process has completed');

Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
}
}
Use the following to execute the OwnerReassignment class in the previous example:
OwnerReassignment reassign = new OwnerReassignment();
reassign.query = 'SELECT Id, Name, Ownerid FROM Account ' + 
                'WHERE ownerid=\'' + u.id + '\'';
reassign.email='admin@acme.com';
reassign.fromUserId = u;
reassign.toUserId = u2;
ID batchprocessid = Database.executeBatch(reassign);
The following is an example of a batch Apex class for deleting records.
global class BatchDelete implements Database.Batchable<sObject> {
   public String query;

   global Database.QueryLocator start(Database.BatchableContext BC){
      return Database.getQueryLocator(query);
   }

   global void execute(Database.BatchableContext BC, List<sObject> scope){
      delete scope;
      DataBase.emptyRecycleBin(scope);
   }

   global void finish(Database.BatchableContext BC){
   }
}
This code calls the BatchDelete batch Apex class to delete old documents. The specified query selects documents to delete for all documents that are in a specified folder and that are older than a specified date. Next, the sample invokes the batch job.
BatchDelete BDel = new BatchDelete();
Datetime d = Datetime.now();
d = d.addDays(-1);
// Replace this value with the folder ID that contains
// the documents to delete.
String folderId = '00lD000000116lD'; // Query for selecting the documents to delete BDel.query = 'SELECT Id FROM Document WHERE FolderId=\'' + folderId + '\' AND CreatedDate < '+d.format('yyyy-MM-dd')+'T'+ d.format('HH:mm')+':00.000Z'; // Invoke the batch job.
ID batchprocessid = Database.executeBatch(BDel); System.debug('Returned batch process ID: ' + batchProcessId);

Using Callouts in Batch Apex

To use a callout in batch Apex, you must specify Database.AllowsCallouts in the class definition. For example:
global class SearchAndReplace implements Database.Batchable<sObject>, 
   Database.AllowsCallouts{
}

Callouts include HTTP requests as well as methods defined with the webService keyword.

Using State in Batch Apex

Each execution of a batch Apex job is considered a discrete transaction. For example, a batch Apex job that contains 1,000 records and is executed without the optional scope parameter is considered five transactions of 200 records each.

If you specify Database.Stateful in the class definition, you can maintain state across these transactions. When using Database.Stateful, only instance member variables retain their values between transactions. Static member variables don’t and are reset between transactions. Maintaining state is useful for counting or summarizing records as they're processed. For example, suppose your job processed opportunity records. You could define a method in execute to aggregate totals of the opportunity amounts as they were processed.

If you don't specify Database.Stateful, all static and instance member variables are set back to their original values.

The following example summarizes a custom field total__c as the records are processed:
global class SummarizeAccountTotal implements 
    Database.Batchable<sObject>, Database.Stateful{

   global final String Query;
   global integer Summary;
  
   global SummarizeAccountTotal(String q){Query=q;
     Summary = 0;
   }

   global Database.QueryLocator start(Database.BatchableContext BC){
      return Database.getQueryLocator(query);
   }
   
   global void execute(
                Database.BatchableContext BC, 
                List<sObject> scope){
      for(sObject s : scope){
         Summary = Integer.valueOf(s.get('total__c'))+Summary;
      }
   }

global void finish(Database.BatchableContext BC){
   }
}
In addition, you can specify a variable to access the initial state of the class. You can use this variable to share the initial state with all instances of the Database.Batchable methods. For example:
// Implement the interface using a list of Account sObjects
// Note that the initialState variable is declared as final

global class MyBatchable implements Database.Batchable<sObject> { private final String initialState; String query; global MyBatchable(String intialState) { this.initialState = initialState; } global Database.QueryLocator start(Database.BatchableContext BC) { // Access initialState here
    
    return Database.getQueryLocator(query); } global void execute(Database.BatchableContext BC, List<sObject> batch) { // Access initialState here } global void finish(Database.BatchableContext BC) { // Access initialState here } }

Note that initialState is the initial state of the class. You cannot use it to pass information between instances of the class during execution of the batch job. For example, if you changed the value of initialState in execute, the second chunk of processed records would not be able to access the new value: only the initial value would be accessible.

Testing Batch Apex

When testing your batch Apex, you can test only one execution of the execute method. You can use the scope parameter of the executeBatch method to limit the number of records passed into the execute method to ensure that you aren't running into governor limits.

The executeBatch method starts an asynchronous process. This means that when you test batch Apex, you must make certain that the batch job is finished before testing against the results. Use the Test methods startTest and stopTest around the executeBatch 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 executeBatch method within the startTest and stopTest methods, the batch job executes at the end of your test method for Apex saved using Salesforce API version 25.0 and later, but not in earlier versions.

Starting with Apex saved using Salesforce API version 22.0, exceptions that occur during the execution of a batch Apex job that is invoked by a test method are now passed to the calling test method, and as a result, causes the test method to fail. If you want to handle exceptions in the test method, enclose the code in try and catch statements. You must place the catch block after the stopTest method. Note however that with Apex saved using Salesforce API version 21.0 and earlier, such exceptions don't get passed to the test method and don't cause test methods to fail.
Note
Asynchronous calls, such as @future or executeBatch, called in a startTest, stopTest block, do not count against your limits for the number of queued jobs.
The example below tests the OwnerReassignment class.
public static testMethod void testBatch() {
   user u = [SELECT ID, UserName FROM User 
             WHERE username='testuser1@acme.com'];
   user u2 = [SELECT ID, UserName FROM User 
              WHERE username='testuser2@acme.com'];
   String u2id = u2.id;
// Create 200 test accounts - this simulates one execute.  
// Important - the Salesforce.com test framework only allows you to
// test one execute. List <Account> accns = new List<Account>(); for(integer i = 0; i<200; i++){ Account a = new Account(Name='testAccount'+'i', Ownerid = u.ID); accns.add(a); } insert accns; Test.StartTest(); OwnerReassignment reassign = new OwnerReassignment(); reassign.query='SELECT ID, Name, Ownerid ' + 'FROM Account ' + 'WHERE OwnerId=\'' + u.Id + '\'' + ' LIMIT 200'; reassign.email='admin@acme.com'; reassign.fromUserId = u.Id; reassign.toUserId = u2.Id; ID batchprocessid = Database.executeBatch(reassign); Test.StopTest(); System.AssertEquals( database.countquery('SELECT COUNT()' +' FROM Account WHERE OwnerId=\'' + u2.Id + '\''), 200); } }

Batch Apex Governor Limits

Keep in mind the following governor limits for batch Apex:
  • Up to 5 batch jobs can be queued or active.
  • In a running test, you can submit a maximum of 5 batch jobs.
  • The maximum number of batch Apex method executions per a 24-hour period is 250,000 or the number of user licenses in your organization multiplied by 200, whichever is greater. Method executions include executions of the start, execute, and finish methods. This is an organization-wide limit and is shared with all other asynchronous Apex: scheduled Apex, future methods, and queueable Apex. The licenses that count toward this limit are full Salesforce user licenses or Force.com App Subscription user licenses. Chatter Free, Chatter customer users, Customer Portal User, and partner portal User licenses aren’t included.
  • The batch Apexstart method can have up to 15 query cursors open at a time per user. The batch Apex execute and finish methods each have a different limit of 5 open query cursors per user.
  • A maximum of 50 million records can be returned in the Database.QueryLocator object. If more than 50 million records are returned, the batch job is immediately terminated and marked as Failed.
  • If the start method of the batch class 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 of the batch class 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.
  • 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.

Batch Apex Best Practices

  • Use extreme care if you are planning to invoke a batch job from a trigger. You must be able to guarantee that the trigger will not add more batch jobs than the five that are allowed. In particular, consider API bulk updates, import wizards, mass record changes through the user interface, and all cases where more than one record can be updated at a time.
  • When you call Database.executeBatch, Salesforce only places the job in the queue. Actual execution may be delayed based on service availability.
  • When testing your batch Apex, you can test only one execution of the execute method. You can use the scope parameter of the executeBatch method to limit the number of records passed into the execute method to ensure that you aren't running into governor limits.
  • The executeBatch method starts an asynchronous process. This means that when you test batch Apex, you must make certain that the batch job is finished before testing against the results. Use the Test methods startTest and stopTest around the executeBatch method to ensure it finishes before continuing your test.
  • Use Database.Stateful with the class definition if you want to share instance member variables or data across job transactions. Otherwise, all member variables are reset to their initial state at the start of each transaction.
  • Methods declared as future aren't allowed in classes that implement the Database.Batchable interface.
  • Methods declared as future can't be called from a batch Apex class.
  • Starting with Apex saved using Salesforce API version 26.0, you can call Database.executeBatch or System.scheduleBatch from the finish method. This enables you to start or schedule a new batch job when the current batch job finishes. For previous versions, you can’t call Database.executeBatch or System.scheduleBatch from any batch Apex method. Note that the version used is the version of the running batch class that starts or schedules another batch job. If the finish method in the running batch class calls a method in a helper class to start the batch job, the Salesforce API version of the helper class doesn’t matter.
  • You cannot use the getContent and getContentAsPDF PageReference methods in a batch job.
  • When a batch Apex job is run, email notifications are sent either to the user who submitted the batch job, or, if the code is included in a managed package and the subscribing organization is running the batch job, the email is sent to the recipient listed in the Apex Exception Notification Recipient field.
  • Each method execution uses the standard governor limits anonymous block, Visualforce controller, or WSDL method.
  • Each batch Apex invocation creates an AsyncApexJob record. Use the ID of this record to construct a SOQL query to retrieve the job’s status, number of errors, progress, and submitter. For more information about the AsyncApexJob object, see AsyncApexJob in the Object Reference for Salesforce and Force.com.
  • For each 10,000 AsyncApexJob records, Apex creates one additional AsyncApexJob record of type BatchApexWorker for internal use. When querying for all AsyncApexJob records, we recommend that you filter out records of type BatchApexWorker using the JobType field. Otherwise, the query will return one more record for every 10,000 AsyncApexJob records. For more information about the AsyncApexJob object, see AsyncApexJob in the Object Reference for Salesforce and Force.com.
  • All methods in the class must be defined as global or public.
  • For a sharing recalculation, we recommend that the execute method delete and then re-create all Apex managed sharing for the records in the batch. This ensures the sharing is accurate and complete.
  • Batch jobs queued before a Salesforce service maintenance downtime remain in the queue. After service downtime ends and when system resources become available, the queued batch jobs are executed. If a batch job was running when downtime occurred, the batch execution is rolled back and restarted after the service comes back up.
1 This status value is part of the Apex Flex Queue pilot.
© Copyright 2000–2014 salesforce.com, inc. All rights reserved.
Various trademarks held by their respective owners.