# Apache Tamaya — Core

Anatole Tresch
<anatole@apache.org>
version 0.1.1, March 2015
Incubator

## Tamaya Core

### Overview

Tamaya Core provides an implementation of the Tamaya Configuration API and adds additional functionality and building blocks for supporting SPI implementations.

Tamaya Core contains the following artifacts:

- Implementations of `Configuration, ConfigurationContext, ConfigurationContextBuilder` ConfigurationProviderSpi+

- A `java.util.ServiceLoader` based `ServiceContext` implementation. Hereby it implements component priorization based on the `@Priority` annotations.

- A PropertyConverterManager+ that loads and stores references to all the preconfigured `PropertyConverter` instances hereby providing type conversion for all important types.

- A simple default configuration setup using the current classpath and an optional staging variable.

- It collects all `PropertySource` and `PropertySourceProvider` instances registered with the `ServiceLoader` and registers them in the global `ConfigurationContext`

- It provides a `ConfigurationContextBuilder` and allows changing the current `ConfigurationContext`.

The overall size of the library is very small. All required components are implemented and registered, so basically the Core module is a complete configuration solution. Nevertheless it is also very minimalistic, but fortunately is flexible enough to be extended/accommodated with additional features as needed, such as

- placeholder and resolution mechanisms

- dynamic resource path lookup, e.g. with ant styled patterns

- configuration injection and configuration templates

- abstraction for reusable formats

- integration with other existing solutions

- configuration and configuration isolation targeting Java EE

- dynamic configuration and configuration updates

- Configuration management extensions

- remote configuration

- and more

For details about the extension modules available and their functionality refer to the extension user guide.

### Default PropertyConverters in Core

As mentioned the Core module delivers several default `PropertyConverter` instances out of the box. Find below the listing of converters automatically registered with the Core module:

Target Type | Class Name | Supported Formats
--- | --- | ---
java.math.BigDecimal | BigDecimalConverter | 1.2345, 0xFF
java.math.BigInteger | BigIntegerConverter | 0xFF, 1234
java.lang.Boolean | BooleanConverter | true, false, T, F, 1 ,0
java.lang.Byte | ByteConverter | 0xFF, MIN_VALUE, MAX_VALUE, 123
java.lang.Character | CharConverter | 0xFF, a, H, 123
java.lang.Class | ClassConverter | <fully qualified class name>
java.util.Currency | CurrencyConverter | CHF, 123
java.lang.Double | DoubleConverter | 1, 0xFF, 1.2334, NaN, NEGATIVE_INFITIY, POSITIVE_INFINITY, MIN_VALUE, MAX_VALUE
Enums | EnumConverter | <Enum item name>
java.lang.Float | FloatConverter | 1, 0xFF, 1.2334, NaN, NEGATIVE_INFITIY, POSITIVE_INFINITY, MIN_VALUE, MAX_VALUE
java.lang.Integer | IntegerConverter | 1, 0xD3, MIN_VALUE, MAX_VALUE
LocalDate | LocalDateConverter | <Date as defined by LocalDate.parse(String)
LocalTime | LocalTimeConverter | <Time as defined by LocalTime.parse(String)
LocalDateTime | LocalDateTimeConverter | <LocalDateTime as defined by LocalDateTime.parse(String)>
java.lang.Long | LongConverter | 1, 0xD3, MIN_VALUE, MAX_VALUE
java.lang.Number | NumberConverter | 1, 0xFF, 1.2334, NaN, NEGATIVE_INFITIY, POSITIVE_INFINITY
java.lang.Short | ShortConverter | 1, 0xD3, MIN_VALUE, MAX_VALUE
java.net.URI | URIConverter | http://localhost:2020/testresource?api=true
java.net.URL | URLConverter | http://localhost:2020/testresource?api=true
ZoneId | ZoneIdConverter | Europe/Zurich

### Registering PropertyConverters

Additional `PropertyConverters` can be implemented easily. It is recommended to register then using the `java.util.ServiceLoader`, meaning you add a file under `META-INF/service/org.apache.tamaya.spi.PropertyConverter` containing the fully qualified class names of the converters to be registered (one line per each).

Alternatively you can also use a `ConfigurationContextBuilder` to add additional converters programmatically.

Note | API Implementations can be read-only thus not allowing adding additional converters programmatically.

### Component Loading and Priorization

Tamaya Core in general loads all components using the `java.util.ServiceLoader` mechanism. This means that new components must be registered by adding a file under `META-INF/service/<myInterfaceName>` containing the fully qualified implementation class names of the components to be registered (one line per each). The `ServiceLoader` itself does not provide any functionality for overriding or ordering of components. Tamaya core adds this functionality by the possibility to add `@Priority` annotations to the components registered. By default, and if no annotation is added `0` is used as priority. Hereby higher values preceed lower values, meaning

