16

As part of the batch context, the static variables get reset at each transaction irrespective of Stateful/Stateless.

class batch_test implements database.batchable, database.stateful () {
   static int value =1;
   start () {
      value =2 ;
   }

   execute () {
      System.debug ( value  ) ; // this will print 1 and not 2 
   }
   finish () {
       System.debug ( value  ) ; // this will print 1  

   }
}

Does anyone know why does database.stateful not persist state for static variables and only for instance variables ?

1
  • 1
    Welcome to SFSE, and kudos for a great first question. – Matt Lacey Mar 31 '15 at 3:16
12

As Bri mentioned, static variables persist for the duration of the execution context in Apex. start(), finish(), and each invocation of the execute() method operate in separate execution contexts, so static variables are reset in the same way they would be reset in separate trigger executions.

Implementing Database.Stateful allows you to use member variables that act in the way you're expecting in this case.

global class batch_test implements Database.Batchable<sObject>, Database.Stateful {
    global Integer value = 1;
    global Database.QueryLocation start(Database.BatchableContext BC) {
        value = 2;
    }

    global void execute(Database.BatchableContext BC, List<sObject> scope) {
        // this will print 2 the first execution, and so on...
        System.debug(value++);
    }

    global void finish(Database.BatchableContext BC) {
        // this will print 2 + however many batches were executed
        System.debug(value);
   }
}
2
  • Thanks. I do see in the Batch apex documentation about the static variables being reset with each transaction. In Database.Stateful instance is not reset but static variables are and I am not able to wrap my head around it. Any pointers? – Sithlord Mar 30 '15 at 21:36
  • 3
    @sithlord - one way to think about this is to look at the debug log after starting your batch class with Database.executeBatch() - you will see separate logs for the start() method, each execute() method, and the finish() method. Each log is a transaction context and as such, the static variables last only as long as the transaction. Database.stateful is the only way within the batch object for the start, each execute, and the finish to communicate using apex variables. – cropredy Mar 31 '15 at 0:52
7

Database.Stateful serializes the object being batched, not the entire memory graph of the transaction that spawns the batch process. I wouldn't know exactly "why" this is, but I'd guess that the underlying implementation uses some sort of binary serialization technique that stores just the object being executed upon, and not the entire memory graph of the execution context.

This makes sense from a performance and space-saving perspective, even if it might happen to be inconvenient at times. A carefully observant developer would notice that the object is serialized at the point where System.executeBatch is called, not at the end of the transaction. For example:

SomethingBatchable b = new SomethingBatchable();
b.someValue = 50;
System.executeBatch(b);
b.someValue = 100;

when start is called on SomethingBatchable, someValue will be 50, not 100, even though we set it later. This is because b was serialized and placed into the queue as-is. In fact, you can execute the same object more than once, with different values, and they will all behave as uniquely instanced values later (assuming, of course, you're in a context that allows more than one batchable call, such as Visualforce context).

I'd further suspect that the entire state of the object is stored in a single BLOB (binary large object) field, and couldn't support static variables correctly anyways without some significant effort, or using considerable database space. Reconstructing the entire memory graph of the object might even be prohibitively expensive time-wise, even if it were possible to do so under the current implementation.

However, at least there happens to be one upshot: you can store non-serializeable data in static variables, and they will be transient, avoiding otherwise fatal errors, such as trying to serialize SavePoint objects (which would cause invalid states if they were allowed to be serialized).

Finally, since we're not able to serialize the entire memory graph, it makes sense that the static variables of the class you're in are treated equally compared to the static variables of a completely unrelated class that might have been loaded in memory at the time. Defining the limits of the serialization to just the contents of a single object greatly simplifies the behavior and offers consistency.

0

Unlike traditional static variables, in Apex, static variables persist only in a single execution context. It appears that the separate transactions in your example are different execution contexts, so the value is reinitialized each time.

1
  • let me restate this. what would make static variable so different? I know that static variables are in a different container. All the documentation says is static variables gets reset on each transaction - but any reason why stateful doesnt hold the static variables past value? the salesforce documentation seems to pose more question than it answers – Sithlord Mar 30 '15 at 21:02

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.