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);
    }
}
  • 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 '15 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 '15 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 '15 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 '15 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 '15 at 0:19
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 ');
        }
    }
}
| improve this answer | |
  • 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 '15 at 1:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.