AnyLogic Initialization Order: Java and Database

       AnyLogic initialization order becomes increasingly important as simulation models grow more complex and introduce dependencies between agents, Java classes, database access, and configurable model parameters. This becomes particularly important in petroleum refining simulation, where process units, tank farms, product mixers, and other Petroleum Refining Library components depend on configurable parameters.
       To manage these values centrally, the Petroleum Refining Library uses the a_model_constants table included in the model database. The table stores each constant's name, label, description, value, and unit. Petroleum Refining Library components can reference these model constants instead of using hard-coded values.
       The problem occurs when AnyLogic evaluates a component property before the Java object that provides its database-backed value has been initialized. This is an initialization-order problem: the property is valid, the database value is valid, but the required dependency is not yet available.

AnyLogic Initialization Order and Database Dependencies

       AnyLogic initializes objects in a defined hierarchy: nested agents are initialized before the agents that contain them. In complex models, this can create dependencies between component properties, Java objects, and database-loaded data. For example, a ProductMixer component may use the ModelConstants Java class to define minimum and maximum additive values.
        If the ProductMixer property is evaluated before ModelConstants has been initialized and loaded from the database, the reference can still be null, causing an initialization error. The dependency can be represented as:

Product Mixer property → ModelConstants → database

       The problem is therefore not the database value itself, but the timing of its initialization. A common workaround is to perform a null check before accessing ModelConstants:
if (modelConstants == null) {
    initializeModelConstants();
}

return modelConstants.getValue(...);
       However, spreading these initialization checks across individual components makes the model harder to maintain and couples component logic to the model initialization sequence.

Initializing Model Constants Before Agent Creation

       A cleaner solution is to move shared configuration initialization out of individual components and into an earlier stage of the AnyLogic model lifecycle. The AnyLogic Simulation Experiment provides an early initialization point where shared configuration can be prepared before dependent model agents are initialized. In particular, the Initial Experiment Setup and Before Each Experiment Run fields can be used to execute initialization code before the model agents are created.
       Starting with Petroleum Refining Library 2.2.5, the ModelConstants constructor can perform this initialization directly. It receives the model folder, connects to the embedded HSQLDB database, reads the constants, and stores them in memory.
As a result, when a component such as Product Mixer evaluates its properties, the required constants are already available. No additional null checks are required in the component code.
       This changes the initialization sequence from:

Agent initialization → property evaluation → ModelConstants → database

to:

Experiment initialization → ModelConstants → database → agent initialization → property evaluation

       This approach keeps database initialization separate from individual components and makes the overall model architecture more predictable and maintainable.

ModelConstants Initialization in Petroleum Refining Library 2.2.5

       In Petroleum Refining Library 2.2.5, the ModelConstants constructor was extended to initialize model constants directly from the embedded HSQLDB database. The constructor receives the model folder, opens a read-only JDBC connection to the model database, and loads the constants into memory:
try (Connection conn = DriverManager.getConnection(url, "sa", "");
     PreparedStatement stmt = conn.prepareStatement(SQL_QUERY);
     ResultSet rs = stmt.executeQuery()) {

    while (rs.next()) {
        add(
            rs.getString("constant_label"),
            rs.getString("constant_name"),
            rs.getString("description"),
            rs.getDouble("constant_value"),
            rs.getString("constant_unit")
        );
    }
}
       The isInitialized() check prevents the shared constants from being initialized more than once. The database is opened in read-only mode because the model only needs to retrieve configuration data during initialization. A parameterless constructor is also provided for cases where the model folder can be resolved automatically:
public ModelConstants() {
    this(new java.io.File(".").getAbsolutePath());
}
       The important architectural change is that database access is now performed when ModelConstants is explicitly initialized, rather than being triggered only when an individual component first requests a constant. This makes the initialization sequence predictable and removes the need to handle the same dependency separately in each Petroleum Refining Library component.

