# AndHow!

Java application configuration

### Configurable constants for Java application configuration

**New Release: 1.5.0, October 10, 2020 -** [**notes**](/release-notes)**.**

This release jumps from 0.4.2 to 1.5.0, reflecting that AndHow has been in production long enough to be considered production ready, and includes some API changes. This release removes deprecated methods, clarifies / subtly changes some behavior, and has general improvements and bug fixes. See the full[ release notes](/release-notes).

![](https://2281660175-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkItIobWMJCrFRNX6Iw%2Fuploads%2FFlND5LiNNe6bPjnkWV2B%2Fandhow_0.5_1280x320_highres_24fps.gif?alt=media\&token=83801760-2fbf-43bc-aae8-e0601b4ee5fb)

### What if you could configure constants? What if Java application configuration was just constants?

AndHow configures your application with strongly typed Properties that work just like `static final` constants in your code. Values for Properties are loaded from multiple sources and are validated at startup.

#### Key Features

* **Strong Typing**
* **Detailed validation**
* **Simple to use and test**
* **Use Java `public` & `private` modifiers to control Property value access**
* **Validates&#x20;*****all*****&#x20;property values at startup to** [***Fail Fast***](https://www.andhowconfig.org/pages/-MkJ0Cr4uXGfwvdK3zRP#andhow-fails-fast...-and-that-is-a-good-thing)
* **Loads values from multiple sources (env. vars, system props, cmd line, prop files, JNDI, and more)**
* **Generates configuration template files for the Properties in your application**

#### Use it via Maven (available on Maven Central)

```xml
<dependency>
    <groupId>org.yarnandtail</groupId>
    <artifactId>andhow</artifactId>
    <version>1.5.0</version>
</dependency>

<dependency>
	<!-- Utils for unit testing apps using AndHow -->
	<groupId>org.yarnandtail</groupId>
	<artifactId>andhow-junit5-extensions</artifactId>
	<version>1.5.0</version>
	<scope>test</scope>
</dependency>
```

#### Declaring and Using AndHow Properties

Declaring Properties looks like this:

```java
private static final StrProp HOST = StrProp.builder().startsWith("internal.").build();
public static final IntProp PORT = IntProp.builder().defaultValue(80).build();
```

Using Properties looks like this:

```java
String theHost = HOST.getValue();
int thePort = PORT.getValue();
```

`StrProp` & `IntProp` are AndHow `Property`s. Properties and their values are constants, so they are always declared as `static final`, but may be `private` or any scope. Properties may have default values, validation rules, description, and more.

Properties are used just like static final constants with `.getValue()` tacked on. They are ***strongly typed***, so `HOST.getValue()` returns a `String`, `PORT.getValue()` returns an `Integer`.

At startup, AndHow scans System.Properties, environment variables, JNDI values, the *andhow\.properties* file, etc., in a [well established order](/user-guide/loaders-and-load-order#default-configuration-source-loading-order). If the loaded value for any Property in the application does not meet the validation requirements, AndHow throws a detailed `RuntimeException` to [fail fast](https://www.andhowconfig.org/pages/-MkJ0Cr4uXGfwvdK3zRP#andhow-fails-fast...-and-that-is-a-good-thing) and prevent the application from running with invalid configuration.

### Where to next?

[Live-Code Quickstart](/live-code-quickstart) will get you started with AndHow right in the browser window.\ <br>

***&?!***


# Live-Code Quickstart

Get started by trying live code examples in Replit

Let's get started!  Below is a live demo REPL that is ready to run five simple demos.  Go ahead and click the Green run button.

{% embed url="<https://replit.com/@EricEverman/AndHowHelloWorld?lite=true>" %}

{% tabs %}
{% tab title="Overview" %}
*If you haven't already, go ahead and click the green run button* <img src="https://2281660175-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkItIobWMJCrFRNX6Iw%2Fuploads%2FDb1LhgbSfW2z0rKyuq8e%2Fgreen%20run%20button.png?alt=media&amp;token=97649567-2d0b-406e-8409-44629267dfed" alt="" data-size="line"> *at the top of the* REPL *window above.*

Running this REPL compiles a small AndHow example, then runs it five times with different configurations.  Take a look at the `Main` class:  It contains two AndHow Properties, `NAME` & `REPEAT_COUNT`. The values of these two Properties are used to print to System.out in the main method.

There is also an ***andhow\.properties*** file - click the file icon <img src="https://2281660175-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkItIobWMJCrFRNX6Iw%2Fuploads%2FVOgMgdxoTjXiWLcLCYiX%2FScreen%20Shot%202021-10-23%20at%209.12.14%20PM.png?alt=media&amp;token=1ac11a9b-6d91-45e9-bf49-346cc5b73503" alt="" data-size="line"> on the left to see the list of files.  The file has a value for both Properties.  (You can click the file icon again to make the list go away).

**Continue on to the Run 1 tab. . .**

{% hint style="info" %}
This REPL is hosted by Repl.it.  You can work on the Console or the Shell without logging in, but you need to login with a free accont to work on a fork to modify code or files.

If you try to run commands on the console and get an error like this:

`Error: Could not find or load main class Main Caused by: java.lang.ClassNotFoundException: Main`

Your VM has timed out - Just click the green run button again to rebuild everything.
{% endhint %}
{% endtab %}

{% tab title="Run 1" %}
*You probably have to scroll back up to the top of the black **Console** window, above, to see the output of Run 1.*

#### Run 1 prints:  <mark style="color:blue;">Hello, Dawn! Hello, Dawn!</mark>

AndHow found and loaded the values for the two Properties from the ***andhow\.properties*** file as soon as the code tried to access a Property value (`Main` line 13).  By default, AndHow will always attempt to read property values from that file.

The command in yellow:

<mark style="color:yellow;">**java -cp .:target/dependency/\*:target/classes Main**</mark>

...is the command that ran this example.  You can copy and paste it in the console and run it again.  Clicking the green run button will compile the code and run all four examples again - you don't need to click the run button again unless you want to see the whole thing run again.

**Continue on to the Run 2 tab, and so on. . .**
{% endtab %}

{% tab title="Run 2" %}

#### Run 2 prints:  <mark style="color:blue;">Hello, Darcey! Hello, Darcey!</mark>

In this example, an environment variable named *Main.NAME* is set to *Darcey* and the `java` command is run with that variable set.

AndHow scans the environment variable names for any that match a Property and assigns *Darcey* to the `NAME` Property.  For AndHow, env. vars. take precidence over values from property files, so *Darcey* is used instead of *Dawn.*  The REPEAT\_COUNT value of 2 is still taken from the properties file.

AndHow has a [well defined priority order of configuration sources](/user-guide/loaders-and-load-order) that works for most situations and the ability to [change the order](/user-guide/changing-the-load-order) if needed.
{% endtab %}

{% tab title="Run 3" %}

#### Run 3 prints:  <mark style="color:blue;">Hello, Dave! Hello, Dave!</mark>

This time NAME is set as a java system property via the `-D` argument.  AndHow can read configuration from many different sources.
{% endtab %}

{% tab title="Run 4" %}

#### Run 4 prints:  <mark style="color:blue;">Hello, Demi! Hello, Demi!</mark>

The java command arguments after the class name are passed to the main(String\[] args) method.  The main method includes this bit of code:

```java
AndHow.findConfig().setCmdLineArgs(args);
```

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 by passing them to AndHow.  Read more about how [findConfig()](https://www.andhowconfig.org/pages/2zA6uJaAKhroeaI7Sfot#the-andhow.findconfig-method) works.
{% endtab %}

{% tab title="Run 5" %}

#### Run 5 uses a system property to set NAME to an invalid value

`NAME` in the `Main` class is built with **`startsWith("D")`** - It must start with D as all the examples have done.  What happens if that rules is broken?

This example was saved for you to run.  Copy and paste the yellow comand in the console window:

<mark style="color:yellow;">**java -cp .:target/dependency/\*:target/classes -DMain.NAME=Bob Main**</mark>

...Did you run it?

AndHow validates all configuration values at startup and throws a `RuntimeExcpetion` to [fail fast](https://www.andhowconfig.org/pages/-MkJ0Cr4uXGfwvdK3zRP#andhow-fails-fast...-and-that-is-a-good-thing) and prevent an application from running with invalid configuration.  The validation errors and messages AndHow gives are very specific:

`Property Main.NAME loaded from java.lang.System.getProperties(): The value 'Bob' must start with 'D'`

It tells us where the value was loaded from and exactly what validation rule the potential configuration value broke.  It also includes a message like this:

<mark style="color:red;">`A set of sample configuration files will be written to '/tmp/andhow-samples/'`</mark>

When a startup error happens, AndHow helpfully creates *configuration templates*.  These templates are rich and detailed files that serve as documentation for application configuration and a starting point for creating a properties configuration file.  You can list and view the contents in the console:

```bash
ls /tmp/andhow-samples/     (your path may be different)
  - JNDI.xml
  - PropertyFile_KeyValuePair.properties
more /tmp/andhow-samples/PropertyFile_KeyValuePair.properties
```

Here is a portion from the PropertyFile\_KeyValuePair.properties file - a template file you can use to create your own andhow\.properties file:

```properties
# 
# NAME (String) NON-NULL
# The property value must start with 'D'
Main.NAME = 

# 
# REPEAT_COUNT (Integer) NON-NULL
# The property value must be less than 5
Main.REPEAT_COUNT = 
```

{% endtab %}
{% endtabs %}

### Where to go next

The [User Guide](/user-guide) has a suggested learning path - Happy trails!

***&?!***


# Simple Usage Examples

This page does some walk-throughs of simple code examples.  You might try the [Live-Code Quickstart](/live-code-quickstart) to try using AndHow right in the browser.  The Live-Code is more fun, but this page is much more comprehensive.

## Complete Usage Example

```java
package simple;
import org.yarnandtail.andhow.property.*;

public class HelloWorld {

  // 1 Declare AndHow Properties
  private static final StrProp NAME = StrProp.builder().defaultValue("Dave").build();
  public static final IntProp REPEAT_COUNT = IntProp.builder().defaultValue(2).build();

  public static void main(String[] args) {

    // 2 Use AndHow Properties
    for (int i = 0; i < REPEAT_COUNT.getValue(); i++) {
      System.out.println("Hello, " + NAME.getValue());
    }
  }
}
```

[>> Complete code <<](https://github.com/eeverman/andhow-samples/blob/homepage/01-hello-world/src/main/java/simple/HelloWorld.java)

### // 1 : Declare AndHow Properties

`StrProp` & `IntProp` are AndHow `Property`s. Properties and their values are constants, so they are always `static final` but may be `private` or any scope. Properties are ***strongly typed***, so their value, default value and validation are type specific.

### // 2 : Using AndHow Properties

Properties are used just like static final constants with `.getValue()` tacked on: `NAME.getValue()` returns a `String`, `REPEAT_COUNT.getValue()` returns an `Integer`.

The Properties in the example have defaults, so with no other configuration, running `HelloWorld.main()` will print **`Hello, Dave`** twice. One way (of many) to configure values is to add an `andhow.properties` file on the classpath like this:

```
# andhow.properties file at the classpath root

simple.HelloWorld.NAME: Kathy
SIMPLE.HELLOWWORLD.repeat_count: 4
```

Resulting in **`Hello, Kathy`** x4 - AndHow ignores capitalization when reading Property values. Unlike most configuration utilities, we didn't have to specify a 'name' for NAME. AndHow builds a logical name for each property by combining the canonical name of the containing class with the variable name, e.g.:\
&#x20;`[Java canonical class name].[AndHow Property name]` --> `simple.HelloWorld.NAME`\
&#x20;Thus, naming isn't something you have to worry about and Java itself ensures name uniqueness. Let's extends this example a bit...

## Adding validation and command line arguments

```java
package simple;  // Imports left out for simplicity

public class HelloWorld2 {

  // 1 Declare
  private static interface Config {
    StrProp NAME = StrProp.builder().mustStartWith("D").defaultValue("Dave").build();
    IntProp REPEAT_COUNT = IntProp.builder()mustBeGreaterThan(0)
      .mustBeLessThan(5).defaultValue(2).build();
  }

  public static void main(String[] args) {

    AndHow.findConfig().setCmdLineArgs(args);  //2 Add cmd line arguments

    // Use
    for (int i = 0; i < Config.REPEAT_COUNT.getValue(); i++) {
      System.out.println("Hello, " + Config.NAME.getValue());
    }
  }
}
```

[>> Complete code <<](https://github.com/eeverman/andhow-samples/blob/homepage/02-hello-world-better/src/main/java/simple/HelloWorld2.java)

### // 1 : Declare AndHow Properties with validation

`Property` values can have validation. At startup, AndHow ***discovers and validates all Properties in your entire application***, ensuring that a mis-configuration application [*fails fast*](https://www.martinfowler.com/ieeeSoftware/failFast.pdf) at startup, rather than mysteriously failing later.

Placing `Property`'s in an interface is best practice for organization and access control. Only code able to 'see' a `Property` can retrieve its value - standard Java visibility rules. Fields in an interface are implicitly `static final`, saving a bit of typing.

### // 2 : Add command line arguments

AndHow loads Property values from several configuration sources in a [well established order](https://sites.google.com/view/andhow/user-guide/value-loaders). At startup, AndHow scans `System.Properties`, environment variables, JNDI values, the `andhow.properties` file, etc., automatically.

Reading from commandline requires a bit of help from the application. The code `AndHow.findConfig().setCmdLineArgs(args);` passes the command line arguments in to AndHow.

Running from cmd line to set `NAME` to 'Dar' would look like this:

```bash
  java -Dsimple.HelloWorld2.Config.NAME=Dar -cp [classpath] simple.HelloWorld2
```

What happens if we try to set NAME to "Bar" and violate the 'D' validation rule? AndHow throws a `RuntimeException` to stop app startup and prints a clear message about the cause:

```
================================================================================
== Problem report from AndHow!  ================================================
================================================================================
Property simple.HelloWorld2.Config.NAME loaded from string key value pairs:
  The value 'Bar' must start with 'D'
================================================================================
A configuration template for this application has been written to: [...tmp file location...]
```

AndHow uses Property metadata to generate precise error messages. When errors prevent startup, AndHow also creates a *configuration template* with all your application's `Property`s, validation requirements, types, defaults and more. Here is what that would look like for this app:

```
==/==/==/==/==/== Excerpt from a configuration template ==/==/==/==/==/==
# NAME (String)
# Default Value: Dave
# The property value must start with 'D'
simple.HelloWorld2.Config.NAME = Dave

# REPEAT_COUNT (Integer)
# Default Value: 2
# The property value must be less than 5
simple.HelloWorld2.Config.REPEAT_COUNT = 2
```

You can create a configuration template on demand by setting the `AHForceCreateSamples` flag:  `java -DAHForceCreateSamples=true -cp [classpath] simple.HelloWorld2`

Let's look at a larger, more enterprise-y example.

## Example with a database connection, aliases and exports

In this example, assume we need to configure an ORM framework like [Hibernate](http://hibernate.org). 3rd party frameworks have their own configuration property names and typically accept properties as a `Map` or `util.Properties`. This example is in two parts: A Handler class which might be an AWS Lambda, and a DAO (Data Access Object) which stores data to a DB using Hibernate.

```java
package simple;  // Both classes are in 'simple'.  Imports left out for simplicity.

public class SaleHandler {

  // 1 Declare configuration Property's for this class
  public static interface Config {
    BigDecProp TAX_RATE = BigDecProp.builder().mustBeGreaterThan(BigDecimal.ZERO)
        .mustBeNonNull().desc("Tax rate as a decimal, eg .10").aliasIn("tax").build();
  }

  public Object handle(BigDecimal saleAmount) throws Exception {

    // TAX_RATE.getValue() returns a BigDecimal
    BigDecimal tax = saleAmount.multiply(Config.TAX_RATE.getValue());
    return new SaleDao().storeSale(saleAmount.add(tax));
  }
}
```

[>> Complete code <<](https://github.com/eeverman/andhow-samples/blob/homepage/99-larger-example/src/main/java/simple/SaleHandler.java)

### // 1 : Declare configuration Property's for this class

AndHow best practice: ***Place Properties in the class that uses them***.  This makes intuitive sense and there is no need to gather them all into a central *Config* class - AndHow will find, load and validate them all ***and*** create a configuration template listing them all.

The `TAX_RATE` Property uses `.aliasIn("tax")`, which adds an alternate name recognized when reading this property from a configuration source. Handy for values that may need to be specified on cmd line.

Lets look at how the DAO class uses AndHow:

```java
public class SaleDao {

  // 2 Declare DB connection Properties
  @ManualExportAllowed
  private static interface Db {
    StrProp URL = StrProp.builder().mustStartWith("jdbc://").mustBeNonNull()
        .aliasInAndOut("hibernate.connection.url").build();
    StrProp PWD = StrProp.builder().mustBeNonNull()
        .aliasInAndOut("hibernate.connection.password").build();
  }

  // 3 Export Db properties to java Properties instance
  java.util.Properties getExportedConfig() throws Exception {
    Properties props = AndHow.instance().export(Db.class)
        .collect(ExportCollector.stringProperties(""));

    return props;
  }

  // Pretend database storage call
  Object storeSale(Object sale) throws Exception {
    Hibernate h = new Hibernate(getExportedConfig());
    return h.save(sale);
  }
}
```

[>> Complete code <<](https://github.com/eeverman/andhow-samples/blob/homepage/99-larger-example/src/main/java/simple/SaleDao.java)

### // 3 : Declare DB connection Properties

The Properties bundled together in `Db` are annotated with `@ManualExportAllowed`, allowing them to be exported to a `Map` or other structure. `.aliasInAndOut()` adds an *in* name just like 'tax' above, but the name is also used when exporting (out).

### // 4 : Export Db properties to a java.util.Properties instance

Property exports use the Java `stream()` API. Exports are done at the class level: `AndHow.instance().export(class...)` specifies one or more `@ManualExportAllowed` annotated classes containing AndHow Properties. `ExportCollector` has collectors to turn a stream of Properties into collections: `ExportCollector.stringProperties("")` turns AndHow Properties into `java.util.Properties` with String values (using "" for null values).

Since we specified alias *out* names for the Db Properties, the *Hibernate* compatible aliases are used for the export. AndHow provides validation at startup, configuration from multiple sources, and more... and can do that for 3rd party frameworks!

## Testing Applications with AndHow

AndHow makes testing with multiple configurations easy. Let's test the `SaleHandler` from above and assume an \`andhow\.properties' file like this:

```
simple.SaleDao.Db.PWD = changeme
simple.SaleDao.Db.URL = jdbc://mydb
simple.SaleHandler.Config.TAX_RATE = .11
```

We can verify the tax rate is set as expected:

```java
  @Test  //This verifies that the tax rate is .11 from the andhow.properties file
  public void defaultConfigTaxRateShouldBe_11Percent() throws Exception {
    SaleHandler handler = new SaleHandler();

    // Total sale should be 10.00 + (10.00 * .11)
    assertEquals(new BigDecimal("11.10"), handler.handle(BigDecimal.TEN));
  }
```

Now lets test the handler with the tax rate configured to 12%:

```java
  @Test @KillAndHowBeforeThisTest  // 1 'Kill' the current AndHow configuration
  public void verifyTaxRateAt_12Percent() throws Exception {

    // 2 Set a new configured value for TAX_RATE
    AndHow.findConfig().addFixedValue(SaleHandler.Config.TAX_RATE, new BigDecimal(".12"));

    SaleHandler handler = new SaleHandler();

    // Total sale should be 10.00 + (10.00 * .12)
    assertEquals(new BigDecimal("11.20"), handler.handle(BigDecimal.TEN));
  }  // 3 Cleanup after the test
```

[>> Complete code <<](https://github.com/eeverman/andhow-samples/blob/homepage/99-larger-example/src/test/java/simple/SaleHandlerTest.java)

### // 1 : 'Kill' the current AndHow configuration

The annotation `@KillAndHowBeforeThisTest` erases AndHow's state before the test.

### // 2 : Set a new configured value for TAX\_RATE

`AndHow.findConfig()` grabs the configuration of AndHow itself to add a 'fixed value' for `TAX_RATE`, ignoring any other configured value for that property.

### // 3 : Cleanup after the test

The tax rate is `.12` just for this test. When the test is done, AndHow is restored to its previous state. This isn't allowed in production: Remember, ***AndHow Property values are constant and once initialized at startup, do not change***. The `@KillAndHow...` annotation uses reflection to bend the rules to make testing easy.

***&?!***


# User Guide

### First time here?

Before diving into the docs, you may want to try out the [Live-Code Quickstart](/live-code-quickstart) to try out AndHow right in the browser window.

If you are ready to move on from that, here is a suggested learning path:

* [Key Concepts](/user-guide/key-concepts) - Key points to know about what AndHow is and does
* [AndHow Properties](/user-guide/andhow-properties) - 90% of using AndHow is creating and using Properties
* [Loaders & Load Order](/user-guide/loaders-and-load-order#default-configuration-source-loading-order) - The first section contains the order AndHow loads values from configuration sources
* [Best Practices](/user-guide/best-practices) - Get the most out of AndHow and your application

After that, try incorporating AndHow into a project, or fork one of the [sample projects](https://github.com/eeverman/andhow-samples). &#x20;

Two other user guide sections are foundational, but can be read after you've had some time to work with AndHow:

* [AndHow Initialization](/user-guide/andhow-initialization) - How AndHow startup up, configures itself, and your application
* [Configuring AndHow](/user-guide/configuring-andhow) - How to configure AndHow before AndHow configures you(r application)

Other sections of the user guide are reference.


# Key Concepts

Key points to know about what AndHow is and does

### AndHow Properties are configurable constants

AndHow [Properties](/user-guide/andhow-properties) are constants in your code, except their value is loaded when your application starts up.  Once loaded during [initialization](/user-guide/andhow-initialization), Property values are immutable and will not change for the run-life of the application.

### AndHow initializes and loads property values only once at startup

[Initialization](/user-guide/andhow-initialization) is AndHow's startup/bootstrap process where it discovers all Properties in your application, scans multiple configuration sources to load values for them, and validates them.  This will only happen once in the run-lifecycle of the application and once completed, the list of Properties and their values will never change.

### AndHow Fails Fast... and that is a good thing

AndHow detects invalid configuration at startup to [*fail fast*](https://www.martinfowler.com/ieeeSoftware/failFast.pdf).

*Failing late* is the alternative.  Failing late might mean that a misconfigured application runs for a few days, then mysteriously fails when a misconfigured feature is first used  ***\~BOOM\~*** You'll get the call in the middle of the night.  Wouldn't it have been nice to see that error at startup? &#x20;

### Property Names are CaSe InSeNsItIvE

For compatibility with Windows environment variable names, property names are case insensitive.  Proper case names are still used internally for reporting and when creating configuration sample files.  One exception to this is JNDI, which is inherently case sensitive.&#x20;

### Null Handling

AndHow does not have an explicit null value.  If a Property is not set, it is null unless it has a default value.

### Configuration Sources and Loaders

AndHow uses Loaders to load Property values from configuration sources such as System.Properties, environment variable, system properties, JNDI, properties files, etc..  Loaders work on a 'first win' basis:  The first loader to find a non-null for a Property sets the value. &#x20;

Thus, the loader order is significant and [well established](https://sites.google.com/d/1iteScRrSeAtJUnD-3ELYLFaGiQLdAmSP/p/1iPp60twwW_ABWH21-K2Z4p7BzEf8voZV/edit).  The standard Loader order will work for most applications, but if needed, [the load order can be changed](https://sites.google.com/d/1iteScRrSeAtJUnD-3ELYLFaGiQLdAmSP/p/1iFKkeYm4n_NHklIL9xkbf2Y6iMs7iauY/edit), loaders removed and other loaders added.


# AndHow Properties

90% of using AndHow is creating and using Properties

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:

```java
private static final IntProp MY_CONST_INT = IntProp.builder().build();
```

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:

```java
Integer theValue = MY_CONST_INT.getValue();
```

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 [Loaders](/user-guide/loaders-and-load-order).
* be null if no value if found for the property at startup, or may have a default value

#### Property Types

AndHow has Properties to represent most common value types:

* [StrProp](https://github.com/eeverman/andhow/blob/homepage/andhow-core/src/main/java/org/yarnandtail/andhow/property/StrProp.java) - String Property
* [BolProp](https://github.com/eeverman/andhow/blob/homepage/andhow-core/src/main/java/org/yarnandtail/andhow/property/BolProp.java) - Boolean Property
* [IntProp](https://github.com/eeverman/andhow/blob/homepage/andhow-core/src/main/java/org/yarnandtail/andhow/property/IntProp.java) - Integer Property
* [LngProp](https://github.com/eeverman/andhow/blob/homepage/andhow-core/src/main/java/org/yarnandtail/andhow/property/LngProp.java) - Long Property
* [DblProp](https://github.com/eeverman/andhow/blob/homepage/andhow-core/src/main/java/org/yarnandtail/andhow/property/DblProp.java) - Double Property
* [BigDecProp](https://github.com/eeverman/andhow/blob/homepage/andhow-core/src/main/java/org/yarnandtail/andhow/property/BigDecProp.java) - BigDecimal Property
* [LocalDateTimeProp](https://github.com/eeverman/andhow/blob/homepage/andhow-core/src/main/java/org/yarnandtail/andhow/property/LocalDateTimeProp.java) - LocalDateTime Property
* [FlagProp](https://github.com/eeverman/andhow/blob/homepage/andhow-core/src/main/java/org/yarnandtail/andhow/property/FlagProp.java) - 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.

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 [StdMainStringArgsLoader](/user-guide/loaders-and-load-order#arguments-passed-to-main-string-args).

#### Property value access and security

`Property.getValue()` is the only way to get a Property's value (other than [exports](/user-guide/integration-and-exports)), so the visibility of the Property controls access:

* If code can see/access a Property, it can read its value
* If code cannot see/access a Property, it cannot read its value

Reflection can bypass visibility (except [non-open modules in JDK 9+](https://www.andhowconfig.org/user-guide/pages/xOR1SztN6mIX65z7wNsE#h.svhszcj4r7f-1)) 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.

#### Properties and their values are immutable

During [initialization](/user-guide/andhow-initialization), AndHow will automatically load Property values from multiple configuration sources.  Once complete, Property values will not change for the run-life of the application.

#### Property Names

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`.

{% hint style="info" %}

#### Best Practice: Don't worry about Property names unless you have to

Canonical Properties names are often good enough and will implicitly update when refactoring.
{% endhint %}

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 [exporting](/user-guide/integration-and-exports).  Properties may have multiple *In* and *Out* aliases:

```java
LngProp CODE = LngProp.builder().aliasIn("pin")
	.aliasOut("secret").aliasInAndOut("secret_pin").build();
```

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.

*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 [exporting](/user-guide/integration-and-exports) to other frameworks or legacy applications that expect specific key names.

#### Default Values

All Properties can have default values:

```java
IntProp RETRY_CNT = IntProp.builder().defaultValue(1).build();
```

...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.

{% hint style="info" %}

#### Best Practice: Use a default value when there is a good business-related default

Don't use a default value for local workstation or test environment configuration values.
{% endhint %}

As you will see in the [testing section](/user-guide/testing), its easy to use separate test configurations.  Its also easy to provide local and tier specific configuration (TDB:  Write this section).

#### Properties have lots of configuration options

Properties can have validation, description, defaults, and more.  Rather than attempt to describe them all, see the examples below.

#### Properties behave like static finals except...

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.

### Groups

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.

### Property Example 1

{% tabs %}
{% tab title="Sample Properties" %}

```java
package org.example;

import org.yarnandtail.andhow.GroupInfo;
import org.yarnandtail.andhow.property.*;

public class TransactionManager {

	@GroupInfo(name="Connection Config", 
		desc = "Config's an http service connection")
	interface Connection {
		StrProp BASE_URL = StrProp.builder().notNull()
			.aliasIn("url").startsWith("http://").endsWith("/")
			.desc("Base url for a service request").build();
		IntProp RETRY_CNT = IntProp.builder().defaultValue(1)
			.aliasIn("retry").aliasIn("retry_cnt")
			.greaterThanOrEqualTo(0).lessThan(10)
			.desc("# of request retries. 0 = no retry.").build();
	}

}
```

{% endtab %}

{% tab title="Auto-Generated Configuration Template" %}

```properties
# ##########################################################################################
# Sample properties file generated by AndHow!
# strong.simple.valid.AppConfiguration  -  https://github.com/eeverman/andhow
# ##########################################################################################

# ##########################################################################################
# Property Group 'Connection Config' - Config's an http service connection.
# Defined in org.example.TransactionManager.Connection

# 
# BASE_URL (String) NON-NULL - Base url for a service request
# Recognized aliases: url
# The property value must:
# - start with 'http://'
# - end with '/'
org.example.TransactionManager.Connection.BASE_URL = 

# 
# RETRY_CNT (Integer)  - # of request retries.  0 = no retry.
# Recognized aliases: retry, retry_cnt
# Default Value: 1
# The property value must:
# - be greater than or equal to 0
# - be less than 10
org.example.TransactionManager.Connection.RETRY_CNT = 

# #### /snip/ ####

# CREATE_SAMPLES (Boolean) NON-NULL - Forces configuration samples to be sent to the
# 	console for each loader that supports it.
# Recognized aliases: AHForceCreateSamples
# Default Value: false
# On cmdline, this works as a flag and is assumed 'true' just by being present. In other
# 	config sources it can be set to 'true'.
# org.yarnandtail.andhow.Options.CREATE_SAMPLES = 
```

{% endtab %}

{% tab title="Validation Errors" %}
Attempting to load invalid values from the *andhow\.properties* file generates specific error messages:

```properties
Detailed list of Value Problems:
Property org.example.TransactionManager.Connection.BASE_URL loaded from file on classpath at:
  /andhow.properties: The value 'http://server.com' must end with '/'
Property org.example.TransactionManager.Connection.RETRY_CNT loaded from file on classpath at:
  /andhow.properties: The value '22' must be less than 10
```

{% endtab %}
{% endtabs %}

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.:

```
java -DAHForceCreateSamples MyMainClass
```

`-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.

### Property Example 2

{% tabs %}
{% tab title="Sample Properties" %}

```java
package org.example;

import org.yarnandtail.andhow.GroupInfo;
import org.yarnandtail.andhow.property.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;

public class ReportGenerator {

	@GroupInfo(name="Record filter", desc="Filters are AND'ed together")
	private interface Filter {
		StrProp REGION = StrProp.builder()
			.oneOfIgnoringCase("EAST", "WEST").build();
		StrProp ZIP = StrProp.builder().matches("\\d{5}(\\-\\d{4})?")
			.desc("Zipcode w optional plus 4 (12345 or 12345-1234)").build();
		LocalDateTimeProp START_TIME = LocalDateTimeProp.builder()
			.defaultValue(LocalDateTime.parse("2010-01-01T00:00"))
			.desc("Include records after this date-time").build();
		BigDecProp MIN_SALE = BigDecProp.builder()
			.defaultValue(BigDecimal.TEN).greaterThanOrEqualTo(BigDecimal.ZERO)
			.desc("Min sale amount to include").build();
	}

	private interface Format {
		DblProp MARGIN = DblProp.builder().defaultValue(1d)
			.greaterThan(.25d).desc("Margin in inches").build();
		BolProp WITH_HEADERS = BolProp.builder().defaultValue(true).build();
	}
}
```

{% endtab %}

{% tab title="Auto-Generated Configuration Template" %}

```properties
# ##########################################################################################
# Property Group 'Record filter' - Filters are AND'ed together.
# Defined in org.example.ReportGenerator.Filter

# 
# MIN_SALE (BigDecimal)  - Min sale amount to include
# Default Value: 10
# The property value must be greater than or equal to 0
org.example.ReportGenerator.Filter.MIN_SALE = 

# 
# REGION (String)
# The property value must be equal to one of '[EAST, WEST]' ignoring case
org.example.ReportGenerator.Filter.REGION = 

# 
# START_TIME (LocalDateTime)  - Include records after this date-time
# Default Value: 2010-01-01T00:00
org.example.ReportGenerator.Filter.START_TIME = 

# 
# ZIP (String)  - Zipcode w optional plus 4 (12345 or 12345-1234)
# The property value must match the regex expression '\d{5}(\-\d{4})?'
org.example.ReportGenerator.Filter.ZIP = 

# ##########################################################################################
# Property Group org.example.ReportGenerator.Format

# 
# MARGIN (Double)  - Margin in inches
# Default Value: 1.0
# The property value must be greater than 0.25
org.example.ReportGenerator.Format.MARGIN = 

# 
# WITH_HEADERS (Boolean)
# Default Value: true
org.example.ReportGenerator.Format.WITH_HEADERS = 
```

{% endtab %}
{% endtabs %}

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.&#x20;

{% hint style="info" %}

#### Best Practice: Declare properties in the class or interface where they are used

Place related sets of Properties in nested interfaces.
{% endhint %}

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)


# Loaders & Load Order

The order AndHow uses to scan configuration sources for property values, and the Loaders used to load from each source.

## Default configuration source loading order

The default order AndHow scans configuration sources for `Property` values is listed below.  Property values are set on a **first win basis**, so the first, non-null value found for a Property will be its value.

1. **Fixed Values - Values set in code during initiation**
2. **Arguments passed to main(String\[] args)**
3. **System Properties**
4. **Environmental Variables**
5. **JNDI values**
6. **Properties file on the filesystem (path requires configuration)**
7. **Properties file on the classpath (defaults to /andhow\.properties)**

This is just the default source load order, but it works for most applications.  Its easy to [change the load order or add custom loaders](/user-guide/changing-the-load-order).

## Configuration sources and the `Loader`s that load them <a href="#h.p_3b5dwoj1idkj" id="h.p_3b5dwoj1idkj"></a>

Each configuration source is handled by a different [`Loader`](https://github.com/eeverman/andhow/blob/homepage/andhow-core/src/main/java/org/yarnandtail/andhow/api/Loader.java) class, each of which has slightly different behaviours related to the source it is reading from.

### **Fixed Values - Values set in code during initiation**

Loaded by: [`StdFixedValueLoader`](https://github.com/eeverman/andhow/blob/homepage/andhow-core/src/main/java/org/yarnandtail/andhow/load/std/StdFixedValueLoader.java)

The fixed value loader is used to set values directly in code.

#### Typical Use Case

Since this loader receives values directly assigned from your code, it is only useful for creating application test configurations. Configuration values can be set directly prior to running a test so an application can be tested in a specific configured state. Since this is the first loader, a property value set by this load will override configuration values found by any other loader.

#### Basic Behaviors

* Trims String values: **No** - Since values are set in code, white-space is assumed to be correct
* Complains about unrecognized properties: **Yes** - See code example below

#### Loader Details and Configuration

One simple way to set fixed values is shown below. AndHow will discover this class implementing the AndHowInit interface during initialization to read your configuration:

```java
import org.yarnandtail.andhow.*;

public class SetFixedValues implements AndHowTestInit {
    @Override
    public AndHowConfiguration getConfiguration() {
        return AndHow.findConfig()
            .addFixedValue(MY_PROP, "some value")
            .addFixedValue("org.myapp.MyClass.PhaserLevel", "Stun");
    }
}
```

The code above is an example of an `AndHowTestInit`, which is auto-discovered at startup and used to configure AndHow in a test environment (there is also an `AndHowInit` for production).  Both calls to `addFixedValue()` are handled by the `StdFixedValueLoader`, which will complain if it cannot find a property with the name `org.myapp.MyClass.PhaserLevel`.

Another place fixed values could be added is at an application entry point, such as the main method.

TODO:  Link to more details about AndHowInit and AndHowTestInit.

Alternatively you can use AndHow\.findConfig() at an application entry point, such as the main method.

TODO:  Link to main method example.

### **Arguments passed to main(String\[] args)**

Loaded by:  [`StdMainStringArgsLoader`](https://github.com/eeverman/andhow/blob/homepage/andhow-core/src/main/java/org/yarnandtail/andhow/load/std/StdMainStringArgsLoader.java)

Reads an array of Strings containing key value pairs in the form `key=value`, and parses & loads the value for any key that matches a Property name.

#### **T**ypical Use Case

A single class, executable jar or desktop application that accepts command line arguments to the `public void main(String[] args)` method can pass them on to AndHow.  This loader scans the key=value pairs and parses values from the keys that match application Properties.

#### Basic Behaviors

* Trims String values: **Yes** - Leading and trailing white space is removed from all values
* Complains about unrecognized properties: **No** - Other properties can be passed in on command line, so the loader does not throw an error if doesn't recognize a property name.

#### Loader Details and Configuration

AndHow has no way to intercept command line arguments, so the application code needs to help a bit, like this:

```java
import org.yarnandtail.andhow.*;

public class MyAppClass {
    public static void main(String[] args) {
        AndHow.findConfig().setCmdLineArgs(args);
        // ...other application code
    }
}
```

The code above passes the command line arguments to AndHow.  The main method is an *application entry point*.  Its the first application code to run, so its safe to configure AndHow.  When the first Property value is read, AndHow will initialize itself from its configuration and will block any further attempts to call `AndHow.findConfig()` by throwing an error.  Another example of an *entry point* would be a lambda `handler()` method.

Running a Java application from command line and passing main arguments generally looks like this:

`java -jar [jar name] [Arguments passed to the main method]`

AndHow property values are passed as `name=value` pairs to the main method, using either full canonical property names or aliases, e.g.:

`java -jar MyApp.jar full.name.of.PROPERTY=aValue propAlias=aValue`

This loader has special handling for `FlagProp`'s allowing them to be set true just by including their name or alias, e.g.:

`java -jar MyApp.jar enableAmazing`

If there is a `FlagProp` with the alias 'enableAmazing', just including its full name or alias would set it true, the equivalent of including `enableAmazing=true`.&#x20;

### System Properties <a href="#h.p_q-pp8zhmi51k" id="h.p_q-pp8zhmi51k"></a>

Loaded by:  [`StdSysPropLoader`](#default-configuration-source-loading-order)

Reads Java system properties and parses & loads the value for any key that matches a Property name.

#### Typical Use Case

An application might receive all or some of its configuration from Java system properties that are set when the JVM starts. Java system properties can be set in a startup script, which could be customized for each environment. This provides a relatively easy way for deployment automation or sys admins to control application configuration values across many servers.

#### Basic Behaviors

* Trims String values: **Yes (0.5.0 and later)**  (No [0.4.2 and earlier](https://github.com/eeverman/andhow/issues/654))&#x20;
* Complains about unrecognized properties: **No** - Since other properties can be in the list, AndHow cannot assume all the system property must match known properties.

#### Loader Details and Configuration

This loader loads properties from `java.lang.System.getProperties()`. Over the lifecycle of the JVM, values of system properties can change so this loader is working from a snapshot of the system properties it finds at the time of AndHow initialization. Once loaded, ***AndHow property values never change***.

For [`FlgProp`](https://github.com/eeverman/andhow/blob/homepage/andhow-core/src/main/java/org/yarnandtail/andhow/property/FlagProp.java) properties (true/false flags), the `StdSysPropLoader` will set the Property's value to true if a matching environment variable is found, even if the value of the property is empty. System properties can be cleared via `java.lang.System.clearProperty(name)`, which is how a flag value could be unset prior to AndHow loading.

Passing system properties on command line looks like this:

`java -Dfull.name.of.MY_PROPERTY=someValue -jar MyJarName.jar`

### Environmental Variables

Loaded by:  [`StdEnvVarLoader`](https://github.com/eeverman/andhow/blob/homepage/andhow-core/src/main/java/org/yarnandtail/andhow/load/std/StdEnvVarLoader.java)

Reads the operating system defined environment variables and parses & loads the value for any key that matches a Property name.

#### Typical Use Case

An application might receive all or some of its configuration from OS defined environmental variables that are passed to the JVM when the JVM starts.  Environment vars can be set in the OS and augmented in a startup script, which could be customized for each environment.  Similar to Java system properties, this provides an easy way for deployment automation or sys admins to control application configuration values across many servers.

Environment vars are becoming the standard way to configure applications since many applications run in virtualized environments, and '[Twelve Factor](https://12factor.net)' has [codified their use](#default-configuration-source-loading-order).

#### Basic Behaviors

* Trims String values: **Yes (0.5.0 and later)**  (No [0.4.2 and earlier](https://github.com/eeverman/andhow/issues/654))&#x20;
* Complains about unrecognized properties: **No** - Since other environment vars can be in the list, AndHow cannot assume all the vars must match known properties.

#### Loader Details and Configuration

This loader loads values from `System.getenv()`. Those environmental values are provided by the host environment (the OS) as a static snapshot to the JVM at startup as a String-to-String map. The underlying OS environment variables may change, however, the JVM will be unaware of it. Similarly, ***AndHow property values never change once loaded***.

For [`FlgProp`](https://github.com/eeverman/andhow/blob/homepage/andhow-core/src/main/java/org/yarnandtail/andhow/property/FlagProp.java) properties (true/false flags), the `StdEnvVarLoader` will set the Property's value to true if a matching environment variable is found, even if the value of the property is empty.

The Windows OS uses ALL CAPS for environment variables, while all others OS's are case sensitive - This is the primary reason AndHow is case insensitive by default. Each OS [has a different way to set an environmental variables](https://www.google.com/url?q=https%3A%2F%2Fwww.schrodinger.com%2Fkb%2F1842\&sa=D\&sntz=1\&usg=AFQjCNEU9yIEce2vJ7ypmL2LwPBDcH8oeg).

### **JNDI values**

Loaded by: [`StdJndiLoader`](https://github.com/eeverman/andhow/blob/homepage/andhow-core/src/main/java/org/yarnandtail/andhow/load/std/StdJndiLoader.java)

Attempts to look up the name of each application Property in the JNDI environment and load the value for any that are found.

#### Typical Use Case

A web service or application that runs in an application container such as [Tomcat](http://www.google.com/url?q=http%3A%2F%2Ftomcat.apache.org%2F\&sa=D\&sntz=1\&usg=AFQjCNGnG5r4GvRXSKjxo10KtAzX7MlwPw). Application containers provide a JNDI environment which can be used to configure applications running in their environment.

#### Basic Behaviors

* Trims String values: **No** - JNDI values are usually configured in XML and have associated type information.  It can be assumed that white space on a string is intentional.
* Complains about unrecognized properties: **No** (Actually NA - see below)

#### Unique Behaviors

* Complains about missing JNDI environment: **No** - (by default)  AndHow can detect when there is no JNDI context and will silently stop looking for JNDI values.
* Is case sensitive: **Yes** - This is one of the only loaders that is case sensitive.  See discussion below.

#### Loader Details and Configuration

While most Loaders process a configuration resource entirely (e.g. a properties file), the JNDI loader works the other way: It goes through the list of known Properties attempts to look up each property name in the JNDI context.  Since JNDI is case sensitive, **the JNDI Loader is case sensitive** as well, since it must individually probe the context for each value.  (Its just not possible to fetch all registered names from the entire JNDI context)

JNDI implementations vary in how they name properties, so the JNDI loader will try several common name forms, for example, the JNDI loader will attempt to look up the following JNDI names for a property named `org.foo.My_Prop`:

* java:comp/env/org/foo/My\_Prop
* java:comp/env/org.foo.My\_Prop
* java:org/foo/My\_Prop
* java:org.foo.My\_Prop
* org/foo/My\_Prop
* org.foo.My\_Prop

AndHow will also look for all Property 'inAliases' as well.  The list of six name forms comes from three root forms and two name forms.  AndHow looks for three different roots (the part that comes before the variable name):

* `java:comp/env/` is used by Tomcat and several other application servers
* `java:` (and nothing else) is used by some non-container environments
* `[no root]` Glassfish (and possibly others?) uses no root at all

The two name forms are:

* dot.separated.AndHow\.style.names
* slash/separated/JNDI/style/names

AndHow will throw an error at startup if it finds multiple names in the JNDI context that refer to the same property.

Specifying JNDI environment variables varies by environment, but here is an example of specifying some properties in a Tomcat context.xml file:

```xml
<Context>
. . .
<Environment name="org/simple/GettingStarted/COUNT_DOWN_START" value="3" type="java.lang.Integer" override="false"/>
<Environment name="org/simple/GettingStarted/LAUNCH_CMD" value="GoGoGo!" type="java.lang.String" override="false"/>
. . .
</Context>
```

In the example above, Tomcat will automatically prepend java:comp/env/ to the name it associates with each value. As the example shows, JNDI values can be typed. If AndHow finds the value to already be the type it expects (e.g. an Integer), great! If AndHow finds a String and needs a different type, AndHow will do the conversion. Any other type of conversion (e.g. from a Short to an Integer) will result in an exception.

If your JNDI environment uses a non-default different root, it can be added [using one of the built-in Properties for the JNDI loader](https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Feeverman%2Fandhow%2Fblob%2Fdc4f845769489204b335a0d4e19c959c786d1835%2Fandhow-core%2Fsrc%2Fmain%2Fjava%2Forg%2Fyarnandtail%2Fandhow%2Fload%2Fstd%2FStdJndiLoader.java%23L224\&sa=D\&sntz=1\&usg=AFQjCNFtKr_FGb0t1dAaJy0IEYfplSYZPQ). Those property values would need to be loaded prior to the JNDI loader, so using system properties, for example, would work. Here is an example of adding the custom JNDI root java:xyz/ as a system property on command line:

`java -Dorg.yarnandtail.andhow.load.std.StdJndiLoader.CONFIG.ADDED_JNDI_ROOTS=java:xyz/ -jar MyJarName.jar`

### **Properties file on the filesystem**

Loaded By:  [`StdPropFileOnFilesystemLoader`](https://github.com/eeverman/andhow/blob/homepage/andhow-core/src/main/java/org/yarnandtail/andhow/load/std/StdPropFileOnFilesystemLoader.java)

Parses and loads Properties from a Java .property file on the file system. Since file systems vary, there is no default filepath that AndHow attempts to load from.

#### Typical Use Case

A web application running in a web container might load some or all of its configuration from a properties file on the file system.  The properties file is not part of the application, so it survives redeployments.  A single environmental or system property could then be used to specify the path to the properties file.

This is a non-standard way to load configuration, but is used by some applications.

#### Basic Behaviors

* Trims String values: **Yes**
* Complains about unrecognized properties: **Yes**
* Complains if the .properties file is missing: **Yes**, but only if a file path is configured

#### Unique Behaviors

* This loader requires configuration to be activated - it has no default file path that it attempts to load from.
* If there are duplicate property entries in a properties file, the last value is used and the others ignored.  This is the behaviour of `java.util.Properties`, which silently ignores duplicate property entries.  Full details can be found in the [properties file specification](https://www.google.com/url?q=https%3A%2F%2Fdocs.oracle.com%2Fjavase%2F8%2Fdocs%2Fapi%2Fjava%2Futil%2FProperties.html%23load-java.io.Reader-\&sa=D\&sntz=1\&usg=AFQjCNFjwA1H-TW0fF13WhMQlv181P-puA).

#### Loader Details and Configuration

This loader is only active if it is configured as shown below, or similar:

```java
import org.yarnandtail.andhow.*;
import org.yarnandtail.andhow.property.StrProp;

public class UsePropertyFileOnFilesystem implements AndHowInit {
    public static final StrProp MY_FILEPATH = StrProp.builder()
    .desc("Path to a properties file on the file system. " +
    "If a path is configured, startup will FAIL if the file is missing.").build();


    @Override
    public AndHowConfiguration getConfiguration() {
        return AndHow.findConfig()
            .setFilesystemPropFilePath(MY_FILEPATH);
    }
}
```

The code above adds the property MY\_FILEPATH (the name is arbitrary) which is used to configure the StdPropFileOnFilesystemLoader with a file location. When AndHow initializes, the StdPropFileOnFilesystemLoader checks to see if a value has been loaded for MY\_FILEPATH by any prior loader. If a value is present, the loader tries to load from the configured file system path. If no value is configured, this loader is skipped.

### Properties file on the classpath (defaults to /andhow\.properties)

Loaded by:  [`StdPropFileOnClasspathLoader`](https://github.com/eeverman/andhow/blob/homepage/andhow-core/src/main/java/org/yarnandtail/andhow/load/std/StdPropFileOnClasspathLoader.java)

Parses and loads Properties from a Java .property file on the classpath. By default, this loader will look for a file named `andhow.properties` at the root of the classpath.

#### Typical Use Case

A service application might load the majority of its configuration from system properties or environmental variables, however, some sane default configuration values can be bundled with the application. By default, AndHow will discover and load a file named `andhow.properties.`

#### Basic Behaviors

* Trims String values: **Yes**
* Complains about unrecognized properties: **Yes**
* Complains if the `andhow.properties` file is missing: **No**

#### Unique Behaviors

* If there are duplicate property entries in a properties file, the last value is used and the others ignored.  This is the behaviour of `java.util.Properties`, which silently ignores duplicate property entries.  Full details can be found in the [properties file specification](https://www.google.com/url?q=https%3A%2F%2Fdocs.oracle.com%2Fjavase%2F8%2Fdocs%2Fapi%2Fjava%2Futil%2FProperties.html%23load-java.io.Reader-\&sa=D\&sntz=1\&usg=AFQjCNFjwA1H-TW0fF13WhMQlv181P-puA).

#### Loader Details and Configuration

Configuring the name or classpath of the properties file can be used to enable different configuration profiles based on the environment. For instance, a system property could specify that /test.properties be used on a test server and /production.properties on a production server. An example of configuring the property file path:

```java
// Some import org.yarnandtail.andhow.*;
import org.yarnandtail.andhow.property.StrProp;

public class UsePropertyFileOnClasspath implements AndHowInit {
    public static final StrProp MY_CLASSPATH = StrProp.builder()
    .desc("Path to a properties file on the classpath. "
    + "If the file is not present, it is not considered an error.").build();


    @Override
    public AndHowConfiguration getConfiguration() {
        return AndHow.findConfig()
            .setClasspathPropFilePath(MY_CLASSPATH);
    }
}
```

The code above adds the property `MY_CLASSPATH` (the name is arbitrary) which is used to configure the `StdPropFileOnClasspathLoader` with a custom property file location. When AndHow initializes, the StdPropFileOnClasspathLoader checks to see if a value has been loaded for `MY_CLASSPATH` by any prior loader. If a value is present, the loader tries to load from the configured classpath. If no value is configured, the default classpath is assumed.


# Testing

AndHow makes testing with multiple configurations easy

Let's write some tests for the ReportGenerator from the [Properties examples](/user-guide/andhow-properties#property-examples).  Here is that class:

```java
package org.example;

import org.yarnandtail.andhow.GroupInfo;
import org.yarnandtail.andhow.property.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;

public class ReportGenerator {

	@GroupInfo(name="Record filter", desc="Filters are AND'ed together")
	interface Filter {
		StrProp REGION = StrProp.builder()
			.oneOfIgnoringCase("EAST", "WEST").build();
		StrProp ZIP = StrProp.builder().matches("\\d{5}(\\-\\d{4})?")
			.desc("Zipcode w optional plus 4 (12345 or 12345-1234)").build();
		LocalDateTimeProp START_TIME = LocalDateTimeProp.builder()
			.defaultValue(LocalDateTime.parse("2010-01-01T00:00"))
			.desc("Include records after this date-time").build();
		BigDecProp MIN_SALE = BigDecProp.builder()
			.defaultValue(BigDecimal.TEN).greaterThanOrEqualTo(BigDecimal.ZERO)
			.desc("Min sale amount to include").build();
	}

	interface Format {
		DblProp MARGIN = DblProp.builder().defaultValue(1d)
			.greaterThan(.25d).desc("Margin in inches").build();
		BolProp WITH_HEADERS = BolProp.builder().defaultValue(true).build();
	}
}
```

This class doesn't really do anything, but lets assume its a lambda function that is launched to run a complicated report.

### Using andhow\.properties on the test classpath

AndHow automatically finds and loads the `andhow.properties` file at the root of the classpath.   Simply place an `andhow.properties` file at the root of the ***test*** classpath to create a configuration used for testing.  This is standard feature of how Maven and many other build tools work and will result in a shared configuration for all tests.

{% hint style="info" %}
Best Practice:  Use Property default values for good business-related defaults.  Don't use default values local workstation or test environment configuration values.
{% endhint %}

Since its easy to provide a test configuration file or a local configuration file, don't be tempted to use Property default values for these purposes.  Unless configured to a A Property with a default value already has a default value, so there will be no warning if that value

### Using the AndHow JUnit Extensions

The JUnit extensions simplify testing multiple configuratino scenarios in your tests.  They can be included in a Maven project like this:

```xml
<dependency>
	<groupId>org.yarnandtail</groupId>
	<artifactId>andhow-junit5-extensions</artifactId>
	<version>1.5.0</version>
	<scope>test</scope>
</dependency>
```

The next examples use the extensions.

### Customize Property values for a test

Lets say that you need test a scenario for a specific zip code in the 'west' region:

```java
@Test @KillAndHowBeforeThisTest
public void test90210Zip() {
	AndHow.findConfig()
		.addFixedValue(Filter.ZIP, "90210")
		.addFixedValue(Filter.REGION, "west");

	assertTrue("west".equalsIgnoreCase(Filter.REGION.getValue()));
	assertEquals("90210", Filter.ZIP.getValue());
	// ... and do some actual app testing
}
```

The `@KillAndHowBeforeThisTest` is one of the AndHow JUnit extensions.  It can be placed on an individual test method to reset AndHow to its unconfigured state before the test runs. When the test is done, the original AndHow state is restored (which may be the un-initialized state).

`AndHow.findConfig()` grabs the configuration of AndHow before it [initializes](/user-guide/andhow-initialization) and loads Property values.  `addFixedValue()` effectively hard-codes a specific Property value via the [FixedValueLoader](/user-guide/loaders-and-load-order#fixed-values-values-set-in-code-during-initiation).

Assuming no environment vars., system properties or other configuration sources provide named values that match the app's Properties, Property values for the test above would come from:

* The 'fixed values' for `ZIP` and `REGION`
* `andhow.properties` on the ***test*** classpath (if there is one) for other properties
* `andhow.properties` on the ***main*** classpath if there is no file on the test classpath

{% hint style="info" %}
'Killing' and resetting AndHow isn't allowed in production. AndHow Property values are constants and once initialized at startup, do not change. The `@KillAndHow...` annotations uses reflection to bend the rules to make testing easier.
{% endhint %}

### Custom .properties file for one or more tests

If a test scenario involves setting lots of Property values or is needed for multiple tests, a separate .properties file can be used.  Here is an example of one way to do that for an entire test class:

```java
package org.example;

import org.example.ReportGenerator.Filter;
import org.junit.jupiter.api.*;
import org.yarnandtail.andhow.AndHow;
import org.yarnandtail.andhow.junit5.KillAndHowBeforeEachTest;
import static org.junit.jupiter.api.Assertions.assertEquals;

@KillAndHowBeforeEachTest
class TransactionManager_WestSeparateTest {

	@BeforeEach
	public void setup() {
		AndHow.findConfig()
			.setClasspathPropFilePath("/west_region.properties");
	}

	@Test
	public void happyPath() {
		assertEquals("west", Filter.REGION.getValue().toLowerCase());
		// ... and do some actual app testing
	}

	@Test
	public void zipCode90212() {
		AndHow.findConfig()
			.addFixedValue(Filter.ZIP, "90212");

		assertEquals("90212", Filter.ZIP.getValue());
		// ... and do some actual app testing
	}

	// Other tests will also share the same AndHow instance
}
```

`@KillAndHowBeforeEachTest` on the test class is the same as putting `@KillAndHowBeforeThisTest` on each test.  All tests in this class will use the `west_region.properties` set in the `@BeforeEach` method.  Since AndHow is reset before each test, we can even further customize AndHow's configuraiton before an individual test, as in the `zipCode90212` test.

If an entire test class needs to run with the same configuration for all tests and/or you don't want AndHow to re-initialize for each test to save a bit of execution time, this can be done slightly differently:

```java
@KillAndHowBeforeAllTests
class TransactionManager_WestSharedTest {

	@BeforeAll
	public static void setup() {
		AndHow.findConfig()
			.setClasspathPropFilePath("/west_region.properties");
		AndHow.instance();  // Optional, but prevents tests from modifying
	}

	@Test
	public void testEastRegionWithWideMargins() {
		assertTrue("West".equalsIgnoreCase(Filter.REGION.getValue()));
	}

	// Other tests will also share the same AndHow instance
}
```

The `@KillAndHowBeforeAllTests` JUnit extension resets AndHow a single time before the test class executes its tests.  The `@BeforeAll` method can be used to initialize AndHow as you want it for all the tests.  Now all the tests in this class will share the same configuration.

The AndHow\.instance() call in `@BeforeAll` is not necessary, but is a good idea.  Without that call, AndHow leaves the setup method uninitialized.  One of the test methods *could* still modify the configuraton (similar to the previous example's `zipCode90212()` method), leading to confusion.  Once AndHow is [initialized](/user-guide/andhow-initialization), it will throw a clear exception if any attempt is made to modify it's configuration.


# AndHow Initialization

How AndHow startup up, configures itself, and your application

Initialization 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***.

### Implicit Initialization

Initialization can be triggered explicitly or implicitly.  *Implicit initialization* happens as a side effect of reading a property value:

```java
My_ANDHOW_PROPERTY.getValue();
```

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

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

### Explicit Initialization

Explicit initialization happens when your application code directly constructs the AndHow 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:

```java
  public static void main(String[] args) {
    AndHow.findConfig().setCmdLineArgs(args);
    
    AndHow.instance();    //  <-- Initialize

    Thread.sleep(1000000);
    checkForTaskToDo();    //  <-- Configuration is first read here
  }
```

In this hypothetical example, configuration values are not used until there is a task to do, perhaps long after the process has started.  To ensure configuration values are validated at startup, use `AndHow.instance()` to force initialization of the AndHow singleton.  This ensures that any mis-configuration [*fails fast*](https://www.martinfowler.com/ieeeSoftware/failFast.pdf).

Later calls to `AndHow.instance()` will return the single `AndHow` instance.  Later calls to `Property.getValue()` will internally call `AndHow.instance()` to look up the property value.

In the example above, the call to `AndHow.findConfig()` does not cause AndHow to initialize.  Instead, it retrieves the configuration that AndHow will use during initialization.  Calling `AndHow.findConfig()` is only allowed ***before AndHow is initialized.***

### Attempting to reconfigure AndHow will throw a RuntimeException

Here is another initialization example:

```java
  public class LambdaHandler {
    public void prepare() {
      System.out.println(A_PROP.getValue());
    }
    
    public String handle(String request) {
      AndHow.findConfig().addFixedValue(MY_ANDHOW_PROP, "xxx");
    }
  }
```

In the code snippets above, it looks like the intent is to set a fixed value of "xxx" for `A_PROP`, but perhaps `prepare()` is called before that happens!?  In that case, `A_PROP` might have the 'wrong' value.

AndHow protects against this situation by blocking access to `AndHow.findConfig()` after initialization happens.  If `prepare()` is called before `handle()`, implicit initialization happens at `A_PROP.getValue()`.  Later when `AndHow.findConfig()` is called, AndHow throws a RuntimeException.

{% hint style="info" %}

#### Best Practice:  If your application needs to configure AndHow, use an `AndHowInit` class&#x20;

Alternatively, ensure the application has a well defined application entry point.

See [Configuring AndHow](/user-guide/configuring-andhow) for more details.
{% endhint %}

, which is always discovered and invoked during initialization, even if implicitly initiated.&#x20;

## AndHow Initialization Steps in Detail

AndHow will use the [StdConfig](https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Feeverman%2Fandhow%2Fblob%2Fmaster%2Fandhow-core%2Fsrc%2Fmain%2Fjava%2Forg%2Fyarnandtail%2Fandhow%2FStdConfig.java\&sa=D\&sntz=1\&usg=AFQjCNEC40ZsNv0lRJNfJ0Smz0jnzI4OwA) to configure itself, which is an instance of [AndHowConfiguration](https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Feeverman%2Fandhow%2Fblob%2Fmaster%2Fandhow-core%2Fsrc%2Fmain%2Fjava%2Forg%2Fyarnandtail%2Fandhow%2FAndHowConfiguration.java\&sa=D\&sntz=1\&usg=AFQjCNE0x6ZDGcLu1T3CqgyEg2hnneR9CA), unless there is an implementation of [AndHowInit](https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Feeverman%2Fandhow%2Fblob%2Fmaster%2Fandhow-core%2Fsrc%2Fmain%2Fjava%2Forg%2Fyarnandtail%2Fandhow%2FAndHowInit.java\&sa=D\&sntz=1\&usg=AFQjCNF8s1hLBuP-Bu030Y8f47v49e17xw) 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.


# 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 <a href="#h.9yf27fod3dww" id="h.9yf27fod3dww"></a>

AndHow ensures that its state and Property values are immutable once [initialized](/user-guide/andhow-initialization), 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()` is the only way to access the configuration AndHow uses for itself.  Until [initialization](/user-guide/andhow-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](https://en.wikipedia.org/wiki/Entry_point).  Common well defined entry points are:

* The main method of application startup class
* The `ServletContextListener.contextInitialized` method in a Servlet application
* The `handle()` method of a lambda function
* Any 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

AndHow 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:

```java
public class InsertLoader implements AndHowInit {

	@Override
	public AndHowConfiguration getConfiguration() {
		PropFileOnClasspathLoader pfl = new PropFileOnClasspathLoader();
		pfl.setFilePath("/my.properties");
		
		return AndHow.findConfig()
			.insertLoaderBefore(StdJndiLoader.class, pfl);
	}
}
```

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](/user-guide/andhow-initialization) and use the new loader.

{% hint style="info" %}

#### Best Practice:  Use an AndHowInit class to configure AndHow and include it with your deployable application, not a library or dependency

{% endhint %}

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.

{% hint style="info" %}
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.
{% endhint %}

### 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:

```
public class HelloWorld {
    private static final StrProp NAME = StrProp.builder().build();
    
    public static void main(String[] args) {
        AndHow.findConfig().setCmdLineArgs(args); // <-- Pass cmd-line args to AndHow
        
        System.out.println("Hello, " + NAME.getValue());
    }
}
```

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](/user-guide/changing-the-load-order) section.

Setting fixed values is mostly done during [testing](/user-guide/testing).


# Whitespace Handling

AndHow generally removes leading and trailing whitespace from values as they are loaded, and each Property has a `Trimmer` instance to do the trimming.

Depending on where values are loaded from (i.e. which loader is used) trimming of String type values maybe enabled or disabled. For instance, if a String value is loaded from JNDI (the StdJndiLoader) or as a fixed value in code (StdFixedValueLoader), no trimming is done for String values because it is assumed that the value is in its final form. Non-String values are always trimmed as they are loaded.

### Non-String Property Trimming

The `TrimToNullTrimmer` is used by most non-text properties and simply removes all whitespace on either end of a value. If the result is a zero length string, it becomes null.

### String Property Trimming

`StrProp`, and likely most other text based properties, use a special `QuotedSpacePreservingTrimmer` (QSPT). The *QSPT* first trims to null, then, if the remaining text begins and ends with double quotes, those quotes are removed and the string inside the quotes, including whitespace, is preserved as the actual value.

Here are a few examples of the *QSPT* trimming behavior, using dots (**●**)to represent whitespace and -> to separate the raw value on the left from the trimmed value on the right:

| Raw Value           | QSPT Trimmed Value | Notes                                                                          |
| ------------------- | ------------------ | ------------------------------------------------------------------------------ |
| **●**               | \[null]            | An all whitespace raw value is trimmed to null                                 |
| ●●●abc●●●           | abc                | whitespace on either side of text removed                                      |
| "●abc●"             | ●abc●              | Quotes are removed and all characters inside preserved                         |
| ●"●abc●"●           | ●abc●              | same result - whitespace outside the quotes is removed                         |
| ●a "word" here●     | a "word" here      | No special quote handling here - there is text outside the quotes              |
| ●"●a "word" here●"● | ●a "word" here●    | After trimming outer whitespace, leading and trailing double quotes were found |
| ●""●                | \[empty string]    | Using quotes, it is possible to assign an empty string                         |

The trimmer for a Property can be changed if a different behaviour is needed:

```java
StrProp TRIM_ME_TO_NULL =
    StrProp.builder.trimmer(TrimToNullTrimmer.instance()).build();
```


# Integration and Exports

AndHow can integrate with other frameworks and legacy apps.

Strong typing, validation at startup, and semantic property names are nice features for new applications, but what about existing applications that are relying on finding specifically named properties?

### Manual Export to Maps, java.util.Properties and more

AndHow can export groups of AndHow Properties to Maps, java.util.Properties, or any structure you need.  Here is an example:

```java
public class AppDataAccess {

	@ManualExportAllowed(
		useCanonicalName=Exporter.EXPORT_CANONICAL_NAME.NEVER)
	private interface HibernateConfig {
		StrProp USER = StrProp.builder()
			.aliasInAndOut("hibernate.connection.username")
			.notNull().build();
		StrProp PWD = StrProp.builder()
			.aliasInAndOut("hibernate.connection.password")
			.notNull().build();
		IntProp POOL_SIZE = IntProp.builder()
			.aliasInAndOut("hibernate.connection.pool_size")
			.defaultValue(20).lessThan(200).build();
	}

	public Properties getHibernateProperties() throws IllegalAccessException {
		return AndHow.instance().export(HibernateConfig.class)
			.collect(ExportCollector.stringProperties(""));
	}
}
```

This example supposes were are configuring the [Hibernate](https://hibernate.org) framework (an ORM tool that connects to a database).  Hibernate accepts a `java.util.Properties` for configuration, so we can use AndHow to export Properties for it.  The resulting java.utils.Property would contain values like this:

* hibernate.connection.username = \[The configured username]
* hibernate.connection.password = \[The configured password]
* hibernate.connection.pool\_size = \[The configured pool size]

Some key points of exporting:

* `@ManualExportAllowed` is required to allow exports.  It applies to all AndHow Properties contained in the class or interface it is on, and is inherited by any nested inner classes or interfaces.
* `AndHow.instance().export(AppDataAccess.class)` will `stream()` `PropertyExport` instances, one per Property contained in the exported class.  Properties contained directly or in nested innerclasses/interfaces will be included.
* A `PropertyExport` object contains a reference to the Property being exported, its value, and other metadata relevant for exporting.  Inspecting and modifying the PropertyExport in the stream gives fine grained control over the export.
* Using `Property.aliasInAndOut` or `aliasOut` gives easy control over the name used to export.  In this example, the alias name is intended to match the property names Hibernate is expecting.  The options on `@ManualExportAllowed` also control which names are exported.  By default, 'out' names are always used and in this example the cannonical names are turned off.  Its possible to have multiple names exported for each Property.

{% hint style="warning" %}
Adding the `@ManualExportAllowed` widens the visibility of the contained Properties.  Normally a private Property is not visible outside the class that declares it.  However, if the class allows export, any class with a reference to the containing class can export and read the values of the contained Properties.
{% endhint %}

In the example, if `@ManualExportAllowed` had been placed on `AppDataAccess`, the result would be the same, however, any private Properties contained in AppDataAccess would indirectly expose their value to any class with a reference to AppDataAccess.

To enable large groups of innerclasses/interfaces to be exported, `@ManualExportAllowed` can be placed on the containing class.  To block some select innerclasses, `@ManualExportNotAllowed` can be used.

//TODO:  There are lots of varieties of exports to include.  The `AndHow.export()` method javadocs contains lots of examples.

### Auto-Export to System Properties

AndHow can export property names and values to bridge the gap between legacy code and AndHow Properties. Below is an example that could be used for a legacy code expecting to find configuration in System.Properties.

```java
import org.yarnandtail.andhow.*;
import static org.yarnandtail.andhow.api.Exporter.*;
import org.yarnandtail.andhow.export.SysPropExporter;

@GroupExport(
    exporter=SysPropExporter.class,
    exportByCanonicalName=EXPORT_CANONICAL_NAME.NEVER,
    exportByOutAliases=EXPORT_OUT_ALIASES.ALWAYS
)
public interface ShoppingCartSvsConfig {
    StrProp SERVICE_URL = StrProp.builder()
        .mustEndWith("/").aliasInAndOut("cart.svs").build();
    IntProp TIMEOUT = IntProp.builder()
        .aliasInAndOut("cart.to").aliasOut("timeout").build();
}
```

The annotation in the example above specifies that as soon as the startup value loading is completed:

* All the Properties contained directly in the class will be exported as a name-value pair to System.Properties at startup.
* The property name used will be the 'out' alias, if the property has one, otherwise the canonical name of the Property is used
* The value will be the validated value loaded by AndHow

Take care to ensure that AndHow is initialized before legacy code attempts to read exported valeus. This can be done by simply calling AndHow\.instance(); at your code entry point, or reading the value of any AndHow Property.

Also note that only properties contained directly in the annotated class are exported: Properties in nested inner classes or interfaces are not included, though those inner classes could also be annotated.

In this exmple, each property is given an InAndOut alias matching the name that the legacy code is expectiving to find in the System.Properties. The '*out'* portion of that specifies a name available for export. The 'in' portion is an added name that will be recognized when reading property values from a configuration source, like JNDI or a properties file. Aliases can be specified as 'in' or 'out' only as well if needed to avoid name collisions.

By using GroupExport and aliasInAndOut, a legacy application can be virtually unchanged and still benefit from strong typing, validation checks, multi-source loading and other features of AndHow.


# Changing the Load Order

## Changing the Loader Order <a href="#h.p_ldwcvoyaib6_" id="h.p_ldwcvoyaib6_"></a>

It's easy to edit or change the order of the loaders:

```java
import org.yarnandtail.andhow.*;
import org.yarnandtail.andhow.load.std.*;

public class ModifyStdLoaderOrder implements AndHowInit {
    @Override
    public AndHowConfiguration getConfiguration() {
        return AndHow.findConfig()
            .setStandardLoaders(StdEnvVarLoader.class, StdJndiLoader.class);
    }
}
```

The example class above implements the AndHowInit interface. At startup, AndHow will discover this class and use it to configure itself. In this case, the standard list of seven loaders has been replaced with just two.

## Adding custom loaders

&#x20;Its also possible to leave the standard list intact and insert loaders between the standard loaders:

```java
@Override
public AndHowConfiguration getConfiguration() {
    PropFileOnClasspathLoader pfl = new PropFileOnClasspathLoader();
    pfl.setFilePath("/my.properties");
    return AndHow.findConfig()
        .insertLoaderBefore(StdJndiLoader.class, pfl);
}
```

Only a single instance of each of the Standard loaders is allowed - these are the loaders with names start with 'Std' and implement the StandardLoader interface, however, it is OK to insert any number of any other loader.


# Java9 and Above

AndHow works for applications built and/or running on Java 9 and up, but there are considerations.

### The good news:  AndHow works on JDK 8 - 16

If you don't use modules (i.e. don't include a `module-info.java` file in your jars), AndHow works just fine.  And this seems to be what most projects and libraries have done:  simply ignore the module system.

### The bad news:  It doesn't work with Java9 modules

If you really need Java 9 modules, it will be some time and work before AndHow can support them.  If module support is important to you, please comment on [this ticket](https://github.com/eeverman/andhow/issues/375).  If you are a module expert, please consider offering to help with that ticket.

### But... Why modules?

Applications, especially those that runs as lambdas, micro-services or within containers, live in a very walled garden. The extra level of ceremony that Jigsaw modules provides (essentially protecting your code from itself and the dependencies you choose to use) doesn't add meaningful security in most cases.


# Best Practices

Get the most out of AndHow and your application

### Declare properties in the class or interface where they are used.  Place related sets of Properties in nested interfaces.

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.

Nesting related Properties into interfaces creates logical, canonical names for Properties.  It also takes advantage of the Java language to save some typing: Variables declared in an interface are implicitly static final.  As of Java 11, inner interfaces may be declared private.

[Read More...](/user-guide/andhow-properties#property-example-2)

### Don't worry about Property names unless you have to <a href="#h.kwud3bftlih4" id="h.kwud3bftlih4"></a>

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.

Properties may have aliases, but the canonical names are often good enough and will implicitly update when refactoring.

[Read More...](/user-guide/andhow-properties)

### Use a Property default value when there is a good business-related default that works in all environments

Don't use a default value for local workstation or test environment configuration values.

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.

[Read More...](/user-guide/andhow-properties)

### Use an *AndHowInit* class to configure AndHow and include it with your deployable application, not a library or dependency <a href="#h.tbqgd0fx2c3z" id="h.tbqgd0fx2c3z"></a>

AndHow allows only a single class implementing the [AndHowInit](https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Feeverman%2Fandhow%2Fblob%2Fhomepage%2Fandhow-core%2Fsrc%2Fmain%2Fjava%2Forg%2Fyarnandtail%2Fandhow%2FAndHowInit.java\&sa=D\&sntz=1\&usg=AFQjCNEhAU40KFuLMUd6k8xVqWZsiXqWtQ) interface on the classpath and will complain (i.e. throw a RuntimeException) at startup if it finds more. Why? AndHowIinit [configures how AndHow configures your application](https://sites.google.com/view/andhow/user-guide/configuring-andhow) - it cannot be ambiguous which AndHowInit is intended to be the effective one. If an AndHowInit instance is included in a library, it prohibits applications using that library from creating their own AndHowInit.

If you have a dual-use library, such as a calculation utility that can be run from command line or bundled into a larger application, use a packaging tool like Maven to create two packaged version: One with an AndHowInit instance for independant usage, and another without an AndHowInit instance for so the library can be included as a dependency in other applications.

### Include an *andhow\.properties* file in your deployable artifact, not in library or dependency <a href="#h.9c0wfcaj8wad" id="h.9c0wfcaj8wad"></a>

Incluing an andhow\.properties file in a library is essentially just like setting default values for each Property. Properties already can have their defalaults declared in their construction, so there is no need to do this. Worse, if the deployed application includes its own properties file, it may become ambiguous which one is suppose to be in use (though web containers like Tomcat and SpringBoot generally get this right).

If you want to include a sample configuration file for applications using a library, it might be clearer to call it andhow\.properties.sample or similar.

### Use an andhow\.properties on your test classpath (not your production one) <a href="#h.3p24zvkhqmzl" id="h.3p24zvkhqmzl"></a>


# Developer Guide


# How to Contribute

Your first pull request

**First,** *<mark style="color:purple;">**thank you**</mark>***&#x20; - Let's work together and make something cool!**

### First Steps

* [***Star***](https://github.com/eeverman/andhow/stargazers) the AndHow project on GitHub. This shameless bit of promotion raises the profile of AndHow a bit and may help others become contributors.
* If you are unfamiliar with the project, read through the [home page](/) (4 minute read).

### Work from the *main* branch

* The ***main*** branch is the branch to work from: branch from it, make PRs to it
* The *homepage* branch is the default branch displayed on GitHub

This can be confusing because most projects use *main* as the default branch, but there are [advantages to this structure](/developer-guide/project-branching-structure#github-and-the-default-branch).

### Typical Task / Issue workflow

AndHow uses the typical [feature branch repository strategy](https://martinfowler.com/articles/branching-patterns.html#feature-branching) (aka fork-and-branch), where developers work on a branch in their own repository.  Basically:

* Fork the [AndHow project](https://github.com/eeverman/andhow) on GitHub
* *Clone* from your fork to your local machine to work on it
* Work on a task in a new branch created just for that task - create the branch ***from your main***
* Submit completed work (or work in progress for review) as a *Pull Request* to ***main*** of the canonical repository

Feature branch names should look like this: `Issue123-A-short-name-for-the-issue`

If that is all new to you, here is a bit of [help with a first git checkout](/developer-guide/first-checkout-with-git).

### Unit Testing

**As a contributor, please:**

* Write tests for new functionality at or new 100% test coverage
* Write tests for untested code if you are modifying it

...and always feel free to contribute tests for untested or poorly tested code

### Code style

* This project uses *tabs* for indentation. If you are working on a file that is not tab indented, please convert it to tabs (but don't do other files).
* Add complete Javadocs for new methods and classes (other than test classes unless needed)
* Good javadocs comments *what* and *why*. We usually don't need comments on how.

### More help getting started

Workstation setup is typical for Java development, but there is a [New Workstation](/developer-guide/new-workstation-setup) setup page if you need additional help, or post a question on the [forum](https://groups.google.com/g/andhowuser).

### Working well together

One of the joys of a project like this is collaborating with others. Collaboration is more than completing issues, it is discussing ideas, asking questions, learning, discovering something new and cool together. Some ways to help that happen:

* Post Work In Progress (WIP) pull requests and ask for review - its a good way start discussion.
* Ask questions on issues: *Is this really the best approach? Does this feature really need to be in this release?*
* Take part in the [Discussions](https://github.com/eeverman/andhow/discussions) or the [user forum](https://groups.google.com/g/andhowuser)

### Project Tenets and Development Guidelines

**AndHow must use no runtime dependencies**

AndHow is a low level utility that can be used in any application or other utility. If AndHow has dependencies, that can lead to version conflicts when included in other projects. AndHow does have dependencies for testing and at compile time (the tools.jar / jdk.compile module), but none of these are dependencies at runtime.

**AndHow must have good quality and effective test coverage**

As a low level utility, we don't want user's to have to second guess if it is working correctly. That does not mean that test coverage must be 100%, but the tests should give confidence that the code functions as intended and is capable of catching new bugs.

Part of AndHow is an annotation processor at *compile time*, so there are unique testing challenges. Caveats aside, the current test coverage (around 87%) should be improved.

#### Other ways to contribute

* Report a bug or suggest a feature on the [issue tracker](https://github.com/eeverman/andhow/issues)
* Submit pull-requests to improve the Javadocs or [test coverage](https://app.codecov.io/gh/eeverman/andhow)
* Any corrections or added documentation needed on this site can be opened as an issue on the project.
* Suggest a new example for the [AndHow Samples Project](https://github.com/eeverman/andhow-samples)


# First Checkout with Git

If git is new to you, there are lots of [good write-ups](https://blog.scottlowe.org/2015/01/27/using-fork-branch-git-workflow/) on the topic.  I won't rehash all the detail from other places, but assuming you have git installed and have already forked AndHow, here is the quick version of getting a local copy ready for development (from a mac/linux terminal window, enter the commands following the <mark style="color:orange;">**`>`**</mark> prompt:

```bash
> git clone https://github.com/[your user name]/andhow.git

Cloning into 'andhow'...
remote: Counting objects: 10545, done.
remote: Compressing objects: 100% (73/73), done.
remote: Total 10545 (delta 19), reused 60 (delta 7), pack-reused 10445
Receiving objects: 100% (10545/10545), 13.

> cd andhow
> git remote add upstream https://github.com/eeverman/andhow.git
> git checkout main
```

* Line 1:  *Clones* (i.e. copies the entire project) your fork of AndHow to your local machine, into a directory named andhow in the directory you are currently in
* Line 9:  cd into that directory
* Line 10:  By forking, you have your own remote repository of AndHow on GitHub.  When you cloned it, it was copied to your local machine, but it knows about that remote copy and calls it 'origin'.  Line 10 tells your local copy about another remote repository that you are calling 'upstream'.   You need upstream in order to pull in the latest changes to your local copy.
* Line 11:  Switch to the main branch (you would have been on the default homepage branch previously)

To begin working on, for example, Issue 123 "Long titles are too long and very wordy", create a new branch for it :

```bash
> git checkout -b Issue123-Long-titles
```

Later you will commit, push, and put in a pull request, but I'll leave those details to [other references](https://blog.scottlowe.org/2015/01/27/using-fork-branch-git-workflow/).


# Project Branching Structure

AndHow uses a slightly modified [*feature branch*](https://martinfowler.com/articles/branching-patterns.html#feature-branching) strategy for branching. The key things to remember are:

* *After you fork the AndHow project, branch off of the **main branch** of your fork for each task.  This new branch is often referred to as a feature branch, since its a dedicated branch for the development of a new feature (or bug fix, or other change)*
* *Submit pull requests (merge requests) of your feature branch to AndHow's **main branch***

### GitHub and the default branch

Unlike most projects, the *main branch*, where development is done, is not the default branch.  The default is the *homepage* branch.  The reason is that GitLab displays the default branch and its much better to display the latest released code, rather than the current head of development.

Not displaying the development branch is especially useful when the API changes between releases - We really don't want to show examples of an unreleased API in the readme.md, yet it often takes a few days to create good examples.  Working on them behind the scenes on the main branch is a nice solution.

### The key branches are: <a href="#h.w9rt4gralo4t" id="h.w9rt4gralo4t"></a>

***main*** - This is the branch that contains all latest code. When you start a task you start from this branch, and when you submit a pull request it goes to this branch.

***\[Your Repository]/Issue###-Short-issue-name*** - This is a feature branch in your repository. When you start work on an issue, pull in the latest code from main to your personal main branch, then branch to create a feature branch with a name like shown. When you complete your work, push that branch to your fork on GitHub, then put in a pull request from your feature branch to canonical main.

***homepage*** - This branch is based at the latest released version and is the default branch displayed when a user visits the AndHow GitHub project.

***release*** - A separate branch for creating a release. It may only be visible during release creation.

**x.x.x** - A branch for a particular release.  These get created occasionally, but don't have any particular conventions.

***\[some other feature branches]*** - One limitation of GitHub is that the project owner cannot create a fork of their own project - the project itself is their 'private' fork. Thus, other feature branches in the project are probably the project owner's because they have no other place to put them :-)


# New Workstation Setup

### Reference workstation platform <a href="#h.p_ny1wmsufr8tt" id="h.p_ny1wmsufr8tt"></a>

Main development has been done on this platform:

* Java JDK 1.8 - JDK 16
* Any IDE that works well with Maven (IntelliJ and Netbeans have been used)
* [Maven 3.8.x](https://maven.apache.org/) (min 3.2.2 required)
* [Git 2.8.1](https://git-scm.com/) or better
* A [Github](https://github.com) account is required to submit pull requests to merge you code changes into the canonical repository

MacOS 10.x and 11.x was used as the OS, but this is not at all a requirement. Linux and Windows workstations should work - AppVeyor builds are done with Linux and Windows to ensure builds and tests work on both systems.

Any current JDK (1.8 - 16) is capable of building AndHow and using it in an application. **Java JDK8 is a requirement for building a release or snapshot**. The 1.8 requirement is due to [Jigsaw](https://www.google.com/url?q=https%3A%2F%2Fwww.baeldung.com%2Fproject-jigsaw-java-modularity\&sa=D\&sntz=1\&usg=AFQjCNHhhCh7P8KvyaMt1811ND5bBJOQHw), introduced in JDK9, which allows modularization of the JDK and applications. AndHow depends on the JDK tools.jar, which was removed in JDK9 and replaced with the jdk.compile module. The add-modules mechanism of JDK9 forces the built jar to be Java9 compatible - its not possible to compile with JDK9, add a module and build a Java8 compatible jar.

*Fret Not!* The resulting JDK8 AndHow jar can be used in Java9 and newer projects, so this limitation only affects development of AndHow itself, not projects that use it.

**Any IDE can be used to develop AndHow.** Some free options are:

* **Netbeans 12.4**
* **IntelliJ CE**
* **Eclipse**

Netbeans is now an Apache project and works very well with Maven, but is a bit rough. IntelliJ Community Edition is very polished, but struggles with Maven a bit, though, this is mostly an issue when changing module structure. Eclipse... I haven't used for several years.

**Maven 3.5 or newer is a requirement**. Any recent version of Maven will work. Maven provides dependencies and build scripting for this and many other Java projects.

**Git 2.8.1 or newer is a requirement**, though any recent version will work. Git is the source code management system for this project and is in wide use.


# Background

This project started as a solution to a problem at work that was never solved. I was on a team writing a custom ETL (Extract, Transform, Load) application that had lots of configuration options. We created a list of all of those options as array, but it was a long list with lots of strange names, so someone created a second array that had descriptions of each of the options. Worse, the options array was in the main class, but options were actually used elsewhere with no connection between an option and the class it configured. To set values for all those options some developers created system properties, others passed options in on the command line, and others ran it in an environment that provided configuration values. Naturally, the loading logic became very complicated and the documentation (hidden in an array) was minimal.

I thought there had to be a better way. A way to document configuration parameters, automatically read them from multiple sources, and place configuration parameters where they are used. The result was AndHow. Sadly, I never managed to port it back to that project...

The initial versions of AndHow were pretty cumbersome to use - You had to register each class that had Properties when you initialized AndHow. A solution to that complexity was found when I found this paper: [The Hacker's Guide to Javac](http://www.google.com/url?q=http%3A%2F%2Fscg.unibe.ch%2Farchive%2Fprojects%2FErni08b.pdf\&sa=D\&sntz=1\&usg=AFQjCNFj-pCMLm50EZO4dUXoDaRiGC32yg). The paper is pretty old (2008 and Java6), but the concept of a compiler plugin and dipping into the compile tree meant that AndHow could 'register' its own Properties at compile time, allowing it to know all available Properties when an application started up.


# Framework Testing

This page is for developers who are working on AndHow and need to write tests for AndHow itself. If you are writing tests for an application *using* AndHow, see the User Guild [Testing](/user-guide/testing) section.

* AndHow ties into the Java compiler as an annotation processor so testing requires running the javac compiler and verifying compilation results in some places.
* At runtime, the main AndHow class is an immutable singleton, however, for good testing we want to put that immutable singleton into lots of different states to ensure it works correctly - Those two things cannot both (easily) be true
* Never hold a reference to the AndHow singleton object in a way that survives beyond a single test (This would be the object returned from `AndHow.instance()` ) or the even more hidden AndHowCore (referenced inside the AndHow class). The AndHow testing framework 'cheats' and actually destroys the AndHow and AndHowCore singleton instances, allowing it to be recreated. Thus, any reference to an AndHow instance held by test code has the potential to be pointing to an old instance left from a previous test.


# Conventions

Its a tough balance to make method names meaningful, short and familiar. Here are some of the established conventions in the AndHow Project. These conventions represent what has happened up to this point and why. Community direction in the future could easily change this.

These Property classes are the main interaction point for most users, so the names used are important. Existing Property names, such as StrProp, IntProp, BigDecProp, and LocalDateTimeProp follow these conventions:

* The names all end with Prop rather than Property to keep the names short
* For property types that are based on a boxed primative, the type is shortened to three characters, such as BolProp, DblProp, IntProp and LngProp. The idea here is that these types are so common and familiar that anyone will recognize what the type is, even in this short form.
* BigDecProp and LocalDateTimeProp show the limits of abbreviation. 'BigDec' is still pretty recognizable in its shortened form, while 'LocalDateTime' can't really be abbreviated without becoming ambiguous.
* FlagProp is special purpose - Its a boolean type with special usage and behaviours. As a precident, it would be purpose wins over datatype.

If the Property classes are the most visible classes of AndHow, the builder methods used to assemble the instances are the most visible methods. Most of those methods are validation / requirements related. Prior to version 0.4.2, all of those methods began with must or mustBe. Those names were clear, but too long. As a result of a [discussion](https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Feeverman%2Fandhow%2Fdiscussions%2F605\&sa=D\&sntz=1\&usg=AFQjCNEAWXA3YzIJWImWGv8AkGXUWBhqog) [resulting](https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Feeverman%2Fandhow%2Fissues%2F587\&sa=D\&sntz=1\&usg=AFQjCNHQWrjZTU-knT8IW-wId9URfRvWtg) [in](https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Feeverman%2Fandhow%2Fissues%2F608\&sa=D\&sntz=1\&usg=AFQjCNFIr-Oyyiwc6beAu4Q5iFCkdZYk4Q) [several](https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Feeverman%2Fandhow%2Fissues%2F609\&sa=D\&sntz=1\&usg=AFQjCNHxee_LBdPsHixijm3LREr1KK1Z-A) [tasks](https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Feeverman%2Fandhow%2Fissues%2F611\&sa=D\&sntz=1\&usg=AFQjCNFnOYqOdTZkJtLVbWV6jkPNXHIgzQ), those method names were shorted.

The intent was to base the validation methods on existing, well-known validation or assertion methods. For String related validation, this was easy since the String class has several assertion style methods to copy from. Things were less clear cut for numeric or date related validation. Here are notable precidents:

* StrProp.StrPropBuilder.oneOf() and startsWithIgnoringCase() is based on [Hamcrest Matchers](http://www.google.com/url?q=http%3A%2F%2Fhamcrest.org%2FJavaHamcrest%2Fjavadoc%2F2.2%2Forg%2Fhamcrest%2FMatchers.html\&sa=D\&sntz=1\&usg=AFQjCNGu4_51fcMI3G04DQRnprHskFQoYg)
* Numeric validation methods are all based on Hamcrest Matchers as well
* PropertyBuilderBase.notNull(), which is used by all builders, is based on JUnit assertions (isNotNull in JUnit)
* LocalDateTimeBuilder validation is based on a [Hamcrest extension for validating dates and times](https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2FeXparity%2Fhamcrest-date%2Fblob%2Fmaster%2Fsrc%2Fmain%2Fjava%2Forg%2Fexparity%2Fhamcrest%2Fdate%2FLocalDateTimeMatchers.java\&sa=D\&sntz=1\&usg=AFQjCNFTl5Lvy4xWm_4ncD3bE_xMr9imJw)

The general guide in preference order might be:

1. Use true/false assertion method names from the type class if possible, e.g. String.startsWith()
2. Use Java utility comparison / assertion / validation method names were possible (no current examples of this)
3. Use JUnit assertion method names, though these often need to have 'assert' or 'is' prefixes removed
4. Use Hamcrest or a Hamcrest extension for the type as a reference


# Release Plan

## Major Project Milestones <a href="#h.p_jqyeid-livyq" id="h.p_jqyeid-livyq"></a>

### 0.4.2 - Current Release <a href="#h.p_u3bazqx5iwej" id="h.p_u3bazqx5iwej"></a>

***Focus: Improvements in AndHow configuration and exports***

This release should be compatible with the 0.4.0 release, but will have several methods that are deprecated in preference to some new, easier patterns for AndHow configuration.

Additionally hoping to add improved export support to allow application code to get specific groups of properties exported to a Map or other collection for use with other frameworks that take their configuration this way.

### 0.5.0 - Planned for ~~August~~ November, 2021 <a href="#h.p_rfsnuaifiwel" id="h.p_rfsnuaifiwel"></a>

***Focus: Removing deprecated methods and classes, API changes that have been waiting for an opportunity to happen***

There have been some places where early API decisions need to change, but that cannot be done without breaking users code. This release will allow AndHow to change its API and users can upgrade when they are ready.

### 1.8.0 - Unscheduled <a href="#h.p_jbhprphmiwen" id="h.p_jbhprphmiwen"></a>

***Focus: Final stable release to support JDK 1.8***

*Its hard to support JDK 1.8 and JDK 9 in the same project.  '1.8.0' is intended to represent 1.8 compatibility.  Its unclear if a parallel branch will be needed to support JDK 9 and beyond.  Currently JDK 1.8 code works with JDK 9 - 16 and most applications do not use JDK 9 modules, so there has not been an large incentive to leave JDK 1.8 behind.*

### 1.9.0 - Unscheduled <a href="#h.p_jbhprphmiwen" id="h.p_jbhprphmiwen"></a>

***Focus: Switch to JDK9 for binaries (thus the '.9' name)***

Major switch to JDK9 build and JDK9 compatible jar. After the switch to JDK9, it may not be possible to create a JDK8 compatible jar without maintaining a separate branch. If that is the case, it may just be easiest to drop JDK8 unless a lot of users object. JDK8 users could continue to use the 0.5.0 release.

### Other notes.... <a href="#h.p_zk5f4ol_iweo" id="h.p_zk5f4ol_iweo"></a>

The current JDK8 build is forwards compatible for JDK9 and beyond.

Currently it does not look like it is possible to easily create a build that is JDK 8 and JDK 9 compatible. If it is possible to do that, possibly with by using multiple Maven pom files, then the 0.9.0 release could be API changes and the switch to JDK 9. There is a [task to investigate this](https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Feeverman%2Fandhow%2Fissues%2F470\&sa=D\&sntz=1\&usg=AFQjCNF8dxbAlp04U-9439A5iyVF67LgbA).

It would also be good to push the andhow\_samples project to better represent real-world usage and have automation that builds the samples on all current JDKs (8-11) and platforms ('nux and Windows). There is a [task for this](https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Feeverman%2Fandhow-samples%2Fissues%2F5\&sa=D\&sntz=1\&usg=AFQjCNGek0OoyU5ryxMkEsDkn8bD1QPtPg).


# HowTo Release

Releasing is hard, so I'm recording this here as a reference. This walk-thru is based on the [Sonatype release guide](https://www.google.com/url?q=https%3A%2F%2Fcentral.sonatype.org%2Fpublish%2Fpublish-guide%2F\&sa=D\&sntz=1\&usg=AFQjCNHM8g8qyz1eitSQG5S7fPi2P_-vjQ) since Sonatype is where the official repository is for AndHow . After a new release, Sonatype automatically copies them over to Maven Central.

Currently requires running on Java 1.8 to ensure that 1.8 compatible jars are created (Only true for the 0.4.x releases)

### Local build

```bash
mvn clean install -P source-and-javadoc-jar,gpg-sign,release-verification
```

(Verify the '-P' argument matches the 'releaseProfiles' of the release plugin in the main pom. This ensures this test install run matches the actual release run)

This will verify if all configuration for GPG is working correctly. Check your local \~/.m2/repository/org/yarnandtail/andhow/\[version] to see if there are .asc signing files for each artifact, as well as javadocs and sources. It should look like this:

```
andhow-0.4.1-SNAPSHOT-javadoc.jar
andhow-0.4.1-SNAPSHOT-javadoc.jar.asc
andhow-0.4.1-SNAPSHOT-sources.jar
andhow-0.4.1-SNAPSHOT-sources.jar.asc
andhow-0.4.1-SNAPSHOT.jar
andhow-0.4.1-SNAPSHOT.jar.asc
andhow-0.4.1-SNAPSHOT.pom
andhow-0.4.1-SNAPSHOT.pom.asc
```

#### Verify local build

* Verify the samples project runs against the new snapshot locally using JDK 1.8 and JDK 16 (and more)
* Verify the 'shaded' andhow\.pom file does not have dependencies in it
* Sanity check size of andhow\.jar

The andhow-samples project can be tried with different compile flags as well when using JDK9+

```xml
<configuration>
    <release>8</release>
</configuration>
<!-- or -->
<configuration>
    <source>8</source>
    <target>8</target>
</configuration>
```

### Snapshot deploy to Nexus

This extra verification just ensures the gpg signing and uploads all work before actually doing the release:

```bash
mvn clean deploy
```

#### Snapshot Checks

* Delete the local .m2/repository/..../yarnandtail and verify andhow-samples can pull down and build against the snapshot.  Also check source and javadoc download.
* Verify the samples project runs against the new snapshot on Travis CI

### Release

```bash
mvn release:clean release:prepare
mvn release:perform
```

Login to [https://oss.sonatype.org/](https://www.google.com/url?q=https%3A%2F%2Foss.sonatype.org%2F\&sa=D\&sntz=1\&usg=AFQjCNGKvQ_3nYuuwn5pFE87wZtj5XJp5A)

Select the Staging Repositories on the left navigation. I only see the latest uploaded staged release when I do this. Check it out... maybe download and try it.

It sounds like its possible to do the release from command line via the nexus plugin:

```bash
mvn nexus-staging:release
```

Or In the UI, the staging repository needs to be 'closed' (no further additions), then 'Released'.

#### Verify the release has propagated

After release, the artifacts should show up in the central Maven repo - It may take some time.  Urls to check:

* <https://repo.maven.apache.org/maven2/org/yarnandtail/andhow/>
* <https://repo.maven.apache.org/maven2/org/yarnandtail/andhow-annotation-processor/>
* <https://repo.maven.apache.org/maven2/org/yarnandtail/andhow-core/>
* <https://repo.maven.apache.org/maven2/org/yarnandtail/andhow-junit5-extensions/>
* <https://repo.maven.apache.org/maven2/org/yarnandtail/andhow-parent/>
* <https://repo.maven.apache.org/maven2/org/yarnandtail/andhow-shared-test-utils/>
* <https://repo.maven.apache.org/maven2/org/yarnandtail/andhow-test-harness/>

#### Verify AndHow Samples builds

Update samples to the new release and the samples homepage branch and make sure the Travis build succeeds

### Other things to do after a release

* Update the GitHub Release to point to the new tag
* Update Readme of per the new release
* Other documentation updates per changed code?
* Testing page has a reference to the JUnit Extension version.

### Post-release readme update

This happens all the time, so I'm leaving my future self notes here...

If readme or .github pages need an update and those changes are needed on the current release (i.e. the active homepage) and the main branch:

* Make a branch from main for the changes
* Submit a PR and merge to main
* check out the homepage branch, then:
* `git cherry-pick $(git merge-base main update-branch)..update-branch`
* Then push to *homepage*


# Troubleshooting

This is a troubleshoot guide for working on / building the AndHow project itself.  If you need help with using AndHow in an application and your issue is not addressed in the User Guide, post a question in the [User Forum](https://groups.google.com/g/andhowuser) or open an [Issue/Bug](https://github.com/eeverman/andhow/issues) on the project.

### General Build Advice <a href="#h.1ud4r0wldr9l" id="h.1ud4r0wldr9l"></a>

AndHow is known to compile with JDK 8 - 16 and current Maven versions (see the [Workstation setup](/developer-guide/new-workstation-setup) page for details). However, to remove all other possibilities, try building with JDK 1.8 via maven from command line:

```bash
mvn --version #should report Maven 3.8+ and JDK 1.8.x
mvn clean test
```

If that works, the issue is with the IDE setup.

AndHow's pom.xml files specify the source and target to be 1.8, but there are some profiles that activate for other JDKs - a possible source of issues.  Setting your IDE to use JDK 1.8 may solve a build issue.  Travis and AppVeyor builds happen automatically to ensure that builds do work on other JDKs in a clean environment, so if there is a real issue, the CI will catch it.

### Issues with IntelliJ <a href="#h.ts6pndhfxk89" id="h.ts6pndhfxk89"></a>

IntelliJ is great, but it really does not do well with Maven based projects. If you are getting weird javac errors, here are some things to try.

* In ***Preferences | Build, Execution, Deployment | Compiler | Java Compiler***
  * Ensure the selected compiler is javac
  * Ensure the Use ''--relase' option is ***not*** selected. In theory this setting would help fix compile issues, but it may be causing issues for AndHow. See [Issue 630](https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Feeverman%2Fandhow%2Fissues%2F630\&sa=D\&sntz=1\&usg=AFQjCNFqWDtC_QdU4N8lp0jOVQLxmHHbVQ).
  * Verify that no special settings are listed for any over the AndHow modules (two places on the page)
* In ***File | Project Structure | Project***
  * Verify the Project SKD and language level is set to ***1.8 / 8***
* In ***File | Project Structure | Modules***
  * Ensure each module is set to language level 8\
    I think IntelliJ tries to guess what the source and target versions are from the pom and gets it wrong because the annotation-processor modules have some profile logic to determine this.

IntelliJ will also make a guess as to what the source and target Java values are for the project and *write them into the pom files* - especially the 'stubs' module for some reason.  If that happens, undo the change and check all the settings listed in the bullet points above.

If all else fails with IntelliJ, it helps to just check the project out fresh and reload it in IntelliJ. This drops all existing preferences for the the project and often fixes things.

### Issues running the andhow-samples project locally from locally compiled AndHow <a href="#h.lpxasx28cyj" id="h.lpxasx28cyj"></a>

If you are developing AndHow, making local builds and then trying to run the samples project from a snapshot of that build, problems can happen if the JDK used to build AndHow is newer than the JDK used to build the samples. The safest is to build AndHow with JDK 8, then any JDK can be used to build and run the samples. Otherwise, the JDK used to build AndHow must be the same version or older as the JDK used to build the samples.

\ <br>


# References

### Reference reading on technologies used in AndHow, or related info <a href="#h.1r0wyerrdpnw" id="h.1r0wyerrdpnw"></a>

Documentation on Annotation Processors is sparse. It seems to be the geeky subgenre of geeky Java coders. Here are a few articles and references I've come across in working on this.

[The Hacker's Guide to Javac](http://www.google.com/url?q=http%3A%2F%2Fscg.unibe.ch%2Farchive%2Fprojects%2FErni08b.pdf\&sa=D\&sntz=1\&usg=AFQjCNFj-pCMLm50EZO4dUXoDaRiGC32yg)

The article that convinced me this project was possible.

[Java Annotation Processors - An introduction](https://www.google.com/url?q=https%3A%2F%2Fcloudogu.com%2Fen%2Fblog%2FJava-Annotation-Processors_1-Intro\&sa=D\&sntz=1\&usg=AFQjCNHgmAUvtk3DgoTRSsKaTdFi5oDweQ)

A three part into to Annotation Processors. The third part gets into working with classes and types.

[Annotation processing during compilation time: Error Handling](http://www.google.com/url?q=http%3A%2F%2Fhauchee.blogspot.com%2F2015%2F11%2Fcompile-time-annotation-processing-error-handling.html\&sa=D\&sntz=1\&usg=AFQjCNHOTBjX0cDm8BbrqtkuzRg_p6d7sg)

Discussion of logging errors vs throwing errors in annotation processors.

[Maven on Java 9 and Beyond](https://nipafx.dev/maven-on-java-9/)

Good info about Maven and Java 9


# Help / Questions

If you need help with using AndHow in an application and your issue is not addressed in the [User Guide](/user-guide), post a question in the [User Forum](https://groups.google.com/g/andhowuser) or open an [Issue/Bug](https://github.com/eeverman/andhow/issues) on the project.

If you have built something you are especially proud of with AndHow, share it in the User Forum.


# Release Notes

## Current Release - 1.5.0 released Oct. 10, 2022[![javadoc](https://javadoc.io/badge2/org.yarnandtail/andhow/1.5.0/javadoc.svg)](https://javadoc.io/doc/org.yarnandtail/andhow/1.5.0) •  [Source Code](https://github.com/eeverman/andhow/tree/andhow-0.4.2) <a href="#h.p_jqdhltovin56" id="h.p_jqdhltovin56"></a>

### Maven Dependency

```xml
<dependency>
    <groupId>org.yarnandtail</groupId>
    <artifactId>andhow</artifactId>
    <version>1.5.0</version>
</dependency>

<dependency>
	<!-- Utils for unit testing apps using AndHow -->
	<groupId>org.yarnandtail</groupId>
	<artifactId>andhow-junit5-extensions</artifactId>
	<version>1.5.0</version>
	<scope>test</scope>
</dependency>
```

### Release Notes

This release jumps from 0.4.2 to 1.5.0, reflecting that AndHow has been in production long enough to be considered production ready, and there are API changes. This release removes deprecated methods, clarifies / subtly changes some behavior, and has general improvements and bug fixes. It's likely that minor application updates will be needed to upgrade from 0.4.x to 1.5.0, however, those changes are small and highlighted here.

#### Changes likely requiring application code changes

* Property builder validation methods beginning with `mustXxx` have all been renamed to be shorter and clearer in meaning. These new methods were available in 1.4.2, but 1.5.0 removes the older deprecated methods. For instance:

```
StrProp OLD_STYLE = StrProp.builder()
	.mustStartWithIgnoreCase("star").mustEndWith("ing").mustMatchRegex("star.+ing").build();

StrProp NEW_STYLE = StrProp.builder()
	.startsWithIgnoringCase("star").endsWith("ing").matches("star.+ing").build();
```

* Some AndHow initialization methods were removed (they were deprecated previously). In particular:

```
AndHow.findConfig().build();   // <-- This build() method has been removed
AndHow.instance(configuration);  // <-- This instance() method has been removed
```

These methods were replaced w/ new best practices. See [Configuring AndHow](https://www.andhowconfig.org/user-guide/configuring-andhow) and [Testing](https://www.andhowconfig.org/user-guide/testing) for documentation and examples that would replace code potentially needing the removed methods.

* Deprecated methods generally have been removed. New usage patterns are well documented in the (User Manual)\[<http://andhowconfig.org>] (Issue [#663](https://github.com/eeverman/andhow/issues/663)).

#### Behavior Changes which may impact applications

* BolProps and FlagProps now throw an exception for unrecognized values (Issue [#658](https://github.com/eeverman/andhow/issues/658)).\
  Prior to this release, BolProps and FlagProps had a list of `true` values (e.g. 'true', 'yes', 'on', 't', etc.) and considered all other non-empty values false. This was changed to prevent configuration errors where a value looks true, like 'truee', but is interpreted as false.
* FlagProps now act as flags **only** when loaded from command line (Issue [#656](https://github.com/eeverman/andhow/issues/656))\
  Prior to this release, any reference to the name of a FlagProp in any configuration source would set its value `True`, however, this behavior is only needed / desirable when used as a command line switch. To migrate, ensure that all non-command-line configuration for FlagProps fully specify the value as `True` or `False` (or an equivalent yes/no etc.)
* StdSysPropLoader & StdEnvVarLoader now trim String values (Issue [#654](https://github.com/eeverman/andhow/issues/654))\
  If your application needs to preserve whitespace from these sources, wrap the complete value in double quotes. More details about [whitespace handling is available](https://www.andhowconfig.org/user-guide/whitespace-handling).
* The `Loader.load()` method signature has changed and a few loader implementations which were not directly used were removed (Issue [#679](https://github.com/eeverman/andhow/issues/679)). This only affects users who have created custom loaders.

#### Internal changes / changes unlikely to affect users

* The ValueType.isParsable method was removed (Issue [#696](https://github.com/eeverman/andhow/issues/696)). This would only affect user who have created custom ValueTypes.

#### Bug Fixes

* Calling setConfig() during initialization is now blocked (Issue [#718](https://github.com/eeverman/andhow/issues/718))

### Past Releases

<table><thead><tr><th width="128">Release</th><th width="160">Release Date</th><th>Javadocs</th><th>Source Code</th><th>Release Notes</th></tr></thead><tbody><tr><td>0.4.2</td><td>Oct. 24, 2021</td><td><a href="https://javadoc.io/doc/org.yarnandtail/andhow/0.4.2"><img src="https://javadoc.io/badge2/org.yarnandtail/andhow/0.4.2/javadoc.svg" alt="javadoc"></a></td><td><a href="https://github.com/eeverman/andhow/tree/andhow-0.4.2">0.4.2 Source</a></td><td><a href="/release-notes/release-0.4.2">0.4.2 Release Notes</a></td></tr><tr><td>0.4.1.1</td><td>Sept. 13, 2021</td><td><a href="https://javadoc.io/doc/org.yarnandtail/andhow/0.4.1.1"><img src="https://javadoc.io/badge2/org.yarnandtail/andhow/0.4.1.1/javadoc.svg" alt="javadoc"></a></td><td><a href="https://github.com/eeverman/andhow/tree/andhow-0.4.1.1">0.4.1.1 Source</a></td><td><a href="https://github.com/eeverman/andhow/releases/tag/andhow-0.4.1.1">0.4.1.1 Release Notes</a></td></tr><tr><td>0.4.1</td><td>June 2, 2021</td><td><a href="https://javadoc.io/doc/org.yarnandtail/andhow/0.4.1"><img src="https://javadoc.io/badge2/org.yarnandtail/andhow/0.4.1/javadoc.svg" alt="javadoc"></a></td><td><a href="https://github.com/eeverman/andhow/tree/andhow-0.4.1">0.4.1 Source</a></td><td><a href="https://github.com/eeverman/andhow/releases/tag/andhow-0.4.1">0.4.1 Release Notes</a></td></tr><tr><td>0.4.0</td><td>Dec 28, 2017</td><td><a href="https://javadoc.io/doc/org.yarnandtail/andhow/0.4.0"><img src="https://javadoc.io/badge2/org.yarnandtail/andhow/0.4.0/javadoc.svg" alt="javadoc"></a></td><td><a href="https://github.com/eeverman/andhow/tree/andhow-0.4.0">0.4.0 Source</a></td><td><a href="https://github.com/eeverman/andhow/releases/tag/andhow-0.4.0">0.4.0 Release Notes</a></td></tr></tbody></table>

Releases prior to 0.4.0 should be considered experimental.&#x20;


# Release 0.4.2

### This is a past release - See [Release Notes](/release-notes) for the current version <a href="#h.p_jqdhltovin56" id="h.p_jqdhltovin56"></a>

[Javadocs](https://javadoc.io/doc/org.yarnandtail/andhow/0.4.2)  •  [Source Code](https://github.com/eeverman/andhow/tree/andhow-0.4.2)

### Maven Dependency

```xml
<dependency>
    <groupId>org.yarnandtail</groupId>
    <artifactId>andhow</artifactId>
    <version>0.4.2</version>
</dependency>

<dependency>
	<!-- Utils for unit testing apps using AndHow -->
	<groupId>org.yarnandtail</groupId>
	<artifactId>andhow-junit5-extensions</artifactId>
	<version>0.4.2</version>
	<scope>test</scope>
</dependency>
```

### Release Notes

**AndHow\.findConfig() is&#x20;*****the*****&#x20;way to find or create AndHow's configuration**

AndHow\.findConfig() should now be used any place there is a need to access the configuration for AndHow, and the configuration returned from that call is the same configuration for each call. This greatly simplifies startup configuration and usage. See samples for examples of this new best practice.

**Shorter Property validation method names**

The 'must' prefix on validation method names has been removed, for instance:

```
IntProp COUNT_DOWN = IntProp.builder().mustBeGreaterThan(1).build;  //old
IntProp COUNT_DOWN = IntProp.builder().greaterThan(1).build;  //New!
```

Other validation methods have similar renames. The prior validation methods have been deprecated.

**AndHow\.getGroupForProperty method has been removed**

This method has no user-code purpose and 'breaks' the security model. See [Issue 624](https://github.com/eeverman/andhow/issues/624).

**New JUnit 5 testing extensions simplify testing**

The are new JUnit 5 extensions in the new `andhow-junit5-extensions` are used as annotations on test classes or methods and make testing applications with AndHow much simpler. With that change, the older JUnit 4 test base has been deprecated.

#### Bug Fixes

Issue [#630](https://github.com/eeverman/andhow/issues/630): Using `javac --release=8` causing build to fail (for AndHow and apps using it)\
Issue [#615](https://github.com/eeverman/andhow/issues/615) & [#655](https://github.com/eeverman/andhow/issues/655): Generated configuration templates were unexpectedly setting values. As a result of these changes, generated templates now have empty values or commented out lines in some cases.\
Isse [#659](https://github.com/eeverman/andhow/issues/659) Trimming was not applied to non-String Property values in some cases

#### Other changes with zero or minimal impact to users of 1.4.1

* Move AndHowTestInit and TestInitLoader from test-harness to core.
* Switch to using the new JUnit 5 extensions for testing AndHow itself
* The AndHowConfiguration interface now includes all methods that were implemented in the StdConfig class. The functionality of StdConfig had grown without porting the methods back to the interface.
* BaseConfig.getDefaultLoaderList() is now an instance method, not static.
* Deprecate AndHow\.isInitialize(), which was missing the trailing 'd'. New method named `isInitialized()`
* Deprecated AndHow\.instance(config) since its usage is no longer best practice after full support of the AndHow\.findConfig() method (see above)
* Add AndHow\.setConfig(config), primarily to make testing user apps easier
* Deprecated AndHowConfig.build() since its usage is no longer best practice after full support of the AndHow\.findConfig() method (see above)
* Lots of internal changes to how configuration takes place, improving encapsilation, testability and ease of use
* Switch from Cobertura to JaCoCo for code coverage ([@alex-kar](https://github.com/alex-kar))
* Switch to new CodeCov uploader which was being deprecated by CodeCov. The new uploader along with JaCoCo adds complexity reports as an added feature ([@alex-kar](https://github.com/alex-kar))
* Fixed several small potential bugs in Loader code ([@alex-kar](https://github.com/alex-kar))
* Fixed several maven deprecation warning (Thanks [@alex-kar](https://github.com/alex-kar))
* Fixed an issue causing the build to fail on JDK 16 ([@alex-kar](https://github.com/alex-kar))
* Deprecate KeyValuePairLoader.setKeyValuePairs(String... keyValuePairs) method (unneeded / unused) ([@alex-kar](https://github.com/alex-kar))
* [JavaDocs](https://www.google.com/url?q=https%3A%2F%2Fwww.javadoc.io%2Fdoc%2Forg.yarnandtail%2Fandhow%2Flatest%2Findex.html\&sa=D\&sntz=1\&usg=AFQjCNE1HYQVB4XjshevQwOgh2kOcbSRmw)
* [Release Notes](https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Feeverman%2Fandhow%2Freleases%2Flatest\&sa=D\&sntz=1\&usg=AFQjCNExmCcH88yvMA820yQQ0vpd6zNeZQ) (Source code is available as a zip file at the bottom of the release notes)
* Source code is browsable for a given release at a [tag matching the release number](https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Feeverman%2Fandhow%2Ftags\&sa=D\&sntz=1\&usg=AFQjCNFpS6epvxkvMw0glcbLf663VIPs0A).


# FAQs

Frequently Asked Questions

### How do I pass property values as system properties from command line to tests run via Maven?

Maven adds an extra layer between the command line and the tests themselves.  Two common plugins are used to run tests within Maven:  [maven-failsafe-plugin](https://maven.apache.org/surefire/maven-failsafe-plugin/plugin-info.html) for integration tests and [maven-surefire-plugin](https://maven.apache.org/surefire/maven-surefire-plugin/plugin-info.html) for unit tests.  Both pass parameters the same way from command line:

```bash
mvn clean verify -DargLine="-DMyPropertyName=MyPropertyValue"
```

`mvn clean verify` instructs Maven to create a fresh build, run units tests (surefire), run integration tests (failsafe) and verify the tests passed.

`-DargLine="-DMyPropertyName=MyPropertyValue"` sets a System Property named `argLine`, instructing both plugins to include `-DMyPropertyName=MyPropertyValue` in the command when they invoke a new process to run the tests, resulting in passing system properties to those tests.  Quotes are needed if there are any spaces.


# Other

Catch all for related research and notes


# JUnit Extension Registration

How-To register extensions via  composed annotations, where it works, where it doesn't, and possible solutions

JUnit's extension system includes several ways to register extensions, but the most user friendly is *Composed Annotation Extension Registration* (***CAER***), where an extension is registered via a custom annotation.  JUnit's docs include a few examples ***CAER***, but there are lots of details left unaddressed, most significantly, how to configure a ***CAER*** extension.  This guide fills in those details.

## Basics of Composed Annotation Extension Registration (CAER)

If you are not familiar with ***CAER***, here is a quick example. Below is a simple extension that loads key-value pairs from the ***MyFile.props*** file into `System.properties`:

```java
public class SimpleExt implements BeforeEachCallback, AfterEachCallback {

	public void beforeEach(final ExtensionContext context) { 
		Properties props = new Properties();  
		InputStream is = getClass().getResourceAsStream("/MyFile.props");  
		props.load(is);  
		System.setProperties(props);
	}  
  
	public void afterEach(final ExtensionContext context) {  
		// reset the sys props ...
	}
}
```

The `@SimpleAnn` annotation, below, is a *composed annotation*.  It registers the extension by, itself, being annotated the `@ExtendWith` annotation:

```java
@Target({ TYPE, METHOD, ANNOTATION_TYPE })  @Retention(RUNTIME)  
@ExtendWith(SimpleExt.class)  // Just one extension registered, but it could be several
public @interface SimpleAnn {  }
```

Users can then annotate test classes or methods with `@SimpleAnn` and the extension is automatically registered.

```java
@SimpleAnn
public class MyTestClass {
    /* SimpleExt will receive lifecycle events for this test class */
}
```

***CAER*** makes it simple to use an extension, but what if the extension needs configuration? For instance, ***what if we wanted to configure which file is loaded in the\*\*\*\* ****`SimpleExt`**** \*\*\*\*example?***

## Adding Configuration to an extension registered via *CAER*

JUnit creates the extension instance for us, so there is no opportunity to pass arguments. The solution is to pass the arguments to the *annotation*, then find the annotation and its arguments in the extension.

Let's extend the example to configure which file is loaded. Here is what that could look like if a `classpathFile` property was added to `@SimpleAnn`:

```java
@SimpleAnn(classpathFile = "/MyFile.props")
public class MyTestClass {  }
```

The annotation just needs a single line added for the classpathFile property:

```java
@Target({ TYPE, METHOD, ANNOTATION_TYPE })  @Retention(RUNTIME)  
@ExtendWith(SimpleExt.class)  
public @interface SimpleAnn {
	String classpathFile();		// Added
}
```

The extension will need to find the annotation to grab the value, but how? JUnit includes two different `AnnotationSupport.findAnnotation()` methods that seem to be designed for the task. If they worked for this purpose, the extension could look like this:

```java
public class SimpleExt implements BeforeEachCallback, AfterEachCallback {
	
	// Trivial method to grab the configured value from the annotation... but it doesn't work
	public String findPath(final ExtensionContext context) {  
		SimpleAnn ann = AnnotationSupport.findAnnotation(  
			context.getElement(), SimpleAnn.class).get();  
		return ann.classpathFile();  
	}  
  
	@Override  
	public void beforeEach(final ExtensionContext context) throws IOException {
		String findPath(context);
		// load the file...
	}
}
```

There are several reasons why `findAnnotation` may not find the annotation, but the key issue is that [inheritance model of JUnit extensions](https://junit.org/junit5/docs/current/user-guide/#extensions-registration-inheritance) is different than how [Java annotations are inherited](https://docs.oracle.com/javase/8/docs/api/java/lang/annotation/Inherited.html), and the `findAnnotation` methods tend to follow the Java model. The scope of a Junit extensions follow these rules:

* An extension registered on a superclass applies to its subclass
* An extension registered on a parent class applies to all `@Nested` test classes

By contrast, annotations in Java follow these rules:

* Annotations on a superclass are only applicable to a subclass if the annotation is marked as `@Inherited`
* Nested inner classes do not inherit the parent class's annotations

## The two `findAnnotation` methods

### `AnnotationSupport.findAnnotation(Optional<AnnotatedElement>, Class<A>)` AKA ***Method 1*** <a href="#method1" id="method1"></a>

***Method 1*** ([source code](https://github.com/junit-team/junit5/blob/732a5400f80c8f446daa8b43eaa4b41b3da929be/junit-platform-commons/src/main/java/org/junit/platform/commons/support/AnnotationSupport.java#L103)) finds an annotation of type `Class<A>` on the `AnnotatedElement`. However, it will not search parent classes of `@Nested` tests, and it will only search superclasses if an annotation is marked as `@Inherited`.

### `AnnotationSupport.findAnnotation(Class<?>, Class<A>, SearchOption)` AKA ***Method 2*** <a href="#method2" id="method2"></a>

***Method 2*** ([source code](https://github.com/junit-team/junit5/blob/732a5400f80c8f446daa8b43eaa4b41b3da929be/junit-platform-commons/src/main/java/org/junit/platform/commons/support/AnnotationSupport.java#L158)) finds an annotation of type `Class<A>` on the class in the 1st argument. My guess is the method was created to address the shortcomings of ***Method 1***: This method *will* find annotations on parent classes of `@Nested` tests if the `INCLUDE_ENCLOSING_CLASSES` `SearchOption` is passed. Similar to ***Method 1***, however, it only searches superclasses if the annotation is `@Inherited`. An unfortunate aspect of this method: It was only introduced in JUnit 5.8.0 and is ***EXPERIMENTAL***.

Here is a summary of these two methods:

| Method                     | Finds superclass ann. if marked as inherited | Finds superclass ann. if NOT marked as inherited | Finds ann. on parent of @Nested class | Is well supported                  |
| -------------------------- | -------------------------------------------- | ------------------------------------------------ | ------------------------------------- | ---------------------------------- |
| [***Method 1***](#method1) | Yes                                          | No                                               | No                                    | Yes (MAINTAINED status)            |
| [***Method 2***](#method2) | Yes                                          | No                                               | Optionally                            | No (EXPERIMENTAL status) since 5.8 |

*Note: There is a* [*third method*](https://github.com/junit-team/junit5/blob/732a5400f80c8f446daa8b43eaa4b41b3da929be/junit-platform-commons/src/main/java/org/junit/platform/commons/support/AnnotationSupport.java#L126)*,but it is trivially different from **method 1.***

At first, the situation doesn't seem so bad: Just mark your annotations as `@Inherited` and use ***Method 2***. That will work for your own projects, but it's a problem if you distribute your extensions.

There is the (not so) minor issue of requiring a relatively recent version of JUnit (5.8 is just a year old) and using an EXPERIMENTAL API. More significantly, while *you* can mark your annotations as `@Inherited`, your users can re-compose them into their own annotations and may forget the `@Inherited` marker. In fact, users may need to compose your annotation into an annotation that *cannot* be inherited. If your extension breaks in this situation while others don't (because they don't need configuration) it will be seen as a bug in your extension.

## Was the annotation on a method or class?

Another complication is that extensions implementing `BeforeEachCallback` and/or `AfterEachCallback` are equally applicable to class or method level registration, thus, their associated annotation could be marked as `@Target({ TYPE, METHOD })`. When the extension's `beforeEach` and `afterEach` methods are called, there is nothing to distinguish the two types of registrations, so the extension code must search for a method annotation, check for null, then try searching for a class annotation.

Its just one more challenge for extensions developers to potentially forget or get wrong. In the `findPath` method example above, this is the reason the method will fail: `context.getElement()` returns the method, not the class, even though the annotation was on the class.

## Determining which class was the annotated class

In the configurable usage example, e.g. `@SimpleAnn(classpathFile = "/MyFile.props")`, the path used is a short, absolute path. It would be useful to accept relative paths to make it easy to, for instance, load a file named 'config.props' in the same package as the annotated class:

```java
package com.bigcorp.bigproject;
       
@SimpleAnn(classpathFile = "config.props") //results in file /com/bigcorp/bigproject/config.props
public class MyTestClass { /*  */ }
```

But how can an extension determine that? As an extension developer, you would need to reimplement and extend the existing `findAnnotation` methods to return the class on which the annotations were found. Yikes!

## Possible Solutions for Developers using *CAER*

### Option 1: Use [Method 1](broken://pages/n7QyIFF7T7TQxrAqqcam) + @Inherited <a href="#option1" id="option1"></a>

#### The Pros

* Easy w/ minimal code
* Works for many use cases
* Doesn't use an experimental API and likely works for all JUnit 5.X releases

#### The Cons

* Won't work at all for `@Nested` tests, which is a standard feature of Junit
* Users of your extension-annotation set will get errors if they re-compose your annotation and do not mark their annotation as `@Inherited`. Your code could help users a bit: If the extension cannot find its annotation, the error message could include this as a possible cause.
* If the extension needs to find the actual annotated class (for relative classpath references), you will still need to reimplement and modify the AnnotationSupport code.

### Option 2: Use the [Method 2](broken://pages/n7QyIFF7T7TQxrAqqcam) + @Inherited <a href="#option2" id="option2"></a>

#### The Pros

* Easy w/ minimal code
* Works for many use cases including `@Nested` tests

#### The Cons

* Users will get compiler errors for pre-5.8.0 JUnit releases
* If [Method 2](broken://pages/n7QyIFF7T7TQxrAqqcam) is removed in the release after 5.9.1, there would be compiler errors for newer versions as well (that is potentially a narrow band of known support).
* Like [Option 1](broken://pages/n7QyIFF7T7TQxrAqqcam), re-composing the annotation without `@Inherited` will cause errors.
* Like [Option 1](broken://pages/n7QyIFF7T7TQxrAqqcam), finding the annotated class will require added code.

### Option 3: Reimplement the needed `findAnnotation` methods as part of your distributable

#### The Pros

* Can be made to work for all uses (`@Nested` tests as well as non-`@Inherited` annotations)
* Doesn't use an experimental API and can easily work for all JUnit 5.X releases
* It's easy to add the ability to find the annotated class, rather than just the annotation

#### The Cons

* It's [a lot of code](https://github.com/eeverman/junit-extension-examples/blob/main/annotation_support_tests/src/main/java/jextension/ExtensionUtil.java) to manage, test and distribute.

#### Option 4:  Separate your extensions into class level and method level.

## Other ideas?

I'm open to suggestions and maybe even creating a separate library to provide this functionality. Contact me (@eeverman) in the [JUnit gitter discussion](https://gitter.im/junit-team/junit5) channel.

```java
// In the properties file: 'other.props' file:
// phaser: stun

	@SimpleAnn(classpathFile = "/other.props")  
	public class SimpleExtTest {  
	  
	@Test  
	public void phaserShouldBeSetToStun() {  
		assertEquals("stun", System.getProperty("phaser"));  
	}  
}
```

However, things get difficult when the annotation is on a superclass:

```java
@SimpleAnn(classpathFile = "/other.props")  
public class InheritedTestBase {  /* Empty */ }

//

public class InheritedTest extends InheritedTestBase {  


	// FAILS WITH AN ERROR!!
	@Test  
	public void phaserShouldBeSetToStun() {  
		assertEquals("stun", System.getProperty("phaser"));  
	}  
}
```

It turns out that none of the `AnnotationSupport.findAnnotation` support method will find the annotation on the super class. There is another possibility: The annotation could be on a containing class, like this:

```java
@SimpleAnn  
public class NestedTest {  
  
  
	@Nested  
	class Nested1 {  
	@Test  
	public void phaserSetToStunViaOuterClassAnnotation(ExtensionContext context) {  
	// JUnit finds and applies the annotation, thus, the system property is set  
	assertEquals("stun", System.getProperty("phaser"));  
	}  
	
	
	}  
  
}
```

First, lets see a simple example of how the extension and annotation mechanism works:

```java
public class MyExtension implements BeforeEachCallback { ... }


@Target({ TYPE, METHOD, ANNOTATION_TYPE })  
@Retention(RUNTIME)  
@ExtendWith(MyExtension.class)  
public @interface MyAnnotation { ... }


@MyAnnotation
public MyTestClass { ... }
```

The example above is typical:

* Create a custom extension that implements a set of callback methods
* Create an annotation that will register that extension (because its easier to use than manual registration)
* Use the annotation, in this case on a test class, but it could be on a test method and/or other things

The example above (with some added details) will work just fine, but things get difficult when the extension takes arguments. Since the extension is constructed by JUnit, there is no way to pass configuration to it. The only place configuration can come from is the annotation. Lets re-imagine the example above as an extension that reads properties from a file and does something with them - perhaps it sets the system properties based on them:

```java
public class ReadPropsExt implements BeforeEachCallback {

	@Override  
	public void beforeEach(final ExtensionContext context) {  
	  String path = findTheClassPathFile(context);
	  ... do something with the path ...
	}


	public void findTheClassPathFile(final ExtensionContext context) {  
	 //how do I find the annotation?? 
	}
}


@Target({ TYPE, METHOD, ANNOTATION_TYPE })  
@Retention(RUNTIME)  
@ExtendWith(MyExtension.class)  
public @interface ReadPropsAnnnotation {
	String path();
}


@ReadPropsAnnnotation(path = "propFile1.props")
public MyTestClass {

	@ReadPropsAnnnotation(path = "propFile2.props")
	@Test
	public void doTest();
}
```

Notes:

* Good to add the detail that its not possible to know if beforeEach is annotated on the method or class.
* Including a concept of distance would be helpful to differentiate ambiguous applications

The problems:

* The primary AnnotationSupport.findAnnotation method doesn't find inherited or nested annotation.
* The EXPERIMENTAL findAnnotation method can find nested annotations, but not inherited.
* None of the methods tell you what class the annotation is on
* Its impossible to tell if an extension was registered by an annotation on a method or class. But perhaps it doesn't matter, since you can search the method first.

So, if you are using an annotation to register an extension ***and the extension needs to find the annotation because the extension needs to discover its configuration***, neither of the `findAnnotation()` will work for you.


