0

I have a below batch class where I am passing 100 account ids to the constructor and in the debug logs I can see 100 in constructor as a set size but in start method I can see 0, could someone please suggest

 public class batching implements database.Batchable<sObject>, Database.AllowsCallouts {

    static set<id> accountIdSet = new set<Id>();
    public restCallout(set<id> accountIds) {

        accountIdSet = accountIds;
        System.debug('size from constructor '+accountIdSet.size());

    }

    public static database.QueryLocator start(database.BatchableContext bc) {
        System.debug('size from start method '+ accountIdSet.size());
        return database.getQueryLocator([SELECT Id FROM Account WHERE ID In:accountIdSet ]); 
    }

    public static void execute(database.BatchableContext bc, list<sObject> Scope) {
        System.debug('Size from execute '+ Scope.size());

        for(Account act: (List<Account>)scope) {            
            makeACallout();
        }
    }
    public static void finish(database.BatchableContext bc) {

    }
1
  • be careful with callouts in batch execute() - there are limits to worry about (# callouts, total callout time) so you need to keep scope size well under 200
    – cropredy
    Commented Feb 25, 2020 at 2:26

2 Answers 2

4

The conventional way to write this is to pass the Account Ids in the constructor and not use any static declarations:

 public class Batching implements Database.Batchable<sObject>, Database.AllowsCallouts {

    private Set<Id> accountIdSet = new Set<Id>();

    public Batching(Set<Id> accountIdSet) {
        this.accountIdSet = accountIdSet;
    }

    public Database.QueryLocator start(Database.BatchableContext bc) {
        System.debug('size from start method '+ accountIdSet.size());
        return Database.getQueryLocator([
            SELECT Id
            FROM Account
            WHERE ID In :accountIdSet
        ]); 
    }

    public void execute(Database.BatchableContext bc, List<sObject> scope) {
        System.debug('Size from execute '+ scope.size());
        for (Account act: (List<Account>) scope) {            
            makeCallout(act);
        }
    }

    public void finish(Database.BatchableContext bc) {
    }

    private void makeCallout(Account act) {
        ...
    }
}

It can then be used like this:

Integer batchSize = 100;
Set<Id> accountIdSet = ...
Database.executeBatch(new Batching(accountIdSet), batchSize);

There are other ways to pass values but a constructor:

prepares the new object for use

so is a good way to go to stop users of the class invoking it before it is in the right state.

1

You need to do like this:-

set<id> accountIdSet{get;set;}
public restCallout(set<id> accountIds) {

    accountIdSet = accountIds;
    System.debug('size from constructor '+accountIdSet.size());
}

Automatic properties allow you to write more compact code that is easier to debug and maintain. It will make sure accountIdSet retain the value in start method.

Update

Also, remove the static keyword from variable definition of accountIdSet.

2
  • Thank you for responding but it is still not working, I am getting null pointer exception in start method where I am checking the size of accountIdSet but in constructor I can see 100, please suggest
    – gs650x
    Commented Feb 23, 2020 at 7:04
  • @gs650x, I have updated my answer Commented Feb 23, 2020 at 7:06

You must log in to answer this question.

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