function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
sebastiangnagnarellasebastiangnagnarella 

Scheduled Batch Apex class cannot access static variables or get properties changed after scheduled

Considering I have to run several different batch processes in my org and the governance limit allowing only 5 queued batch processes at a time, I took this idea and i tried to take it to the next level to avoid using a custom setting to store the current JobId. My idea was simple. In a nutshell I was going to keep the JobId for that execution inside the Apex Batch, and having the finish method using that value to abort the scheduled job

global with sharing abstract class INS_aOrchestratedBatch implements Database.Batchable<sObject> {
    
    protected final integer BATCHS_INTERVAL_MIN = 2;
    
    private List<INS_aOrchestratedBatch> batchProcessOnQueue;
    private Map<string, string> parameters;
    protected string query;
    protected string name;
    
    
    global string getName(){
        return name;
    }
    
    global Id jobId{set;get;}
    
    
    global INS_aOrchestratedBatch(List<INS_aOrchestratedBatch> abatchProcessOnQueue, Map<string, string> aparameters, string pname){
        System.debug('Building INS_aOrchestratedBatch');
        
        batchProcessOnQueue = abatchProcessOnQueue;
        parameters = aparameters;
        name = pname;
    }
    
    global virtual Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator(query);  
    }
    
    global abstract void execute(Database.BatchableContext BC, List<sObject> scope);
    
    global virtual void finish(Database.BatchableContext BC){
        sendJobStatus(BC);
        cancelPreviousJobSchedule(jobId);
        scheduleNextBatch(BATCHS_INTERVAL_MIN);
    }
    
    protected virtual string scheduleNextBatch(Integer minutesAfter){
        
        
        
        string returnJobId;
        
        if(batchProcessOnQueue.size() > 0 ){ 	
            integer nextBatchIndex = batchProcessOnQueue.size() - 1;
            INS_aOrchestratedBatch nextBatch = batchProcessOnQueue.remove(nextBatchIndex);
            
            DateTime n = datetime.now().addMinutes(minutesAfter);
            String cron = '';
            
            cron += n.second();
            cron += ' ' + n.minute();
            cron += ' ' + n.hour();
            cron += ' ' + n.day();
            cron += ' ' + n.month();
            cron += ' ' + '?';
            cron += ' ' + n.year();
            
            INS_OrchestratedBatchScheduler scheduler = new INS_OrchestratedBatchScheduler(nextBatch);
            
            
            
            returnJobId = System.schedule('Notification Batch - ' + nextBatch.Name , cron, scheduler);
            system.debug('scheduleNextBatch --------->'  + returnJobId);
            //We setup the jobId on the same class so it cancel itself at the end
            nextBatch.jobId = returnJobId;
        }
        
        return returnJobId;
        
    }
    
    private virtual void cancelPreviousJobSchedule(Id jobId){
        if(jobId != null){
		System.abortJob(jobId);
        }
    }
    

}

 

 

 

You will find out that that I am using a list of chained process and  also a wrapper to schedule, but that doesn't make any difference to understand the problem. The interesting part is in this line :

 

            returnJobId = System.schedule('Notification Batch - ' + nextBatch.Name , cron, scheduler);
            system.debug('scheduleNextBatch --------->'  + returnJobId);
            //We setup the jobId on the same class so it cancel itself at the end
            nextBatch.jobId = returnJobId;

 Where I schedulle the job and then I tried to setup a properly so it can auto abort the job in the finish.

However when the class hits the finish, the jobId property is null, My idea here is that when salesforce queues the class in the scheduller, the instance is copied somewhere else and you cannot modify the values of what is already queued. i also tried with a static variable with the same results.

I ended up just queryng the CronDetails (only available in W'14)  together with the  CronTrigger object, to get the job Id based on my Schedule name.

 

Any ideas about this behavior of schedulled classes? I am curious how it works as it is not documented.

 

Thanks