7

How does one handle individual record errors in a Batch Process?

Tried the following example below, but once I iterate through wlist after the batch has completed (checking the job status through an apex:actionPoller), the wlist contains no errors, even though several have occurred.

//Calling Class
MyBatchClass job = new MyBatchClass(wlist);
Id jobId = Database.executeBatch(job);
//iterate through wlist to look for record erros

//Batch class
global class MyBatchClass implements Database.Batchable<SObject>,Database.Stateful{

  global List<MyWrapper> wlist {get;set;}
  global Integer currentIndex {get;set;}

  public MyBatchClass(List<MyWrapper> wlist){
     this.currentIndex = 0;
         this.wlist = wlist;
  }

  global Iterable<sObject> start(Database.BatchableContext bc){
    List<MyObject__c> olist = new List<MyObject__c>();
    for(MyWrapper w : rewardPoints){
      olist.add(w.obj);
    }
    return olist;
  }

  global void execute(Database.BatchableContext bc, sObject [] objects){
    for(Database.SaveResult sr : Database.insert(objects,false)){
      if(!sr.success){
        wlist.get(currentIndex).errorMessage = sr.getErrors().get(0);  
      }
      currentIndex++;
    }
  }

  global void finish(Database.BatchableContext bc){}
}
  • Maybe you just excluded that code but I don't see where you are adding any elements to wList. – Greg Grinberg Aug 18 '12 at 16:08
  • Good catch. Omitted it from the constructor in the psuedo code above. Fixed the pseudo code, but the issue at hand still exists. – James Loghry Aug 18 '12 at 20:57
  • Did my answer resolve the issue or was it something else? – Greg Grinberg Aug 19 '12 at 17:01
9

You can only access wlist in the finish method of the batch class. You will not be able to access it by waiting for the batch job to finish and then getting job.wlist.

If you are trying to run the batch job from a visualforce page and provide detailed information about the errors on the page when the job completes you have three ways of doing this.

  1. Save wlist to an object in salesforce and then query for it when the job completes. You could include the batch job id in the object to separate results from different jobs.
  2. put wlist in a static variable in your finish method and then access that static variable from your controller.
  3. Pass in your controller to MyBatchClass and update a MyWrapper list variable that resides in your controller. I haven't tested this but I THINK it should work.

Here's some sample code for the first option:

global class MyBatchClass implements Database.Batchable<SObject>, Database.Stateful
{

  global List<MyWrapper> wlist {get;set;}
  global Integer currentIndex {get;set;}

  public MyBatchClass(List<MyWrapper> wlist){
     this.currentIndex = 0;
         this.wlist = wlist;
  }

  global Iterable<sObject> start(Database.BatchableContext bc){
    List<MyObject__c> olist = new List<MyObject__c>();
    for(MyWrapper w : rewardPoints){
      olist.add(w.obj);
    }
    return olist;
  }

  global void execute(Database.BatchableContext bc, sObject [] objects){
    for(Database.SaveResult sr : Database.insert(objects,false)){
      if(!sr.success){
        wlist.get(currentIndex).errorMessage = sr.getErrors().get(0);  
      }
      currentIndex++;
    }
  }

  global void finish(Database.BatchableContext bc)
  {
      list<Batch_Error__c> errors = new list<Batch_Error__c>();
      for(MyWrapper w : wlist) errors.add(new Batch_Error__c(error=w.errormessage));
      insert errors;
  }
}
  • I havent tried them yet, but all 3 make sense. I was considering the writing error objects w/ batch id before i posted this question. Little apprehensive about 2 and 3 and being able to retain the correct state in the controller, but still worth a shot. Thanks. – James Loghry Aug 20 '12 at 1:34

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.