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 Feb 25 '20 at 2:26
3

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 Feb 23 '20 at 7:04
  • @gs650x, I have updated my answer – sanket kumar Feb 23 '20 at 7:06

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.