6

Below is my question in a nutshell, using the framework for a batch apex class:

global class ActOn_Batchable implements Database.Batchable<sObject>{

    string query = 'query here';

    **CAN I INSERT CODE HERE THAT WILL BE ACCESSIBLE BY THE BATCHES?**
    for example:
    string AuthKey = SomeOtherClass.callout_for_AuthKey();


    global Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<sObject> scope){

    }

    global void finish(Database.BatchableContext BC){
    }

}

To clarify the example shown in the code: In my current scenario I'm using batch to get around the 10 callout limit. Since each batch is going to need an AuthKey, my thought was to get the AuthKey with a callout prior to executing on the batches, rather than include the AuthKey callout in each batch (and waste 1 of the 10 callouts allowed per batch).

In my example above, would the string AuthKey be available to each batch if I then reference that string within the 'execute' method? If so, how would the callout used by "callout_for_AuthKey()" count towards governors limits? I'm wondering if the overall class "ActOn_Batchable" has its own set of limits, and then the limits reset for each batch that is executed as well.

1
  • Why not assign the value to global variable 'AuthKey' in the start function, since it's run before all of the batches? AuthKey = SomeOtherClass.callout_for_AuthKey();
    – DavidWaugh
    Commented Jul 29, 2014 at 21:53

2 Answers 2

5

Yes. Batch Apex gives you three bites at the cherry. All of the start and execute and finish methods happen inside their own governor context. Each gets its own limit allowance to work with.

Example: you run Database.executeBatch(impl, 10) and your QueryLocator returns 30 rows:

  • start has its own governor context
  • execute has its own governor context for rows 1-10
  • execute has its own governor context for rows 11-20
  • execute has its own governor context for rows 21-30
  • finish has its own governor context

So you can do something like this using Database.Stateful:

public class ActOnBatchable implements Database.Batchable<SObject>,Database.Stateful {

    private String AuthKey;

    public Database.QueryLocator start(Database.BatchableContext context) {
        this.AuthKey = SomeOtherClass.getAuthKey();
        //you have 9 callouts left inside start method
    }

    public void execute(Database.BatchableContext context, List<SObject> scope) {
        //you have 10 callouts left inside execute method
    }

    public void finish(Database.BatchableContext context) {
        SomeOtherClass.expireAuthKey(this.AuthKey);
        //you have 9 callouts left inside finish method
    }

}

When using Database.Stateful, instance member variables retain their values between transactions.

1
  • OP wants to run code in between subsequent calls to execute. They probably know the info in this question and want a little extra oomph, such as a freebie call to login. It'd be nice for certain use cases, since it'd help full gaps in resources that'd be wasted otherwise.
    – sfdcfox
    Commented Jul 30, 2014 at 0:05
6

You can run code in the constructor of the batch that will run when the class is instantiated. That code will not run in batch context, so you will have all the limits of synchronous code.

Alternatively, you could do the callout in your start method; it all comes down to how you're going to use the batch. If you're going to schedule it, then put your callout in start, as that will be called when the batch is actually run. Code in the constructor will be executed when the batch is scheduled.

Either way, you're using a callout only once.

Be sure to set the batch class to allow callouts:

global class ClassName implements Database.Batchable, Database.AllowsCallouts {
0

You must log in to answer this question.

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