Scheduled Batch Apex class - Answers - Salesforce Trailblazer Community
Trailblazer Community
Ask Search:
Srinivasa Sarma RayapuriSrinivasa Sarma Rayapuri 

Scheduled Batch Apex class

I need to write a Scheduled Batch Apex Class on two Obhects Case and Ticket__c. 

Note: Ticket__c Has a look up to the Case. So, a case can have multiple tickets but a ticket can only be associated to one case.

what the Scheduled Batch Class should do
****** Run the batch apex at 2:00am every Morning
1. Get all the records of  a case whose status is Open, Breached and Escalated.
2. List all the tickets whose Id = Case.Id
3. Loop through to validate the Ticket_c status (GLOBAL_Ticket_Status__c=Closed)  // if not come out of the loop
4. Add the tickets id to case id and close the case after 7 days of Highest LastModifiesDate of a ticket associated to case i.e Ticket__c (Status=close) and Highster Lastmodified > 7 close the case. 

global class CloseCaseBatch implements Database.Batchable<sObject> {
  global String query;
    global Database.QueryLocator start(Database.BatchableContext BC)
        query = 'Select Id,  from Case WHERE Status = \'Open\' And ' +
                                       'Status = \'Escalated\' And' +
                                       'Status = \'Breached\''; //need to define query
        System.debug('checkcase---' + query);

        return Database.getQueryLocator(query);


   global void execute(Database.BatchableContext BC, List<sObject> scope)

      List<Case> scase= (List<Case>)scope; // ? scope is case
      System.debug('checkcase---' +scope);
      Set<ID> caseIDs = new Set<ID>();
      Map<ID,List<Ticket__c>> CaseID_TicketList = new Map<ID,List<Ticket__c>>();
      for(case cI : scase)

      // Need to setup caseID set ??
   for (Ticket__c ticket : [Select ID, LastModifiedDate , GLOBAL_Ticket_Status__c,GLOBAL_Goal__c from Ticket__c where GLOBAL_Goal__c in :caseIDs]){
        /*List<Ticket__c> tkList = new List<Ticket__c>();
            tkList = CaseID_TicketList.get(ticket.GLOBAL_Goal__c);

        else {
        // Map case & ticket

   Boolean allClosedTickets = true;
    // Loop thru Map on Case for all associated tickets
      //for (caseID map loop)
      allClosedTickets = true;
      for (Ticket__c ticket: scase) { // Ticket loop
        System.debug('checkcase---' +ticket);
          // save LastModified date of the highest date
          if (ticket.GLOBAL_Ticket_Status__c != 'closed') {
              allClosedTickets = false;
              //caseIDs.add(ticket.GLOBAL_Goal__c);   // case ID of current Records.
      if (allClosedTickets = true) { // all closed so Case can be closed
          // if lastModifiedDate greater than 7 days then
            // add CaseId to casesToUpdate

    List<Case> casesToUpdate = new List<Case>();

    for (Id caseID : caseIDs) {

        Integer totalTickets = CaseID_TicketList.get(caseID).size();
        Integer closedTickets = 0;
        for(Ticket__c ticket : CaseID_TicketList.get(caseID)){
            if(ticket.GLOBAL_Ticket_Status__c == 'Closed'){
        if(closedTickets == totalTickets) {
            casesToUpdate.add(new Case(Id = caseID, Status= 'Closed'));

    if(!casesToUpdate.isEmpty()) {
        update casesToUpdate;

   global void finish(Database.BatchableContext BC)

Can anyone help me out please. 

Sachin DasSachin Das

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 at the scheduled time. 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 variables or data across job transactions. Otherwise, all instance 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.
You cannot call the Database.executeBatch method from within any batch Apex method.
You cannot use the getContent and getContentAsPDF PageReference methods in a batch job.
In the event of a catastrophic failure such as a service outage, any operations in progress are marked as Failed. You should run the batch job again to correct any errors.
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 Web Services API Developer's Guide.
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 Web Services API Developer's Guide.
All methods in the class must be defined as global.
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.
Sachin DasSachin Das
Batch Apex Governor Limits
Keep in mind the following governor limits for batch Apex:
Up to five queued or active batch jobs are allowed for Apex.
A user can have up to five query cursors open at a time. For example, if five cursors are open and a client application still logged in as the same user attempts to open a new one, the oldest of the five cursors is released.
Cursor limits for different features are tracked separately. For example, you can have five Apex query cursors, five batch cursors, and five Visualforce cursors open at the same time.
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.
The maximum value for the optional scope parameter is 400. If set to a higher value, Salesforce chunks the records returned by the QueryLocator into smaller batches of 400.
If no size is specified with the optional scope parameter, Salesforce chunks the records returned by the QueryLocator 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 only one callout in each method.
Batch executions are limited to one callout per execution.
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.
Sachin DasSachin Das

Srinivasa Sarma RayapuriSrinivasa Sarma Rayapuri
Thanks for the reply sachin das. can you help me with making changes in my code. 

And Batch apex is not invoking any trigger. 
Kalloori RameshKalloori Ramesh
Hi Srinivas,

Create the class that implements Schedulabe interface.

global class LocationCalloutsSchedule implements Schedulable {
global void execute(SchedulableContext ctx) {  
  //Call the BatchApex Here
  CloseCaseBatch CloseObj=new CloseCaseBatch();

And next is schedule the above schedular class.

GOto>>ApexClasses>>Clickon Schedule Apex>>Select the class as(LocationCalloutsSchedule)>> Select the Time and date to run the schedule.


Josep Vall-lloveraJosep Vall-llovera
Hello Srinivas,

You may also be interested in using some templates to schedule a batch job. I've written a couple of them some time ago:


Kathleen JonesKathleen Jones
Hi Srinivasa,
You might go through these articles as well to get a good idea about Batch Apex. Might help you.