Use a single scheduled job to run multiple batch class dynamically

It’s very typical to run batch jobs using scheduled job in each org. I’ve seen developers to develop different scheduled job for each batch class which cost not only extra redundant code but also lot of overhead of complexity and test code liability. So, I just developed a way to use a single scheduled jobs to run as many batch jobs/classes you want.

Here is service scheduled Class:

public with sharing class DynamicBatchJobScheduler implements Schedulable{
    public String CLASSNAME;
    public Integer BATCHSIZE;
    public String QUERY;
    public DynamicBatchJobScheduler(String batchClassName, Integer count, String q){
        CLASSNAME = batchClassName;
        BATCHSIZE = count;
        QUERY = q;
    }
    public void execute(SchedulableContext sc) { 
        //PASS QUERY FROM SHEDULER CONSTRUCTOR .. TBD BY DHIREN
        String batchParameters = '{"query": "'+QUERY+'"}';
        Database.Batchable<SObject> b = (Database.Batchable<SObject>) JSON.deserialize(batchParameters, Type.forName(CLASSNAME));
        Database.executeBatch(b, BATCHSIZE);
   }

}

Here is one sample batch class’s example that deletes specified records at scheduled time:

global Class DynamicBatchClass implements Database.Batchable<SObject>{
    
    global String query;
    global String queryString;
    global String objectName;
    global String status;
    global DynamicBatchClass(string queryString1, string objectName1, string status1){
        queryString = queryString1  ;
        objectName= objectName1;
        status = status1;
    }
    
    global DynamicBatchClass(){
        
    }
    
    global Database.QueryLocator start(Database.BatchableContext BC){
        if(Test.isRunningTest()==true) query = 'SELECT id FROM Case LIMIT 4';
        system.debug('query ==='+query);
        return Database.getQueryLocator(query);
    }
    
    global void execute(Database.BatchableContext BC, List<sobject> scope){
        system.debug(query+'__'+queryString);
        String objectType = '';
        //System.debug('scope-before-'+scope);
        if(scope <> null &&  scope.size() > 0){
            if(scope[0]!=null){
                objectType =  String.valueOf(scope[0].getSObjectType()); // Getting Object type
            }
            if(objectType!='' && objectType=='Case'){
               // do something
            }else{
               //do something
            }
            //System.debug('scope-after-'+scope);
            delete scope ;// MAKE OPERATION DYNAMIC
        }
    }
    
    global void finish(Database.BatchableContext BC){
        List<Messaging.SingleEmailMessage> mails = new List<Messaging.SingleEmailMessage>();
       
        Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
        message.setSubject('Batch Finished');
        message.setPlainTextBody('Batch..');
        //current user Id ...
        String currentuser = UserInfo.getUserId(); 
        //adding other email ids...
        String[] emailRecipients = new List<String>{'ayub.salsforce@gmail.com'};
        emailRecipients.add(currentuser);
        message.setToAddresses(emailRecipients);
        mails.add(message);
        Messaging.sendEmail(mails);
    
    }
    
}

Here is code to schedule batch jobs dynamically that can be done by executing it in anonymous window in developer console:

String query = 'SELECT Id FROM Case WHERE Status=\''+'Spam'+'\'';
DynamicBatchJobScheduler p = new DynamicBatchJobScheduler('DynamicBatchClass', 100,query);
String sch = '0 30 9 * * ?'; // 9 am 30 mins
system.schedule('Batch Job 1', sch, p);
        
String query = 'SELECT id, TaskSubtype, What.type FROM task WHERE TaskSubtype = \''+'Email'+'\''+ AND What.Type=\''+'Case'+'\'';
DynamicBatchJobScheduler p = new DynamicBatchJobScheduler('DynamicBatchClass', 100,query);
String sch = '0 40 9 * * ?'; // 9 am 40 mins
system.schedule('Batch Job 2', sch, p);