Skip to content

Application context initialization

AppManagerBase is an abstract application-manager base class inherited by concrete application managers throughout the BOF stack. Before a manager can service a request it must run its one-time initialization sequence, which wires up its data-access layer and hands control to subclass-supplied hooks for the rest of setup. This operation captures that sequence and the related context-validity check that callers use afterward.

Field Value
Operation ID OP-APP-01
Trigger A consuming subclass calls the protected Initialize() method, typically from its own constructor or an explicit setup call
Inputs The clsSecurityPrincipal supplied to the protected constructor; subclass-specific state read by OnInitialize() and OnCreateDataLayer()
Outputs A manager instance with its lazily-created ApplicationDataAccess data layer available through the DataLayer property; subclass-specific initialization side effects
Primary components AppManagerBase.New, AppManagerBase.Initialize, AppManagerBase.OnInitialize (MustOverride), AppManagerBase.OnCreateDataLayer (MustOverride), AppManagerBase.DataLayer, AppManagerBase.ValidContext
Entry point Application\SAIF.Application\AppManagerBase.vb

Steps

  1. Construct the manager. The protected constructor New(inSecurityPrincipal As clsSecurityPrincipal) stores the caller-supplied security principal in m_SecurityPrincipal, exposed to subclasses through the read-only SecurityPrincipal property. No data layer is created at construction time.
  2. Call Initialize(). The subclass (or its own constructor) invokes the protected Initialize() method, which runs exactly two steps in order and returns nothing:
  3. OnInitialize() — a MustOverride hook the subclass implements to perform its own setup (for example, reading request context or seeding default state).
  4. OnCreateDataLayer() — a MustOverride hook the subclass implements to populate the manager's ApplicationDataAccess instance with the portal entries it will need.
  5. Because both hooks are abstract, AppManagerBase itself performs no concrete initialization work beyond invoking them in this fixed order; all actual behavior depends on the subclass implementation.*
  6. Lazily materialize the data layer. The first time any code reads the DataLayer property, AppManagerBase checks whether m_DataLayer is Nothing and, if so, constructs a new ApplicationDataAccess(SecurityPrincipal.UserName.ToString) — passing the security principal's user name as the batch-user constructor argument — and caches it for the life of the manager instance.
  7. On failure: if SecurityPrincipal is Nothing (constructor never called with a valid principal, or OnInitialize()/OnCreateDataLayer() read DataLayer before construction completes), the UserName.ToString call raises a NullReferenceException. This is not explicitly guarded.*
  8. Register portals during OnCreateDataLayer(). Subclasses typically call DataLayer.CreateSQLServerPortal(key) or DataLayer.CreateOraclePortal(key) from within their OnCreateDataLayer() override; see Multi-database portal registration for that operation's own step sequence, which this step delegates to.
  9. This is an embedded delegation to a sibling operation of this same library, not an external dependency — no > Origin callout is required because both operations are documented in this library's own operations/ folder.
  10. Confirm context validity before use. Once initialized, callers read the ValidContext property to decide whether the manager instance has enough state to proceed with a retrieve or write:
  11. ValidContext delegates directly to OnValidContext(), another MustOverride hook.
  12. The subclass implementation inspects whatever state it considers necessary (for example, whether a required identifier or context key has been set) and returns True or False.
  13. If ValidContext returns False: callers are expected to avoid invoking Retrieve() or Write(); AppManagerBase does not itself block those calls when the context is invalid — enforcement is left to the subclass or caller.*
  14. Track explicit context-set state separately. AppManagerBase also maintains a private m_ContextSet flag, toggled by the protected MarkContextSet() and MarkContextNotSet() methods, exposed read-only as ContextSet. This is a distinct signal from ValidContext — ContextSet records whether the subclass has explicitly marked the context as entered, while ValidContext is a subclass-computed judgment of whether that context is usable.*

Process flow

The following diagram visualizes the initialization and context-validity sequence.

flowchart TD
    Start([Subclass constructor runs]) --> Ctor[AppManagerBase.New stores<br>SecurityPrincipal]
    Ctor --> Init[Subclass calls Initialize]
    Init --> OnInit[OnInitialize hook<br>subclass-defined]
    OnInit --> OnLayer[OnCreateDataLayer hook<br>subclass-defined]
    OnLayer --> Portal[Register SQL Server / Oracle<br>portals via DataLayer]
    Portal --> MarkSet[Subclass calls MarkContextSet<br>when context is entered]
    MarkSet --> Valid{Caller reads ValidContext}
    Valid --> OnValid[OnValidContext hook<br>subclass-defined]
    OnValid -->|True| Proceed([Manager ready for<br>Retrieve or Write])
    OnValid -->|False| Block([Caller should not proceed;<br>not enforced by AppManagerBase])

Failure and edge-case behavior

  • Initialize() calls OnInitialize() unconditionally before OnCreateDataLayer(); a subclass that needs data-layer state during OnInitialize() cannot get it from this base sequence.*
  • The lazy DataLayer getter has no null-check on SecurityPrincipal, so a manager constructed without a valid principal (or a subclass path that reads DataLayer before the constructor sets it) fails with a NullReferenceException rather than a descriptive error.*
  • ValidContext and ContextSet are independent flags; nothing in AppManagerBase keeps them synchronized, so a subclass could mark the context set (MarkContextSet()) while OnValidContext() still reports invalid context, or vice versa.*
  • Because OnInitialize(), OnCreateDataLayer(), and OnValidContext() are all MustOverride, the base class provides no default behavior at all — every concrete initialization or validity rule lives in the consuming application's subclass and is outside this library's documentation scope.

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • Application\SAIF.Application\AppManagerBase.vb
  • Application\SAIF.Application\ApplicationDataAccess.vb