Startup / Initiation

strong.valid.simple Application Configuration

AndHow Initiation

Initiation is AndHow's startup/bootstrap process where it does the following:

  • Discovers its own configuration

  • Discovers all declared AndHow Properties (even those in dependencies)

  • Loads values for those properties from various sources using the configured Loaders

  • validates all property values

Within the lifecycle of your application, AndHow will initialize only once (and that is important). Its also important to realize that Java has no 'startup hook', that is, there is no standard way to have some initialization code that runs as soon as an application starts up. Thus, AndHow initialization happens in response to some type of application event.

There are two types application events that trigger initiation: Implicit and Explicit.

Implicit Initiation

Implicit initiation happens as a side effect of reading a property value, which is what happens in the GettingStarted example:

for (int i = COUNT_DOWN_START.getValue(); i >= 1; i--) { ... }

The call to Property.getValue() forces AndHow to initialize so that it can provide the value. Later calls to getValue() of any property simply return the value loaded for that property - the initiation will only ever happen once. This is the simplest way to initialze AndHow - just let it happen on its own.

If your application could start up and not access any property values immediately, then AndHow will not be forced to initialize and your configuration values are not verified. In that case, you should use explicit initialization.

Explicit Initiation

Explicit initiation happens when your code directs AndHow to construct its one and only instance. We could extend the GettingStarted example to load property values from the String[] args passed to the main method by explicitly initiating AndHow in the main method:

public static void main(String[] args) {

AndHow.findConfig().setCmdLineArgs(args);

AndHow.instance();

...

}

AndHow.instance() causes AndHow to do its one time only initiation to return the single instance of AndHow. All values for all Properties are loaded and validation is run for all of them. Later calls to AndHow.instance() simply return the singleton AndHow instance.

Note: Prior to 0.5.0, the public instance(AndHowConfiguration config) method allowed application code to attempt to explicitly re-initialize AndHow. This would just throw an error if AndHow was already initialized. This method was removed, so its no longer possible to attempt to force an initialization after AndHow is already initialized.

Note that the call to AndHow.findConfig() is only allowed before AndHow is initialized.

Attempting to reconfigure AndHow will throw a RuntimeException

From the code snippets above, imagine the value for COUNT_DOWN_START is read, causing an implicit initiation, then the main method is called, which attempts modify the configuration of AndHow by adding the command line arguments. If a value for COUNT_DOWN_START was passed to the main method, the value read before main() was called would be incorrect or at least unintended.

This a serious problem and AndHow protects applications from this situation by throwing a RuntimeException for any call to AndHow.findConfig when AndHow is already initialized. In practice this means that applications should follow best practices and have a well defined entry point where AndHow and other one-time initiation takes place. Common entry points are:

  • A main method in single startup class for desktop application / executable jar

  • A ServletContextListener with a contextInitialized method for a web application

  • The handle() method of a lambda function

Using explicit initiation at your application's entry point ensures that configuration is deterministic and that your application will fail fast if configuration values are invalid.

AndHow Initiation Steps

Lets walk through each of the initiation steps

Configuration Discovery

AndHow will use the StdConfig to configure itself, which is an instance of AndHowConfiguration, unless there is an implementation of AndHowInit is on the classpath. AndHowInit is an interface with a single method: getConfiguration() which returns AndHowConfiguration. Common initiation needs, like injecting String[] args or adding fixed values can be handled in-line with explicit initiation (example above). For more detailed control, subclassing StdConfig and providing an AndHowInit implementation is needed.

How does AndHow scan for AndHowInit implementations?

AndHow uses a similar process for Property discovery and configuration discovery. At compile time, the AndHowCompileProcessor 'sees' all classes as they are being compiled. If it sees a non-abstract AndHowInit , the processor adds a provider-configuration file at: META-INF/services/org.yarnandtail.andhow.AndHowInit which just contains the full name of the implementation. At runtime, the Java ServiceLoader is able to scan all jars and resources on the classpath for a specific service provider interface (org.yarnandtail.andhow.AndHowInit in this case) and return instances of that service. Scanning all jars on the classpath for any classes implementing a specific interface is not easily or performantly possible; Scanning jars for the presence of a specific file is.

TLDR - AndHow is able to find your custom AndHowInit implementation anywhere on the classpath.

unfinished documentation. . .