Initializing ModelConstants in an AnyLogic Experiment

       The recommended approach is to initialize ModelConstants from the Experiment before the model agents are created. This ensures that database-backed configuration is available when component properties are evaluated. For example, the Experiment initialization code can create the constants object using the model directory:
       As a result, the initialization dependency is handled once at the model level instead of being repeated across individual components.
       ModelConstants is implemented as a static class, so its constructor can be called without assigning the resulting object to a variable. The constructor performs the initialization and loads the shared model constants from the database.
       The exact initialization point depends on the experiment configuration, but the important requirement is that ModelConstants is created before the first dependent agent is initialized. Once initialization is complete, components can reference model constants directly from their Properties panel without implementing additional initialization logic.
       This approach provides a clear separation of responsibilities:
  • Experiment controls when global configuration is initialized.
  • ModelConstants loads configuration from the database.
  • Petroleum Refining Library components consume the already initialized values.
  • Component properties do not need to manage database initialization themselves.
       As a result, the initialization dependency is handled once at the model level instead of being repeated across individual components.

Benefits of Early Initialization

       Initializing ModelConstants before agent creation moves initialization responsibility from individual Petroleum Refining Library components to the model lifecycle.Components can assume that the required configuration is already available when their properties are evaluated.

       This approach has several practical advantages:
        - No repeated null checks in individual components.
        - Centralized database initialization at the model level.
        - Cleaner Properties panel expressions that can directly reference model constants.
        - Simpler Java code without component-specific initialization workarounds.
        - More predictable model startup in complex agent hierarchies.
        - Better separation of responsibilities between model initialization and component behavior.
       For complex AnyLogic models, this pattern can be useful whenever component properties depend on Java objects, database records, or other resources that must exist before agent initialization begins.
The key principle is to initialize shared configuration at the earliest appropriate stage of the model lifecycle rather than allowing individual components to initialize it on demand.

Conclusion

       AnyLogic initialization order becomes an architectural concern when model components depend on Java objects or database-backed configuration. In complex refinery simulations, evaluating a component property before its configuration dependency is initialized can cause startup errors even when the underlying data is valid.
       Petroleum Refining Library 2.2.5 addresses this problem by allowing ModelConstants to be initialized before dependent agents are created. This moves database initialization to the model lifecycle and keeps individual components focused on their simulation logic.
       The general principle is applicable beyond ModelConstants: initialize shared dependencies before the agents and properties that consume them. This approach produces cleaner Java code, more predictable model startup, and a more maintainable AnyLogic simulation architecture.

FAQ

1. What is the initialization order in AnyLogic?
AnyLogic initializes objects according to the agent hierarchy. Nested agents and their objects are initialized before the agents that contain them. In complex models, this can create dependencies between component properties and database-backed Java objects.

2. Why can AnyLogic return a null value during initialization?
A property may be evaluated before the Java object providing its value has been initialized. For example, a Product Mixer may request a value from ModelConstants before ModelConstants has loaded its data from the database.

3. How can database initialization cause an AnyLogic startup error?
If a component property depends on data loaded from a database, the database-backed object must be initialized before that property is evaluated. Otherwise, the reference can be null and cause an initialization error.

4. How can I initialize ModelConstants before AnyLogic agents?
ModelConstants can be initialized from the Experiment before the model agents are created. In Petroleum Refining Library 2.2.5, its constructor performs the required database initialization.

5. Does ModelConstants need to be assigned to a variable?
No. ModelConstants is implemented as a static class, so the constructor can be called without assigning the resulting object to a variable. The constructor initializes the shared model constants.

6. How does Petroleum Refining Library 2.2.5 solve the initialization problem?
Version 2.2.5 allows ModelConstants to be initialized explicitly at an earlier stage of the model lifecycle. This ensures that database-backed constants are available before dependent PRL components are initialized.

7. Is it better to use null checks or early initialization?
For shared configuration objects, early initialization is generally cleaner. It removes repeated null checks from individual components and makes the dependency explicit at the model level.

8. Can the same approach be used for other Java classes in AnyLogic?
Yes. The same architectural principle can be applied whenever an agent or component depends on a shared Java object, database data, or another resource that must exist before agent initialization.