You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by an...@apache.org on 2015/01/17 00:33:35 UTC

incubator-tamaya git commit: Updated docs.

Repository: incubator-tamaya
Updated Branches:
  refs/heads/master b853936a2 -> 332077072


Updated docs.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/33207707
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/33207707
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/33207707

Branch: refs/heads/master
Commit: 3320770728db706aa68a27458a941624c4c60960
Parents: b853936
Author: anatole <an...@apache.org>
Authored: Sat Jan 17 00:33:12 2015 +0100
Committer: anatole <an...@apache.org>
Committed: Sat Jan 17 00:33:27 2015 +0100

----------------------------------------------------------------------
 docs/API.adoc                       | 134 +++++++++++------
 docs/modules/injection.adoc         |  90 +++++++++--
 docs/requirements/Requirements.adoc | 249 +++++++++++++++++++++++++++++++
 3 files changed, 416 insertions(+), 57 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/33207707/docs/API.adoc
----------------------------------------------------------------------
diff --git a/docs/API.adoc b/docs/API.adoc
index 891b03a..8553bdd 100644
--- a/docs/API.adoc
+++ b/docs/API.adoc
@@ -211,56 +211,71 @@ public interface Configuration extends PropertySource{
     default <T> Optional<T> getOptional(String key, PropertyConverter<T> adapter);
     <T> Optional<T> getOptional(String key, Class<T> type);
 
-    public static Configuration current();
+    static Configuration current();
 }
 --------------------------------------------
 
 Hereby
 
-* +XXX getXXX(String)+ provide type safe accessors for all basic wrapper types of the JDK. Basically all this
-  methods delegate to the +getAdapted+ method, additionally passing the required +PropertyAdapter+.
-* +get(String, PropertyConverter)+ allow accessing any type, hereby also passing a +PropertyConverter+ that converts
-  the configured literal value to the type required.
+* +get(String)+ and +getOptional(String)+ provide easy access to any kind of configuration properties in their
+  String format.
+* +get(String, Class), getOptional(String, Class)+ and +getOptional(String, PropertyConverter)+ provide type safe
+  access to configuration properties. If a +PropertyConverter+ is passed, it will replace any predefined standard
+  converters defined for the type. By default several +PropertyConverter+ instances can be registered for a given
+  target type. The are managed in an ordered list, whereas the ordering is defined by +@Priority+ annotations
+  on the converters.
+* +getProperties()+ gives access to all known (=scannable) properties.
 * +with, query+ provide the extension points for adding additional functionality modelled by +ConfigOperator,
   ConfigQuery+.
 * +current()+ returns the _current_ +Configuration+
 
 
-[[TypeConversion]]
-==== Type Conversion (PropertyConverter)
+[[PropertyConverter]]
+==== Property Converters
 
-Configuration also provides support for non String types. Nevertheless internally configuration is modelled as
-pure Strings only, so non String types must be created by conerting the String values into the required target type.
-This is achieved with the help of +PropertyConverter+ instances:
+As illustrated in the previous section, +Configuration+ also to access non String types. Nevertheless internally
+all properties are strictly is modelled as pure Strings only, so non String types must be derived by converting the
+configured String values into the required target type. This is achieved with the help of +PropertyConverters+:
 
 [source,java]
 --------------------------------------------
-// @FunctionalInterface in Java 8
 public interface PropertyConverter<T>{
+    Class<T> getTargetType();
     T convert(String value);
+    //X TODO Collection<String> getSupportedFormats();
 }
 --------------------------------------------
 
-+PropertyConverter+ instances can be implemented and registered by default using the +ServiceLoader+.
-Access to converters is given by the +ConfigurationContext+ (see SPI a bit later)
++PropertyConverter+ instances can be implemented and registered by default using the +ServiceLoader+. Hereby
+a configuration values is passed to all registered converters for a type in order or their annotated +@Priority+
+value. The first non-null result of a converter is then returned as the current configuration value.
+
+Also worth mentioning is the fact, that the +PropertyConverter+ to be used can also be explicitly defined, when
+a configuration value is accessed, by using the method
++<T> T Configuration#getOptional(String, PropertyConverter<T> converter)+.
+
+Access to converters is given by the +ConfigurationContext+ (see <<SPI>>).
 
 [[ExtensionPoints]]
 === Extension Points
 
 We are well aware of the fact that this library will not be able to cover all kinds of use cases. Therefore
