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
basedServiceContext
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
andPropertySourceProvider
instances registered with theServiceLoader
and registers them in the globalConfigurationContext
-
It provides a
ConfigurationContextBuilder
and allows changing the currentConfigurationContext
.
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 |
|
java.net.URL |
URLConverter |
|
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):
-
Read environment properties and add them prefixed with
env.
-
Read all files found in
META-INF/cfg/defaults.properties
-
Read all files found in
META-INF/cfg/${tamaya.stage}/defaults.properties
-
Read all files found in
META-INF/cfg/config.properties
-
Read all files found in
META-INF/cfg/${tamaya.stage}/config.properties
-
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:
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.