0

I am running a batch class of size 10. Now i trying to get the count of error and success records. I am using database.stateful to maintain data between batches. Im increasing the counter in exceute method and checking the value in finish method. It gives me null counter value.

Below is the code:

global class MassUpdateCaseControllerBATCH implements Database.Batchable<sObject>,Database.stateful {

  List<Id> listCaseRecordIds;
  Map<String, Object> newData;
    public static Integer counter{get; set;}
  // called by case classes that have future methods to ensure this isn't running.
  public static Boolean isMassUpdateRunning = false;

  global Integer getCount() {
        return counter;
    }
  global MassUpdateCaseControllerBATCH(List<Id> listCaseRecordIds, Case newCaseData) {
    this.listCaseRecordIds = listCaseRecordIds;

    String sj = JSON.Serialize(newCaseData);
    newData = (Map<String, Object>) JSON.deserializeUntyped(sj);
  }

  global Database.QueryLocator start(Database.BatchableContext BC) {

    return Database.getQueryLocator('SELECT ID, OwnerId, Status, Minutes_Worked__c, Add_Case_Comment__c, Public_Comment__c FROM Case WHERE Id IN :listCaseRecordIds');
  }

  global void execute(Database.BatchableContext BC, List<sObject> scope) {
    Map<String, Schema.SObjectField> caseSchema = getCaseSchema();

    for (sObject sCase : scope) {
      for (String key : newData.keySet()) {
        if (caseSchema.containsKey(key) && caseSchema.get(key).getDescribe().isUpdateable() == true) {
          if (newData.get(key) != null && newData.get(key) != '') {
            sCase.Put(key, newData.get(key));
          }
        }
      }
    }
    Database.DMLOptions opt = new Database.DMLOptions();
    opt.AllowFieldTruncation = true;
    opt.OptAllOrNone = false;
    MassUpdateCaseControllerBATCH.isMassUpdateRunning = true;

    Database.SaveResult[] resultList = Database.update(scope, opt);
    counter = 0;
    for (Database.SaveResult result : resultList) {
      if (result.isSuccess()) {
         counter+= scope.size();
         System.debug('Sucessfully saved ' + result.getId());
          system.debug('counter' +counter); 
        }

        else {
        createMassUpdateLogRecs(result, BC.getJobID());
      }
    }
      system.debug('counter' +counter); 

  }

  global void finish(Database.BatchableContext BC) {
      system.debug('counter' +counter); 
  }

  private static Map<String, Schema.SObjectField> getCaseSchema() {
    Map<String, Schema.SObjectField> fieldSchema;
    Map<String, Schema.SObjectType> gd = Schema.getGlobalDescribe();

    fieldSchema = gd.get('Case').getDescribe().fields.getMap();
    Return fieldSchema;
  }

  /**
   * Create the mass update log records and save to SF
   * @param  Database.Error[] errors        errors that occurred
   * @param  Id               batchId       Id of the batch
   * @return
   */
  private void createMassUpdateLogRecs(Database.SaveResult result, Id batchId) {
    Map<String, String> fieldLabels = FieldMap();

    Database.Error[] errors = result.getErrors();
    List<Mass_Update_Log__c> massUpLogList = new List<Mass_Update_Log__c>();
    for (Database.Error err : errors) {
      Mass_Update_Log__c mul = new Mass_Update_Log__c();
      mul.Name = batchId;
      mul.Error__c = err.getMessage();
      String fields = '';
      for (String field : err.getFields()) {
        fields = fields + fieldLabels.get(field.toLowerCase()) + ', ';
      }
      mul.Fields__c = fields.removeEnd(', ');
      mul.Status_Code__c = err.getStatusCode().name();
      Blob hash = Crypto.generateDigest('MD5', Blob.valueOf(mul.Error__c + mul.Fields__c + mul.Name));
      mul.Hash__c = EncodingUtil.base64Encode(hash);
      massUpLogList.add(mul);
    }

    insert massUpLogList;
  }

  public static Map<String, String> FieldMap() {
    String type = 'Case';
    Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
    Schema.SObjectType leadSchema = schemaMap.get(type);
    Map<String, Schema.SObjectField> fieldMap = leadSchema.getDescribe().fields.getMap();

    Map<String, String> mapValues = new Map<String, String>();
    for (String fieldName : fieldMap.keySet()) {
      mapValues.put(fieldName.toLowerCase(), fieldMap.get(fieldName).getDescribe().getLabel());
    }
    return mapValues;
  }
}
1
  • You have a lot of minor problems with your code, but it should function. I suspect that the null value you're seeing is not anywhere in this code, but rather in the code that's calling this batch job.
    – sfdcfox
    Mar 7, 2019 at 22:40

1 Answer 1

1

Your variable counter is declared static:

public static Integer counter{get; set;}

Static variables are not preserved by Database.Stateful:

When using Database.Stateful, only instance member variables retain their values between transactions. Static member variables don’t retain their values and are reset between transactions.

To store this state across batch invocations, you need to make it a non-static member variable.

You must log in to answer this question.

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