| :jbake-type: page |
| :jbake-status: published |
| |
| [[Core]] |
| == Apache Tamaya: Core Implementation |
| === Overview |
| |
| `tamaya-core` provides an implementation of the link:api.html[Tamaya Configuration API] and adds additional functionality |
| and building blocks for supporting SPI implementations. |
| |
| Tamaya Core contains the following artifacts: |
| |
| * A service loader implementation, configurations and further logic required to run |
| in an OSGI environment. |
| * Numerous *converters*, including an +EnumConverter+, that is a converter implementation that can automatically select |
| the currect enumeration values based on a configured entry. |
| * A configurable `BannerManager`to print Tamaya's start logo on load. |
| |
| Basically `tamaya-core` leverages the base implementations contained in Tamaya's SPI support module, so it is quite |
| small in size. All required components are implemented and registered, so basically the |
| Core module with its trasitive dependencies (API and spi-support) is a complete configuration solution. Nevertheless |
| it is also very minimalistic, but fortunately it can be easily extended/accommodated with additional features as needed. |
| |
| These extensions are managed in the extensions repository of the Tamaya project. Some of the most commonly used |
| extensions are |
| |
| * placeholder and resolution mechanisms (+org.apache.tamaya.ext:tamaya-resolver+) |
| * dynamic resource path lookup, e.g. with ant styled patterns (+org.apache.tamaya.ext:tamaya-resources+) |
| * configuration injection and configuration templates (+org.apache.tamaya.ext:tamaya-injcetion-api+) |
| * abstraction for reusable formats (+org.apache.tamaya.ext:tamaya-formats+) |
| * integration with other existing solutions (e.g. +org.apache.tamaya.ext:tamaya-spring+) |
| * configuration and configuration isolation targeting Java EE (+org.apache.tamaya.ext:tamaya-injection-ee+) |
| * dynamic configuration and configuration updates (+org.apache.tamaya.ext:tamaya-events+) |
| |
| For details about the extension modules available and their functionality refer to the link:extensions.html[extension |
| user guide]. |
| |
| |
| [[CorePropertyConverters]] |
| === Default PropertyConverters |
| |
| The `tamaya-core` module provides several +PropertyConverter+ implementations, which are automatically registered: |
| |
| [width="100%",frame="1",options="header",grid="all"] |
| |======= |
| |_Target Type_ |_Class Name_ |_Supported Formats_ |
| |java.math.BigDecimal |BigDecimalConverter |1.2345, 0xFF |
| |java.math.BigInteger |BigIntegerConverter |0xFF, 1234 |
| |java.ui.lang.Boolean |BooleanConverter |true, false, T, F, 1 ,0 |
| |java.ui.lang.Byte |ByteConverter |0xFF, MIN_VALUE, MAX_VALUE, 123 |
| |java.ui.lang.Character |CharConverter |0xFF, 'a', 'H', 123 |
| |java.ui.lang.Class |ClassConverter |<fully qualified class name> |
| |java.util.Currency |CurrencyConverter |CHF, 123 |
| |java.ui.lang.Double |DoubleConverter |1, 0xFF, 1.2334, NaN, NEGATIVE_INFITIY, POSITIVE_INFINITY, MIN_VALUE, MAX_VALUE |
| |java.time.Duration |DurationConverter |<Duration as defined by Duration.parse(String)> |
| |java.io.File |FileConverter |value -> new File(value) |
| |java.ui.lang.Float |FloatConverter |1, 0xFF, 1.2334, NaN, NEGATIVE_INFITIY, POSITIVE_INFINITY, MIN_VALUE, MAX_VALUE |
| |java.time.Instant |InstantConverter |<Instant as defined by Instant.parse(String)> |
| |java.ui.lang.Integer |IntegerConverter |1, 0xD3, MIN_VALUE, MAX_VALUE |
| |java.time.LocalDate |LocalDateConverter |<Date as defined by LocalDate.parse(String) |
| |java.time.LocalDateTime |LocalDateTimeConverter |<LocalDateTime as defined by LocalDateTime.parse(String)> |
| |java.time.LocalTime |LocalTimeConverter |<Time as defined by LocalTime.parse(String) |
| |java.ui.lang.Long |LongConverter |1, 0xD3, MIN_VALUE, MAX_VALUE |
| |java.ui.lang.Number |NumberConverter |1, 0xFF, 1.2334, NaN, NEGATIVE_INFITIY, POSITIVE_INFINITY |
| |java.time.OffsetDateTime |OffsetDateTimeConverter |<OffsetDateTime as defined by OffsetDateTime.parse(String)> |
| |java.time.OffsetTime |OffsetTimeConverter |<OffsetTime as defined by OffsetTime.parse(String)> |
| |java.util.Optional |OptionalConverter | |
| |java.nio.Path |PathConverter | |
| |java.ui.lang.Short |ShortConverter |1, 0xD3, MIN_VALUE, MAX_VALUE |
| |java.util.Supplier |SupplierConverter | |
| |java.net.URI |URIConverter |http://localhost:2020/testresource?api=true |
| |java.net.URL |URLConverter |http://localhost:2020/testresource?api=true |
| |_Enums_ |EnumConverter |<Enum item name> |
| |======= |
| |
| |
| === Registering PropertyConverters |
| |
| Additional +PropertyConverter+ classes can be implemented easily. It is recommended to register them 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 each) to enable |
| auto-discovery. |
| |
| Alternatively you can also use a +ConfigurationBuilder+ to add additional converters |
| programmatically. |
| |
| |
| [[ComponentLoadingAndPriorization]] |
| === Component Loading and Priorization |
| |
| Tamaya _Core_ in general loads all components by default 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 such a functionality with the possibility to add +@Priority+ |
| annotations to the components registered. By default, and if no annotation is added +0+ is assumed |
| 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_ |
| based on their priorities, 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 all scenarios. |
| |
| NOTE: Sorting the property sources based on their ordinal value is only the default ordering |
| principle applied. By implementing your own implementation of +ConfigurationProviderSpi+ |
| you can apply a different logic: |
| |
| |
| [[RegisteringPropertySources]] |
| === Registering Property Sources |
| |
| +PropertySource+ implementations that provide configuration properties are registered as components as described in the |
| previous section. Hereby the precedence (ordering) of property sources is not hard-coded. Instead a +Comparator<PropertySource>+ |
| can be passed to a +ConfigurationBuilder+ to perform automatic ordering of the property sources |
| registered. The default implementation hereby implements the following logic: |
| |
| . It checks for an property entry +tamaya.ordinal+ if present the value is parsed into an +int+ value and used as |
| the ordinal val value. |
| . It checks for an explicit method +int getOrdinal()+, if found its value is taken as an ordinal. |
| . It checks for a +@Priority+ annotation, if present the priority value is used as an ordinal. |
| . If none of the above works, +0+ is assumed as ordinal value. |
| . If multiple +PropertySource+ instances share the same ordinal value, they are ordered based on their fully qualified |
| class names. |
| |
| Custom implementations of the property source comparator can be applied by calling |
| +ConfigurationContextBuilder.sortPropertySources(Comparator<PropertySource>)+. The default comparator can be replaced |
| by passing the fully qualified comparator class name as system property: |
| |
| +-Dproperty-source-comparator=a.b.c.MyComparatorClass+ |
| |
| The ladder allows to adapt the ordering of auto-discovered property sources, even if the value returned by |
| +int getOrdinal()+ cannot be changed. |
| |
| |
| [[CorePropertySources]] |
| == Configuration Setup in Core |
| |
| Tamaya Core provides a minimal configuration setting, that allows you to configure SE |
| applications already easily. Basically configuration is built up by default as follows: |
| |
| . Read environment properties and add them prefixed with +env.+ |
| . Read all files found at +META-INF/javaconfiguration.properties+ |
| and +META-INF/javaconfiguration.xml+ |
| |
| |
| === 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.spisupport.propertysource+ and |
| +org.apache.tamaya.core.provider+: |
| |
| [width="100%",frame="1",options="header",grid="all"] |
| |======= |
| |_Type_ |_Class Name_ |_Ordinal Used_ |
| |META-INF/javaconfiguration.properties |JavaConfigurationProvider |100 |
| |META-INF/javaconfiguration.xml |JavaConfigurationProvider |100 |
| |JNDI Entries |JNDIPropertySource |200 |
| |Environment Properties |EnvironmentPropertySource |300 |
| |System Properties |SystemPropertySource |1000 |
| |======= |
| |
| NOTE: Similarly to property converters the property sources shown here are defined within the "tamaya-spisupport* module |
| and automatically registered with the *tamaya-core* implementation using Tamaya's auto-discovery mechanisms. |
| |
| NOTE: +JNDIPropertySource+ is provided by the `tamaya-jndi` extension module. |
| |
| |
| === 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: |
| |
| [source,java] |
| -------------------------------------------- |
| 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: |
| |
| [source,java] |
| -------------------------------------------- |
| 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: |
| |
| [source,java] |
| .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+ |
| as defined 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()+. |
| |
| |
| [[CorePropertySourceProviders]] |
| === 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+ |
| and +META-INF/javaconfiguration.xml+. |
| |
| |
| === Replacing the property value evaluation policy |
| |
| Tamaya's core implementation allows to replace the complete logic how a configuration value or the current configuration |
| properties are calculated from a given +ConfigurationContext+ by implementing the +ConfigValueEvaluator+ |
| interface: |
| |
| [source,java] |
| -------------------------------------------- |
| /** |
| * Component SPI which encapsulates the evaluation of a single or full <b>raw</b>value |
| * for a {@link ConfigurationContext}. |
| */ |
| public interface ConfigValueEvaluator { |
| |
| /** |
| * Evaluates single value using a {@link ConfigurationContext}. |
| * @param key the config key, not null. |
| * @param context the context, not null. |
| * @return the value, or null. |
| */ |
| PropertyValue evaluteRawValue(String key, ConfigurationContext context); |
| |
| /** |
| * Evaluates all property values from a {@link ConfigurationContext}. |
| * @param context the context, not null. |
| * @return the value, or null. |
| */ |
| Iterable<PropertyValue> evaluateRawValues(ConfigurationContext context); |
| |
| } |
| -------------------------------------------- |
| |
| The default implementation +DefaultConfigValueEvaluator+ implements the following logic: |
| |
| . Collect all +PropertySources+ from the context. |
| . Access +PropertyValue get(String)+ (single key access)/ +Map<String,PropertyValue> getProperties()+ |
| (config map access) from each property source and combines the previous with the next value. |
| |
| The resulting _raw_ value(s) are then finally handed over to the registered filters and finally |
| converted to the target type as required by the user API. |
| |
| |
| [[Extensions]] |
| == Adding Extensions |
| |
| Tamaya _Core_ only implements the link:api.html[API]. Many users require/wish additional functionality from a |
| configuration system. Fortunately there are numerous extensions available that add further functionality. |
| 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 link:extensions.html[extensions documentation]. |