- if a singleton component is accessed from the current `ServiceContext` the component with the higher value effectively overrides/replaces any component with lower values.

- if a collection of components is obtained from the `ServiceContext` the components are ordered in order, where the ones with higher priority are before components with lower priority.

- if priorities match Tamaya Core additionally sorts them using the simple class name. This ensures that ordering is still defined and predictable in almost all scenarios.

### Registering Property Sources

PropertySources that provide configuration properties are registered as ordinary components as described in the previous section. Nevertheless the priority is not managed based on `@Priority` annotations, but based on an explicit `int getOrdinal()` method. This allows to define the ordinal/priority of a `PropertySource` explicitly. This is useful due to several reasons:

- it allows to define the ordinal as part of the configuration, thus allowing new overriding property sources being added easily.

- it allows to define the ordinal dynamically, e.g. based on the configuration location, the time of loading or whatever may be appropriate.

## Configuration Setup in Core

Tamaya Core provides a minimal, but already powerful configuration setting, that allows you to configure SE applications already easily. Basically you can provide configuration properties using the following formats and locations (from weakest to strongest):

1. Read environment properties and add them prefixed with `env.`

2. Read all files found in `META-INF/cfg/defaults.properties`

3. Read all files found in `META-INF/cfg/${tamaya.stage}/defaults.properties`

4. Read all files found in `META-INF/cfg/config.properties`

5. Read all files found in `META-INF/cfg/${tamaya.stage}/config.properties`

6. Read current system properties.

Hereby `tamaya.stage` can be set by setting an according environment property, or by applying (overriding any environment property) a corresponding system property:

    -Dtamaya.stage=test

If not set the staging locations will be ignored.

### Overview of Registered Default Property Sources and Providers

The Tamaya Core implementation provides a couple of default `PropertySource` implementations, which are automatically registered. They are all in the package `org.apache.tamaya.core.propertysource`:

Type | Class Name | Ordinal Used
--- | --- | ---
Environment Properties | EnvironmentPropertySource | 300
System Properties | SystemPropertySource | 400
Base Implementation | BasePropertySource | 1000
Properties Implementation | PropertiesPropertySource | 1000
Properties Implementation based on a URL | PropertiesFilePropertySource | 1000

There is also a class `DefaultOrdinal`, which defines several default ordinals. Beside the ordinals for system and environment properties above, there may additional default ordinals defined in the future.

### Abstract Class PropertiesFilePropertySource

The abstract class `PropertiesFilePropertySource` can be used for implementing a `PropertySource` based on a `URL` instance that points to a `.properites` file. It requires a `URL` to be passed on the constructor:

    PropertiesFilePropertySource(URL url);

#### Abstract Class PropertiesPropertySource

The abstract class `PropertiesPropertySource` can be used for implementing a `PropertySource` based on a `Properties` instance. It requires a `PropertySource` to be passed on the constructor:

    PropertiesPropertySource(Properties properties);

#### Abstract Class BasePropertySource

The abstract class `BasePropertySource` can be used for implementing custom `PropertySource` classes. It requires only one method to implemented:

Implementing a PropertySource using BasePropertySource

    public class MyPropertySource extends BasePropertySource{

        public String getName(){
            // return a unique name for the property source, e.g. based on the underlying resource. This name also
            // allows to access the property source later
        }

        public Map<String, String> getProperties(){
            // Get a map with all properties provided by this property source
            // If the property source is not scannable, the map returned may be empty.
            // In the ladder case the +boolean isScannale()+ must be overridden, since
            // by default property sources are assumed to be scannable.
        }

    }

By default the ordinal of the property sources will be 1000, unless the key `tamaya.ordinal` asdefined in `PropertySource.TAMAYA_ORDINAL` is present in the current `PropertySource`. Of course it is also possible to override the inherited `protected void initializeOrdinal(final int defaultOrdinal)`, or directly `int getOrdinal()`.

### Default PropertySourceProvider in Core

With `org.apache.tamaya.core.provider.JavaConfigurationProvider` there is also a default `PropertySourceProvider` present that loads all .properties files found at `META-INF/javaconfiguration.properties`.

## Adding Extensions

The Core module only implements the API. Many users require/wish additional functionality from a configuration system. Fortunately there are numerous extensions available that add further functionality (most of them are compatible with Java 7 and 8, so you can use regardless which version of the API you are using). Loading extensions hereby is trivial: you only are required to add the corresponding dependency to the classpath.

For detailed information on the extensions available refer to the extensions documentation.