AndHow Properties
90% of using AndHow is creating and using Properties
Last updated
Was this helpful?
90% of using AndHow is creating and using Properties
Last updated
Was this helpful?
AndHow Properties are immutable constants in your code, except their value is loaded when your application starts up. They are always static final
and created with a builder() method:
Properties may be private
or public
, but they must be static final
and the compiler will enforce that. Getting the value of a Property is simple:
Properties are strongly typed (so IntProp
returns an Integer
) and there are Property types for most primitive types - see the next section.
Properties can...
be declared anywhere in code that a static final
variable can be declared. They do not need to be centralized into a configuration class. Best pactice is to declare them where you use them.
have constraints such as greaterThan(5)
(for a numeric type) or matches("regex expression")
(for a String), etc.
have configuration values loaded into them during application startup from a number of configuration sources - see the .
be null if no value if found for the property at startup, or may have a default value
AndHow has Properties to represent most common value types:
- String Property
- Boolean Property
- Integer Property
- Long Property
- Double Property
- BigDecimal Property
- LocalDateTime Property
- boolean Property (never null) that acts as a command line switch
All Property types basically behave the same way:
They parse the configured values they receive during application startup into the appropriate type.
If no configuration value is found, their value is null unless a default is specified.
If the value cannot be parsed to the appropriate type or does not meet the validation requirements defined in the Property declaration, the application startup is stopped with a runtime exception.
If code can see/access a Property, it can read its value
If code cannot see/access a Property, it cannot read its value
Properties always have a unique canonical name based on their logical path. A Property named MY_PROP
declared in the com.bigcorp.MyClass
has the canonical name com.bigcorp.MyClass.MY_PROP
. The same pattern continues with nested inner classes or interfaces.
Property names are case-insensitive, so com.bigcorp.MyClass.MY_PROP
is the same as COM.BiGcOrP.MyClaSS.my_prOP
.
Canonical Properties names are often good enough and will implicitly update when refactoring.
When AndHow loads values, CODE
's canonical name, pin and secret_pin will be recognized. If values are exported (such as to a Map to configure another framework), the canonical name, secret and secret_pin will all be names that could be used.
All Properties can have default values:
...But be careful! Its easy for a default value to end up in production. Some Properties have good defaults: report margin, retry counts or log level. Others do not: DB connection string, user name or password. If a Property has no value that is acceptable in all environments, its better to not specify a default and rely on configuration to supply the value.
Don't use a default value for local workstation or test environment configuration values.
Properties can have validation, description, defaults, and more. Rather than attempt to describe them all, see the examples below.
AndHow Properties work like static final variables whose value is assigned at startup. This is true in amost all situations except one: A Property's getValue()
method cannot be called inside a static initializer block. Doing so will cause a startup error that AndHow will tell you about.
A Group is just the AndHow term for the class or interface containing Properties. Some AndHow operations and annotations apply to Groups, as you will see in the examples below.
Properties and Groups can have description to help make code self-documenting. AndHow uses all the Property metadata to generate rich configuration templates for your Properties, as in the 2nd tab. The template serves as both documentation and an initial configuration file, and is created when startup fails due to validation error, or it can be run manually by setting the built-in org.yarnandtail.andhow.Options.CREATE_SAMPLES
to true, e.g.:
-D
sets a Java system property and AHForceCreateSamples
is an In alias for CREATE_SAMPLES
, as you can see at the bottom of the configuration template. It is also a 'flag' property (FlagProp
), so just being present is enough to set it true, similar to other command line switches.
The 3rd tab shows example error messages for invalid configuration values. These informative messages would be part of a RuntimeException
, thrown to prevent startup with invalid configuration.
Just like constants, Properties can (and should) be declared where they are be used to create natural scope: If a secret is only needed by one class, don't make it visible to the entire application. Avoid placing Properties in a central 'Config' class.
Place related sets of Properties in nested interfaces.
The Properties in the example above configure a Report class, and related Properties have been nested into interfaces. This creates logical, canonical names for Properties: The purpose of ZIP is easy to understand when it's inside Report.Filter.
Nesting into interfaces also takes advantage of the Java language to save some typing: Variables declared in an interface are implicitly static final
. (Note: Java 11+ is required to use a private interface as in the example)
One exception to this general behavior is the FlagProp
. The FlagProp behaves similar to an on/off switch, thus it is never null and always returns true
or false
from getValue()
. Additionally, the FlagProp behaves like a 'nix flag when used on the command line - see the example in the .
Property.getValue()
is the only way to get a Property's value (other than ), so the visibility of the Property controls access:
Reflection can bypass visibility (except ) and code can read environment vars and other sources, but many other configuration solutions result in all configuration being effectively public. AndHow Properties let you scope configuration to the classes that need it.
During , AndHow will automatically load Property values from multiple configuration sources. Once complete, Property values will not change for the run-life of the application.
Properties may have In and Out aliases. In aliases are recognized when loading values, in addition to canonical names. Out aliases are alternate names that can be used when . Properties may have multiple In and Out aliases:
In aliases are useful for Properties that need to be specified from command line, or to match an already existing set of configuration files / sources. Out aliases are useful for to other frameworks or legacy applications that expect specific key names.
As you will see in the , its easy to use separate test configurations. Its also easy to provide local and tier specific configuration (TDB: Write this section).