Configuring AndHow
How to configure AndHow before AndHow configures you(r application)
Why would an application need to configure AndHow? There are several possible reasons:
To pass in command-line arguments
To use a custom name for the classpath andhow.properties file
To use a properties file on the filesystem (non-classpath), which requires configuring a file path
To add, remove or reorder the loaders that load Property values, or configure them
To set fixed values for some Properties (mostly done for testing)
AndHow Configuration can only happen before initialization
AndHow ensures that its state and Property values are immutable once initialized, so any attempt to modify AndHow's configuration after initialization results in a RuntimeException. How can you be sure your code to configure AndHow happens before initialization?
The AndHow.findConfig()
method
AndHow.findConfig()
methodAndHow.findConfig()
is the only way to access the configuration AndHow uses for itself. Until initialization, AndHow holds a reference to an AndHowConfiguration
instance that can be retrieved via AndHow.findConfig()
. All configuration happens via the AndHowConfiguration
instance, and after initialization the reference is gone.
The first time findConfig()
is called, AndHow scans the classpath for a class implementing AndHowInit
(or AndHowTestInit
). If an implementation exists, it's getConfiguration()
method is called to provide the AndHowConfiguration
instance. If no AndHowInit class exists, AndHow starts with a default StdConfig
instance. Later calls to findConfig()
return the same instance that was found or created in the first call.
As a first step of initialization, AndHow calls findConfig()
on itself so it initializes with the configuration that has been built up, created by default, or returned from the AndHowInit
class.
Configuring AndHow at a well defined entry point
The simplest way to ensure AndHow configuration happens before Properties are accessed is to have a well defined Entry Point. Common well defined entry points are:
The main method of application startup class
The
ServletContextListener.contextInitialized
method in a Servlet applicationThe
handle()
method of a lambda functionAny well documented init method that is invoked prior to all other application code
Generally a deployed application of GUI will have a well defined entry point, while a reusable utility library will not.
Configuration via the AndHowInit
interface
AndHowInit
interfaceAndHow will discover and use a class implementing AndHowInit
to configure itself, if it is present, so implementing that interface in your deployable application is the best way to configure AndHow. It ensures your configuration is always used and won't attempt to configure AndHow 'late', after it is already initialized. Example:
This example implements the AndHowInit
interface to add a new Loader to load "my.properties" from the classpath before the JNDI loader. No other code is required - AndHow will find this class during its initialization process and use the new loader.
Best Practice: Use an AndHowInit class to configure AndHow and include it with your deployable application, not a library or dependency
Only a single AndHowInit
class is allowed on the classpath, otherwise configuration would be ambiguous. Thus, don't bundle an AndHowInit class with a distributable library - it is only intended to be used with deployable apps.
If AndHow.findConfig()
calls AndHowInit.getConfiguration()
, doesn't it cause a loop when findConfig
is used inside that method??
Well, sure. Yes it would. To keep the API simple and make findConfig
the universal way to access configuration, AndHow detects the re-entrant call to findConfig and simply returns a new StdConfig.
Setting command line arguments
This is a common need and appears in so many examples that its easy to miss that this is actually an example of configurating AndHow.
AndHow can load values from most configuration sources automatically, however, it has no way to intercept the command line arguments passed to the main method - the application has to help. Here is modified version of HelloWorld, updated to load from the command line:
In the above example, we know that the only entry point is the main() method, so it is safe to configure AndHow at the top of that method.
findConfig()
is called and all the steps outlined above take place: If there is an AndHowInit
instance on the classpath, it will be used to supply an AndHowConfiguration
instance. If not, a default instance is created. Then, we supply the command line arguments to AndHow's configuration. When its time to initialize (which happens when we access a value on line 7), AndHow provides the command line arguments to a Loader
instance that knows how to parse key-value pairs from command-line.
Any attempt to call findConfig()
after line 7 would result in a RuntimeException because AndHow has already initialized.
Other examples of Configuring AndHow
There are two other common situations where you need to configuration AndHow:
Modifying the load order, customizing loaders, or adding new loaders is discussed in the Changing the Load Order section.
Setting fixed values is mostly done during testing.
Last updated
Was this helpful?