-we have added functional extension mechanisms to +Configuration+ that were used in other areas of the Java eco-system as well:
+we have added functional extension mechanisms to +Configuration+ that were used in other areas of the Java eco-system
+as well:
 
-* +with(UnaryOperator<Configuration> operator)+ allows to pass arbitrary functions that take adn return instances of +Configuration+.
-  They can be used to cover use cases such as filtering, configuration views, security interception and more.
-* +query(Function<Configuration,T> query)+ ConfigQuery+ defines a function returning any kind of result based on a
-  configuration instance. Queries are used for accessing/deriving any kind of data of a +Configuration+ instance,
-  e.g. accessing a +Set<String>+ of area keys present.
+* +with(ConfigOperator operator)+ allows to pass arbitrary unary functions that take and return instances of
+  +Configuration+. Operators can be used to cover use cases such as filtering, configuration views, security
+  interception and more.
+* +query(ConfigQuery query)+ allows to apply a function returning any kind of result based on a
+  +Configuration+ instance. Queries are used for accessing/deriving any kind of data based on of a +Configuration+
+  instance, e.g. accessing a +Set<String>+ of root keys present.
 
-Both interfaces hereby are functional interfaces, defined in +java.util.function+ and can be applied using Lambdas or
-method references:
+Both interfaces hereby are functional interfaces. Because of backward compatibility with Java 7 we did not use
++UnaryOperator, Function+ from the +java.util.function+ package. Nevertheless usage is similar, so you can
+use Lambdas and method references in Java 8:
 
 [source,java]
-.Applying a +ConfigurationQuery+
+.Applying a +ConfigurationQuery+ using a method reference
 --------------------------------------------
 ConfigSecurity securityContext = Configuration.current().query(ConfigSecurity::targetSecurityContext);
 --------------------------------------------
@@ -270,45 +285,50 @@ NOTE: +ConfigSecurity+ is an arbitrary class only for demonstration purposes.
 Or an operator calls basically looks quite similar:
 
 [source,java]
-.Applying a +ConfigurationOperator+
+.Applying a +ConfigurationOperator+ using a lambda expression:
 --------------------------------------------
-Configuration secured = Configuration.current().with(ConfigSecurity::secure);
+Configuration secured = Configuration.current()
+                           .with((config) ->
+                                 config.getOptional("foo").isPresent()?;
+                                 FooFilter.apply(config):
+                                 config);
 --------------------------------------------
 
 [[Mutability]]
 ==== Mutability
 
-In general Property sources can be modeled as mutable. Nevertheless the API does not support out of the box mutability,
-due to the following reasons:
+tbd
 
-* Mutability is rather complex
-* Mutability is only rarely required
-* Mutability can be implemented in various ways
 
-tbd
+[[ConfigException]]
+=== ConfigException
+
+The class +ConfigException+ models the base *runtime* exception used by the configuration system.
 
 [[SPI]]
 == SPI
 
 [[PropertySource]]
-=== PropertySource
+=== Interface PropertySource
 
 We have seen that constraining configuration aspects to simple literal key/value pairs provides us with an easy to
 understand, generic, flexible, yet expendable mechanism. Looking at the Java language features a +java.util.Map<String,
 String>+ and +java.util.Properties+ basically model these aspects out of the box.
 
-Though there are advantages in using these types as a model, there are some severe drawbacks, mostly implementation
-of these types is far not trivial or the basic model has sever drawbacks, because of backward compatibility with
-the original collection API.
+Though there are advantages in using these types as a model, there are some severe drawbacks, notably implementation
+of these types is far not trivial and the collection API offers additional functionality not useful when aiming
+for modelling simple property sources.
 
-To make implementation of a custom property source as convinient as possible only the following methods were
+To render an implementation of a custom +PropertySource+ as convenient as possible only the following methods were
 identified to be necessary:
 
 [source,java]
 --------------------------------------------
 public interface PropertySource{
+      int getOrdinal();
+      String getName();
       String get(String key);
-      boolean isBrowseable();
+      boolean isScannable();
       Map<String, String> getProperties();
 }
 --------------------------------------------
