|
Why does activeStateForUndo() Perform a ROLLBACK?
A partner wrote in to ask about why the ApplicationModule's activateStateForUndo() method performs a database-level ROLLBACK operation before reactivating the application module's state. This short article tries to clarify why we do this.
First of all, the combination of the passivateStateForUndo() and the activateStateForUndo() methods allow the developer to programatically leverage the same underlying infrastructure that is used for implicit state management across HTTP request boundaries by the application module pooling infrastructure. The key difference is that this combination of methods allow the developer to assign a logical name to a sort of application-tier "savepoint" and then rollback the state of the application-tier transaction to the snapshot of pending changes taken at that previous "savepoint" by name at some point in the future.
In general, a passivation of middle-tier transaction state and its subsequent activation can conceivably involve completely different application module instances from the same pool, or even instances from different Java VM's or different application servers due to the request's getting failed-over. In addition, the passivation and subsequent activation can conceivably involve different database connection instances used on subsequent requests from a connection pool. Due to these reasons, your application should never assume that database transaction state will be the same after a reactivation as it was at the time of passivation. We enforce this best practice by forcing a database-level ROLLBACK on the connection as part of every re-activation of middle-tier state. This holds whether it is performed implicitly by the application module pooling mechanism, or explicitly by calling activateStateForUndo().
The ApplicationModuleImpl class provide the overridable methods named passivateConnectionState() and activateConnectionState() if your application needs to save-away some custom information into the state snapshot and use it at reactivation time to restore some database-level transaction state to the expected values. By being very explicit about this, you insure that your application will work correctly under load and under failover scenarios, rather than being surprised when what worked in your one-user testing suddenly "breaks" when the system is put under load.
Also, it's worth noting that Row and/or Entity references that your code might have from before an activateStateForUndo() call need to be re-found using findByKey() after the activateStateForUndo() call to remain usable.
Additional information about the application module pooling mechanism and the application module statement management facility can be found in the following whitepapers on OTN:
|