Back to Summer Batch home page

Context Managers

When launching jobs and steps, instances of JobExecution and StepExecution are used by the Summer Batch engine and persisted in the repository. These executions each have a dedicated context that can be used to store data and process variables. In order to give access to theses contexts in a convenient way, several classes were added to Summer Batch: ContextManager, ContextManagerUnityLoader, AbstractExecutionListener and AbstractService.

ContextManager class

The contexts are basically dictionaries. The ContextManager simply enables to store and retrieve from the dictionary and gives some utility methods, particularly methods related to counter management, which is a very common need. There is a single ContextManager class for both job context and step context but two instances will be available, one for the job and the other for the step.

It implements the Summer.Batch.Extra.IContextManager interface, whose code is given below

Example 7.20. IContextManager interface contract

using Summer.Batch.Infrastructure.Item;

namespace Summer.Batch.Extra
{
    /// <summary>
    /// Interface for context manager
    /// </summary>
    public interface IContextManager
    {
        /// <summary>
        /// Accessors for the context
        /// </summary>
        ExecutionContext Context { get; set; }

        /// <summary>
        /// Stores an object inside the cache
        /// </summary>
        /// <param name="key">object key to store</param>
        /// <param name="record">object to store</param>
        void PutInContext(object key, object record);

        /// <summary>
        /// Check if the key is in the cache
        /// </summary>
        /// <param name="key">key of the object to retrieve</param>
        /// <returns>whether it is in the cache</returns>
        bool ContainsKey(object key);

        /// <summary>
        /// Retrieves an object from the cache
        /// </summary>
        /// <param name="key">key of the object to retrieve</param>
        /// <returns>retrieved object</returns>
        object GetFromContext(object key);

        /// <summary>
        /// Clears the cache
        /// </summary>
        void Empty();

        /// <summary>
        /// Dumps the cache content
        /// </summary>
        /// <returns>the content of the cache as a string</returns>
        string Dump();

        /// <summary>
        /// Sets the value of a named counter
        /// </summary>
        /// <param name="counter">the name of the counter</param>
        /// <param name="value">the new value of the the named counter</param>
        void SetCounter(string counter, long value);

        /// <summary>
        /// Returns the value of a named counter
        /// </summary>
        /// <param name="counter">the name of the counter</param>
        ///<returns>the value of the the named counter</returns>
        long GetCounter(string counter);

        /// <summary>
        ///  Increments the value of a counter by one. If this counter does not yet
        /// exist, it is first created with a value of 0 (thus, the new value is 1).
        /// </summary>
        /// <param name="counter">the name of the counter</param>
        void IncrementCounter(string counter);

        /// <summary>
        ///  Decrements the value of a counter by one. If this counter does not yet
        /// exist, it is first created with a value of 0 (thus, the new value is -1).
        /// </summary>
        /// <param name="counter">the name of the counter</param>
        void DecrementCounter(string counter);
    }
}
				
				

[Note]Note

Despite being object for internal compatibility, the key should be a string and will be converted to a string if it is not.

ContextManagerUnityLoader

In order to use the context managers, one should extend a dedicated UnityLoader: ContextManagerUnityLoader, that will register in the unity container two instances of the ContextManager, one for the job and one for the step. The keys used for these regsitrations are BatchConstants.JobContextManagerName and BatchConstants.StepContextManagerName. As usual, this class must be extended and the LoadArtifacts must be implemented with all the job artifacts registrations. If a registration should declare a ContextManager as a property, it can be done through usual unity wiring.

Example 7.21. Unity wiring example for ContextManager

container.StepScopeRegistration<IMyInterface, IMyClass>("MyKey")
    .Property("JobContextManager").Reference<IContextManager>(BatchConstants.JobContextManagerName)
    .Property("StepContextManager").Reference<IContextManager>(BatchConstants.StepContextManagerName)
    .Register();

[Note]Note

Unity registration can also be done through automatic injection, which is the strategy used in AbstractExecutionListener and AbstractService presented just below.

AbstractExecutionListener and AbstractService

AbstractExecutionListener class must be extended by the Processor classes. It supplies access to the StepContextManager and JobContextManager properties and adds a StepListener capability: in the BeforeStep method, the job and step context managers are linked to the current job execution context and step execution context. Then, the context managers can be used in the processor code. Even other services involved in the processing can access these context managers by extending AbstractService. In any case, with these base classes, properties named StepContextManager and JobContextManager will be available and usable.

[Caution]Caution

If you do not use AbstractExecutionListener, the context managers will not be linked to the correct contexts, and even if they are injected, they will remain empty shells and not work properly.

Back to Summer Batch home page