@@ -316,17 +336,31 @@ public interface PropertySource{
 Hereby
 
 * +get+ looks similar to the methods on +Map+. It may return +null+ in case no such entry is available.
-* +getProperties+ allows to extract mapped data to a +Map+. Other methods like +containsKey, keySet+ as well as
-  streaming operations then can be applied on the returned +Map+ instance.
-* But not in all scenarios a property source may be browseable. This can be evaluated by calling +isBrowseable()+.
+* +getProperties+ allows to extract all property data to a +Map<String,String>+. Other methods like +containsKey,
+  keySet+ as well as streaming operations then can be applied on the returned +Map+ instance.
+* But not in all scenarios a property source may be scannable, e.g. when looking up keys is very inefficient, it
+  may not make sense to iterator over all keys to collect the corresponding properties.
+  This can be evaluated by calling +isScannable()+. If a +PropertySource+ is defined as non scannable accesses to
+  +getProperties()+ may not return all key/value pairs that would be available when accessed directly using the
+  +String get(String)+ method.
+* +getOrdinal()+ defines the ordinal of the +PropertySource+. Property sources are managed in an ordered chain, where
+  property sources with higher ordinals override the ones with lower ordinals. If ordinal are the same, the natural
+  ordering of the fulloy qualified class names of the property source implementations are used. The reason for
+  not using +@Priority+ annotations is that property sources can define dynamically their ordinals, e.g. based on
+  a property contained with the configuration itself.
+* Finally +getName()+ returns a (unique) name that identifies the +PropertySource+ within the current
+  +ConfigurationContext+.
 
 This interface can be implemented by any kind of logic. It could be a simple in memory map, a distributed configuration
 provided by a data grid, a database, the JNDI tree or other resources. Or it can be a combination of multiple
 property sources with additional combination/aggregation rules in place.
 
++PropertySources+ are by default registered using the Java +ServiceLoader+ or the mechanism provided by the current
+ active +ServiceContext+.
+
 
 [[PropertySourceProvider]]
-==== Property Source Provider
+==== Interface PropertySourceProvider
 
 Instances of this type can be used to register multiple instances of +PropertySource+.
 
@@ -342,11 +376,25 @@ This allows to evaluate the property sources to be read/that are available dynam
 are read out and added to the current chain of +PropertySource+ instances within the current +ConfigurationContext+,
 refer also to [[ConfigurationContext]].
 
++PropertySourceProviders+ are by default registered using the Java +ServiceLoader+ or the mechanism provided by the current
+ active +ServiceContext+.
+
 [[PropertyFilter]]
-==== Property Value Filtering
+==== Interface PropertyFilter
+
+Also +PropertyFilters+ can be added to a +Configuration+. They are evaluated before a +Configuration+ instance is
+passed to the user. Filters can hereby used for multiple purposes, such as
+
+* resolving placeholders
+* masking sensitive entries, such as passwords
+* constraining visibility based on the current active user
+* ...
+
++PropertyFilters+ are by default registered using the Java +ServiceLoader+ or the mechanism provided by the current
+active +ServiceContext+. Similar to property sources they are managed in an ordered filter chain, based on the
+applied +@Priority+ annotations.
 
-Also filters can be registered (by default) using the +ServiceLoader+. Filters allow to replace or remove values
-provided by the underlying property sources. A filter is defined as follows:
+A +PropertyFilter+ is defined as follows:
 
 [source,java]
 --------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/33207707/docs/modules/injection.adoc
----------------------------------------------------------------------
diff --git a/docs/modules/injection.adoc b/docs/modules/injection.adoc
index 0eec5dc..3e4221a 100644
--- a/docs/modules/injection.adoc
+++ b/docs/modules/injection.adoc
@@ -42,26 +42,30 @@ Apache Tamaya -- Injection Module
 
 Inversion of Control (aka IoC/the Hollywood Principle) has proven to be very handy and effective in avoiding boilerplate
 code. In Java there are different frameworks available that all provide IoC mechanisms. Unfortunately IoC is not a
-built-in language feature. So for a portable solution OOTB that works also in Java SE Tamaya itself has to provide the
-according injection services. As an example refer to the following example:
+built-in language feature. So for a portable solution that works also in Java SE Tamaya itself has to provide the
+according injection services. This module adds that functionality to Tamaya. As an example refer to the following
+code snippet:
 
 [source,java]
 .Annotated Example Class
 --------------------------------------------
+package foo.bar;
+
 public class ConfiguredClass{
 
-    // resolved by default, using property name, class and package name
+    // resolved by default, using property name, class and package name: foo.bar.ConfiguredClass.testProperty
     private String testProperty;
 
-    @ConfiguredProperty(config="pluginConfig", keys={"a.b.c.key1","a.b.legacyKey"})
-    @ConfiguredProperty(config="productConfig", keys="area1.key2")
+    @ConfiguredProperty(keys={"a.b.c.key1","a.b.legacyKey",area1.key2"})
     @DefaultValue("The current \\${JAVA_HOME} env property is ${env:JAVA_HOME}.")
     String value1;
 
+    // Using a (default) String -> Integer converter
     @ConfiguredProperty(keys="a.b.c.key2")
     private int value2;
 
-    // resolved by default
+    // resolved by default as foo.bar.ConfiguredClass.accessUrl
+    // Using a (default) String -> URL converter
     @DefaultValue("http://127.0.0.1:8080/res/api/v1/info.json")
     private URL accessUrl;
 
@@ -69,7 +73,8 @@ public class ConfiguredClass{
     @NoConfig
     private Integer int1;
 
-    @ConfiguredProperty("BD")
+    // Overriding the String -> BigDecimal converter with a custom implementation.
+    @ConfiguredProperty(keys="BD")
     @WithAdapter(MyBigDecimalRoundingAdapter.class)
     private BigDecimal bigNumber;
 
@@ -77,23 +82,80 @@ public class ConfiguredClass{
 }
 --------------------------------------------
 
-The class does not show all (but most all) the possibilities that are provided. Configuring an instance of the
-class using Tamaya is very simple:
+The class does not show all (but most) possibilities provided. Configuring an instance of the
+class using Tamaya is very simple. The only thing is to pass the instance to Tamaya to let
+Tamaya inject the configuration (or throw a +ConfigException+, if this is not possible):
 
 [source,java]
 .Configuring the +ConfiguredClass+ Instance
 --------------------------------------------
 ConfiguredClass classInstance = new ConfiguredClass();
-Configuration.configure(configuredClass);
+ConfigurationInjector.configure(configuredClass);
 --------------------------------------------
 
 ==== The Annotations in detail
 
-tbd
+The +ConfigurationInjector+ interface provides methods that allow to any kind of instances be configured
+by passing the instances to +T ConfigurationInjector.getInstance().configure(T);+. The classes passed
+hereby must not be annotated with +@ConfiguredProperty+ for being configurable. By default Tamaya
+tries to determine configuration for each property of an instance passed, using the following resolution policy:
+
+Given a class +a.b.MyClass+ and a field +myField+ it would try to look up the following keys:
+[source, listing]
+--------------------------------------------
+a.b.MyClass.myField
+a.b.MyClass.my-field
+MyClass.myField
+MyClass.my-field
+myField
+my-field
+--------------------------------------------
+
+So given the following properties:
+
+[source, properties]
+--------------------------------------------
+a.b.Tenant.id=1234
+Tenant.description=Any kind of tenant.
+name=<unnamed>
+--------------------------------------------
+
+The following bean can be configured as follows:
+
+[source, java]
+--------------------------------------------
+package a.b;
+
+public final class Tenant{
+  private int id;
+  private String name;
+  private String description;
+
+  public int getId(){
+    return id;
+  }
+  public String getName(){
+    return name;
+  }
+  public String getDescription(){
+    return description;
+  }
+}
+
+Tenant tenant = ConfigurationInjector.getInstance().configure(new Tenant());
+--------------------------------------------
+
+In many cases you want to create a supplier that simply creates instances that are correctly configured as defined
+by the current context. This can be done using +Suppliers+:
+
+[source, java]
+--------------------------------------------
+Supplier<Tenant> configuredTenantSupplier = ConfigurationInjector.getInstance().getConfiguredSupplier(Tenant::new);
+--------------------------------------------
+
+
 
-The +Configuration+ interface provides static methods that allow to any kind of instances be configured
-ny just passing the instances calling +Configuration.configure(instance);+. The classes passed hereby must
-be annotated with +@ConfiguredProperty+ to define the configured properties. Hereby this annotation can be
+Hereby this annotation can be
 used in multiple ways and combined with other annotations such as +@DefaultValue+,
 +@WithLoadPolicy+, +@WithConfig+, +@WithConfigOperator+, +@WithPropertyAdapter+.
 

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/33207707/docs/requirements/Requirements.adoc
----------------------------------------------------------------------
diff --git a/docs/requirements/Requirements.adoc b/docs/requirements/Requirements.adoc
new file mode 100644
index 0000000..00d32a3
--- /dev/null
+++ b/docs/requirements/Requirements.adoc
@@ -0,0 +1,249 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+<<<
+[[Requirements]]
+== Requirements
+=== Core Configuration Requirements
+==== General
+
+Tamaya must provide a Java SE API for accessing key/value based configuration. Hereby
+
+* +Configuration+ is modelled by an interface
+* +Configuration+ is organized as key/value pairs, using a subset of functionality present on +Map<String,String>+ as
+  follows:
+  ** access a value by key (+get+)
+  ** check if a value is present (+containsKey+)
+  ** get a set of all defined keys (+keySet+)
+  ** a configuration must be convertible to a +Map+, by calling +toMap()+
+  ** a configuration must provide access to its meta information.
+* +Configuration+ value access methods must never return null.
+* The API must support undefined values.
+* The API must support passing default values, to be returned if a value is undefined.
+* The API must allow to throw exceptions, when a value is undefined. Customized exceptions hereby should be supported.
+* Properties can be stored in the classpath, on a file or accessible by URL.
+* Properties can be stored minimally in properties, xml-properties or ini-format.
+
+
+==== Minimalistic Property Source
+
+For enabling easy integration of custom built configuration sources a minimalistic API/SPI must be defined, that
+
+* is modelled by an interface
+* is a minimal subset of +Configuration+ necessary to implement a configuration.
+* must be convertible to a "Configuration+.
+
+==== Extension Points
+
+For supporting more complex scenarios, +Configuration+
+
+* must implement the composite pattern, meaning new +Configuration+ instances can be created by combining existing
+  configurations.
+* must be adaptable, by creating a new configuration by applying a +UnaryOperator<COnfiguration>+ to it.
+* must be queryable, by passing a +ConfigQuery+ to an +Configuration+ instance.
+
+
+==== Type Safety
+
+Besides Strings +Configuration+ should also support the following types:
+
+* Primitive types
+* Wrapper types
+* All other types (by using a +PropertyAdapter+
+
+Hereby type conversion should be done as follows:
+
+# Check if for the given target type an explicit adapter is registered, if so, use the registered adapter.
+#If no adapter is present, check if the target type T has static methods called +T of(String), T getInstance(String), T valueOf(String), T from(String)+. If so
+use this method to create the non value of T.
+# Check if the target type has a constructor T(String). If so, try to instantiate an instance using the constructor.
+# Give up, throw a IllegalArgument exception.
+
+=== Configuration Fomats
+
+By default Tamaya support the following configuration formats:
+
+* .properties
+* .xml properties
+* .ini files
+
+It must be possible to add additional formats by registering them with the current +ServiceContext+.
+
+=== Mutability
+
+* Configurations can be mutable, mutability can be accessed as a property.
+* Configuration can be changed by collecting the changes into a +ConfigCHangeSet+ and apply this set to the
+  given +Configuration+ instance.
+* Besides the points above, +Configuration+ is immutable.
+
+=== Serializability and Immutability of Configuration
+
+* Configuration is modelled as a service. Therefore serialization may not work. This can be mitigated by adding
+  a freeze feature, where the know key/value pairs are extracted into an immutable and serializable form.
+
+=== Configuration Combination Requirements
+
+At least the following composition policies must be supported:
+
+* override: subsequent entries override existing ones.
+* aggregate-exception: key/values were added, in case of conflicts a +ConfigException+ must be thrown.
+* aggregate-ignore-duplicates: similar to union, whereas duplicates are ignored (leaving the initial value loaded).
+* aggregate-combine: conflicting entries were resolved by adding them both to the target configuration by
+  redefining partial keys.
+* custom: any function determining the key/values to be kept must be possible
+
+When combining configuration it must also be possible to override (file/classpath) configuration by
+
+* system properties.
+* command line arguments.
+
+
+=== Configuration Injection
+
+As metnioned configuration can be injected by passing a unconfigured instance of an annotated class to the
++Configuration.configure+ static method:
+
+[source, java]
+.Configuring a POJO
+----------------------------------------------------
+MyPojo instance = new MyPojo();
+Configuration.configure(instance);
+----------------------------------------------------
+
+Hereby
+* It must be possible to define default values to be used, if no valid value is present.
+* It must be possible to define dynamic expressions, at least for default values.
+* The values configured can be reinjected, if the underlying configuration changes. This should also be the case
+  for final classes, such as Strings.
+* Reinjection should be controllable by an loading policy.
+* It must be possible to evaluate multiple keys, e.g. current keys, and as a backup deprecated keys
+  from former application releases.
+* It must be possible to evaluate multiple configurations.
+* The type conversion of the properties injected must be configurable, by defining a +PropertyAdapter+.
+* The value evaluated for a property (before type conversion) must be adaptable as well.
+* It must be possible to observe configuration changes.
+
+The following annotations must be present at least:
+
+* *@ConfiguredProperty* defining the key of the property to be evaluated. It takes an optional value, defining the
+  property name. It must be possible to add multiple annotations of this kind to define an order of evaluation
+  of possible keys.
+* *@DefaultValue* (optional) defines a default String value, to be used, when no other key is present.
+* *@WithConfig* (optional) defines the name of the configuration to be used. Similar to +@ConfiguredProperty+ multiple
+  configuration can be defined for lookup.
+* *@WithConfigOperator* allows to adapt the String value evaluated, *before* it is passed as input to injection or
+  type conversion.
+* *@WithPropertyAdapter* allows to adapt the conversion to the required target type, hereby overriding any default
+  conversion in place.
+* *@WithLoadPolicy* allows to define the policy for (re)injection of configured values.
+* *@ObservesConfigChange* allows to annotate methods that should be called on configuration changes.
+* *@DefaultAreas" allows to define a key prefix key to be used for the configured key, if no absolute key
+  is defined.
+
+=== Configuration Templates
+
+For type safe configuration clients should be able to define an interface and let it implement by the
+configuration system based on +Configuration+ available:
+
+* Clients define an interface and annotate it as required (similar to above)
+* The interface methods must not take any arguments
+* The configuration system can be called to return such an interface implementation.
+* The configuration system returns a proxy hereby providing type-safe access the values required.
+* Similar to configured types also templates support multiple values and custom adapters.
+* It is possible to listen on configuration changes for templates, so users of the templates
+  may react on configuration changes.
+
+The following snippet illustrates the requirements:
+
+[source, java]
+.Type Safe Configuration Template Example
+----------------------------------------------------
+public interface MyConfig {
+
+  @ConfiguredProperty("myCurrency")
+  @DefaultValue("CHF")
+  String getCurrency();
+
+  @ConfiguredProperty("myCurrencyRate")
+  Long getCurrencyRate();
+
+  @ConfigChange
+  default configChanged(ConfigChange event){
+     ...
+  }
+
+}
+----------------------------------------------------
+
+Templates can be accessed by calling the +Configuration.current(Class)+ method:
+
+[source, java]
+.Accessing a type safe Configuration Template
+----------------------------------------------------
+MyConfig config = Configuration.current(MyConfig.class);
+----------------------------------------------------
+
+[[RequirementsServer]]
+=== Server Configuration Requirements
+
+* Ensure Configuration can be transferred over the network easily.
+* Beside serializability text based formats for serialization in +XML+ and +JSON+ must be defined.
+* A management API must be defined, which allows to inspect the configuration in place, e.g. using
+   JMX or REST services.
+
+[[RequirementsJavaEE]]
+
+Java EE leads to the following requirements:
+
+* Configuration must be contextual, depending on the current runtime context (e.g. boot level, ear, war, ...).
+* Hereby contextual aspects can even exceed the levels described above, e.g. for SaaS scenarios.
+* Resources can be unloaded, e.g. wars, ears can be restarted.
+* The different contextual levels can also be used for overriding, e.g. application specific configuration
+may override ear or system configuration.
+* Configuration may be read from different sources (different classloaders, files, databases, remote locations).
+* Configuration may be read in different formats (deployment descriptors, +ServiceLoader+ configuration, alt-DD feature, ...)
+* JSF also knows the concept of stages.
+* Many SPI's of Java EE require the implementation of some well defined Java interface, so it would be useful if the
+   configuration solution supports easy implementation of such instances.
+* In general it would be useful to model the +Environment+ explicitly.
+* Configuration used as preferences is writable as well. This requires mutability to be modelled in way, without the
+   need of synchronization.
+* JNDI can be used for configuration as well.
+
+[[RequirementsMultitenancy]]
+
+Configurations made in the tenant or user layer override the default app configuration etc., so
+
+* It must be possible to structure Configuration in layers that can override/extend each other.
+* The current environment must be capable of mapping tenant, user and other aspects, so a corresponding configuration
+  (or layer) can be derived.
+
+[[RequirementsExtensions]]
+=== Extensions Requirements
+
+It must be possible to easily add additional functionality by implementing external functional interfaces operating
+on +Configuration+.
+
+* +UnaryOperator<Configuration>+ for converting into other version of +Configuration+.
+* +ConfigQuery<T>+ extending +Function<T, Configuration>+.
+
+[[RequirementsNonFunctional]]
+=== Non Functional Requirements
+THe following non-functional requirements must be met:
+
+* tbd
+