0

Trying to implement Dan Appleman solution to call batch job from finish method of another batch job. Bu the execute method is continously looping. Can someone suggest me on ways to improve my batch class to achieve what Dan got explained in his solution (calling a method in the finish of batch job which again calls the same batch job when there are still records pending). Thanks

public class caseTriggerBatch implements Database.Batchable<caseVars>, Database.AllowsCallouts, Database.Stateful {

    public integer remaining;
    public string jsonString;
    public list<CaseVars> cM;

    public caseTriggerBatch(Integer count, list<CaseVars> cTest){
        remaining = count-1;
        cM = cTest;
        //cM = new List<CaseVars>();
        //cM.add(cTest[remaining]);
    }

    public Iterable<caseVars> start(Database.BatchableContext BC){
        system.debug('starting'+remaining);
        return cM;
    }   

    public void execute (Database.BatchableContext BC, List<CaseVars> cList){
        list<caseVars> cV = new list<caseVars>();
        for(caseVars c: cList){
            CaseVars caseV = new CaseVars();
            caseV.caseId = c.caseId;
            caseV.caseNumber = c.caseNumber;
            caseV.origin = c.origin;
            cV.add(caseV);
        }
        system.debug(cV);
    }

    public void finish (Database.BatchableContext BC){
        remaining--;
        system.debug('exiting'+remaining);
        if(remaining > 0){
            StartTheBatch(remaining, cM);
            system.debug('last'+remaining);
        }
    }

    public static void StartTheBatch(Integer repeats, list<CaseVars> c){
        caseTriggerBatch ct = new caseTriggerBatch(repeats, c);
        Database.executeBatch(ct, 1);
    }
}
5
  • 2
    Dan framework works like this: If you want to submit a batch, you need to insert a record in the ApexAsync custom job. The batch job looks at the number of records in this custom object and runs the batch those many times. Upon successful finish of the batch it removes the record from the custom object and the finish method restarts the batch if there are still records exist in that custom batch. I think you are implementing totally different.
    – javanoob
    Aug 20, 2015 at 19:56
  • 1
    Are you referring to the appleman async apex pattern? Your execute(..) method does nothing useful. I don't see how items in the initial list are ever removed
    – cropredy
    Aug 20, 2015 at 19:58
  • I added system.debug for now. But my actual requirement is I need to do post each caseVars from list<caseVars> to webservice. This webservice can only take one record at a time. so I cannot go for future as I am reaching limits easily. So looking for alternate solution and found this and trying
    – sf_user
    Aug 20, 2015 at 20:09
  • 1
    You can use the Limits class methods to see if you still have any callouts left, if you ran out of callouts but have records still need to be processed, then start the batch again from finish method. I had similar requirement and I can post code once I reach home.
    – javanoob
    Aug 20, 2015 at 23:36
  • Thanks Javanoob. Please post when you find time and that can be really useful. What I tried ? I initially used future callout hoping that webservice can handle multiple records in single callout. But when I learnt I have to post one record at a time, I am kind of stuck and trying to find a solution
    – sf_user
    Aug 21, 2015 at 0:19

1 Answer 1

2

I think code is kind of simple and self-explanatory. We are making callouts from start method until the governor limit is reached or our records are completed. If governor limit is reached but still records are left then set the chainAnotherBatch boolean to true so that finish method starts the batch again. When you are finished with your records, set the chainAnotherBatch flag to false and finish method exits the batch silently..

Refer to this question and it gives you some clarity on the callouts from batch apex : Number of callouts allowed from batch execute method showing zero? I hope this solves your requirement.

global class CalloutsFromBatchExample implements Database.Batchable<SObject>,Database.AllowsCallouts,Database.stateful{

    public Boolean chainAnotherbatch = true;

    public void OwnLocalBatchClass(){
    }   

    public Iterable<SObject> start(Database.BatchableContext bc){

        Integer totalCallouts = Limits.getLimitCallouts();

        for(Integer i = 0;i<totalCallouts;i++){
            //Make the callout
            //Build the scope object
            //Have a if condition to set the chainAnotherbatch boolean to true or false.            
        }
        return scope;
    }

    public void execute(Database.BatchableContext bc, List<Sobject> scope){
            Database.insert(scope); 
    }

    public void finish(Database.BatchableContext bc){
        if(chainAnotherbatch){
            Database.executeBatch(new CalloutsFromBatchExample(),1000);
        }else{
            System.debug('Start method signalled that no need to chain another batch another batch job ');
        }
    }
}
1
  • Thanks javanoob for your time. Really helpful and should definitely help me start off. Will implement this and get back to you.
    – sf_user
    Aug 21, 2015 at 1:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .