http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/blob/8951b7be/content/documentation-new/extensions/mod_functions.adoc ---------------------------------------------------------------------- diff --git a/content/documentation-new/extensions/mod_functions.adoc b/content/documentation-new/extensions/mod_functions.adoc new file mode 100644 index 0000000..50a2b8b --- /dev/null +++ b/content/documentation-new/extensions/mod_functions.adoc @@ -0,0 +1,110 @@ +:jbake-type: page +:jbake-status: published + += Apache Tamaya - Extension: Functions + +toc::[] + +[[Functions]] +== Tamaya Functions (Extension Module) + +Tamaya _Functions_ is an extension module. Refer to the link:../extensions.html[extensions documentation] for further details. + + +=== What functionality this module provides ? + +Tamaya _Functions_ provides several functional extensions using the +ConfigOperator,ConfigQuery+ extension points. Most +functional extension are accessible from the +ConfigurationFunction+ singleton. When importing its methods statically +one can use the methods to achieve some interesting effects, e.g. + +[source,java] +------------------------------------------------------------------- +import static org.apache.tamaya.functions.ConfigurationFunctions.*; + +Set<String> sections = ConfigurationProvider.getConfiguration().with(areas("a", false).with(transitiveAreas()); +------------------------------------------------------------------- + +The expression above returns all fully qualified section names that are child sections of the root section 'a'. +So given the entries +a.b.entry1, a.b.entry2, a.a.entry3, a.b.c.entry4+ the reult would be +a, a.a, a.b, a.b.c+. + +=== Compatibility + +The module is based on Java 7, so it can be used with Java 7 and beyond. + +=== Installation + +For using the functionality shown in this document you only must add the corresponding dependency to your module: + +[source, xml] +----------------------------------------------- +<dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-functions</artifactId> + <version>{tamaya_version}</version> +</dependency> +----------------------------------------------- + + +=== The Provided Functions + +==== Functions on +ConfigurationFunctions+ + +The following sections explain the provided functions defined by +ConfigurationFunctions+ singleton. + +* *ConfigOperator filter(PropertyMatcher matcher)* creates a +ConfigOperator+ that creates a +Configuration+ + containing only keys that are selected by the given _matcher predicate_. The +PropertyMatcher+ hereby allows to evaluate not only + the _key_, but also the _value_. +* *ConfigOperator map(KeyMapper keyMapper)* creates a +ConfigOperator+ that maps the keys as defined + by the given _keyMapper_. +* *ConfigOperator section(String section)* creates a +ConfigOperator+ that creates a +Configuration+ containing only + entries that are direct or indirect members of the given section. +* *ConfigOperator section(String areaKey, boolean stripKeys)* creates a +ConfigOperator+ that creates a +Configuration+ + containing only entries that are direct or indirect members of the given section. Hereby _stripKeys_ allows to determine + if the returned entries should be relative to the search criteria {{stripKeys=true}} or absolute keys. +* *isKeyInSection(String section, String sectionKey)* allows to easily determine if a given _key_ is a direct or indirect member + of a given section. +* *boolean isKeyInSections(String key, String... sectionKeys)* allows to easily determine if one key of given + _key_ is a direct or indirect member of at least one of the given _sectionKeys_. +* *ConfigQuery<Set<String>> sections()* allows to query all the contained fully qualified section names (the ones that + also have parameters present). +* *ConfigQuery<Set<String>> transitiveSections()* allows to query all the contained fully qualified section names, + including the transitive closure of sections. +* *ConfigQuery<Set<String>> sections(final Predicate<String> predicate)* allows to query all the contained fully + qualified section names that are selected by the given _predicate_. +* *ConfigQuery<Set<String>> sections(final Predicate<String> predicate)* allows to query all the contained fully + qualified section names that are selected by the given _predicate_, including the transitive closure of sections + identified. +* *ConfigOperator sectionsRecursive(String... sectionKeys)* provides a +ConfigOperator+ that filters all sections identified + by the given _sectionKeys_ and its child sections. +* *ConfigOperator sectionRecursive(final boolean stripKeys, final String... sectionKeys)* provides a +ConfigOperator+ + that filters all sections identified by the given _sectionKeys_ and its child sections. _stripKeys_ allows to + determine if the resulting configuration should be relative to the selected areas ({{stripKeys=true}}) or + absolute (filtering only). +* *ConfigQuery<String> jsonInfo()* returns a query that converts a +Configuration+ into a JSON formatted +String+ + representation. + + +==== Functions on +PropertySourceFunctions+ + +The following sections explain the provided functions defined by +PropertySourceFunctions+ singleton. + +* *PropertySource addMetaData(PropertySource propertySource, Map<String,String> metaData)* Creates a new +PropertySource+ + with the given metadata added. +* *boolean isKeyInSection(String key, String sectionKey)* Checks if the given _key_ is a direct or indirect member of + one of the given _sectionKey_. +* *boolean isKeyInSections(String key, String... sectionKeys)* Checks if the given _key_ is a direct or indirect member of + one of one of the given _sectionKeys_. +* *Set<String> sections(Map<String, String> properties)* Extracts the sections from the given properties. +* *Set<String> transitiveSections(Map<String, String> properties)* Extracts the transitive sections from the given + properties. +* *Set<String> sections(Map<String, String> properties, final Predicate<String> predicate)* Extracts the sections + from the given properties, also filtering with the given predicate. +* *Set<String> transitiveSections(Map<String, String> properties, Predicate<String> predicate)* Extracts the transitive + sections from the given properties, also filtering with the given predicate. +* *Map<String,String> sectionsRecursive(Map<String, String> properties, String... sectionKeys)* Creates w +PropertySource+ + only containing the sections that a direct or indirect children of the given _sectionKeys_. +* *Map<String,String> sectionRecursive(Map<String, String> properties, boolean stripKeys, String... sectionKeys)* Creates w +PropertySource+ + only containing the sections that a direct or indirect children of the given _sectionKeys_. With _stripKeys_ one can + select of the returned values should be relative to its selection of be fully qualified. +* *String stripSectionKeys(String key, String... sectionKeys)* This function strips away the matching section key as given + in _sectionKeys_ from a given _key_.
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/blob/8951b7be/content/documentation-new/extensions/mod_hazelcast.adoc ---------------------------------------------------------------------- diff --git a/content/documentation-new/extensions/mod_hazelcast.adoc b/content/documentation-new/extensions/mod_hazelcast.adoc new file mode 100644 index 0000000..13487a9 --- /dev/null +++ b/content/documentation-new/extensions/mod_hazelcast.adoc @@ -0,0 +1,119 @@ +:jbake-type: page +:jbake-status: published + += Apache Tamaya - Extension: Integration with Hazelcast + +toc::[] + + +[[Consul]] +== Integration with Hazelcast (Extension Module) + +Tamaya _Hazelcast_ is an extension module. Refer to the link:../extensions.html[extensions documentation] for further details. + + +=== What functionality this module provides ? + +Tamaya _Hazelcast_ provides a property source which uses +link:http://www.hazelcast.org[Hazelcast] as configuration backend. Hereby the +module supports read-only integration (as a +HazelcastPropertySource+ as well +as a writing configuration changes back (based on Tamaya's +MutableConfiguration+ API +defined by the link:mod_mutable_config.html[tamaya-mutable-config] extension module. + + +=== Compatibility + +The module is based on Java 7, so it will not run on Java 7 and beyond. + + +=== Installation + +To use _tamaya-hazelcast_ you only must add the corresponding dependency to your module: + +[source, xml] +----------------------------------------------- +<dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-hazelcast</artifactId> + <version>{tamaya_version}</version> +</dependency> +----------------------------------------------- + + +=== The Extensions Provided + +Hazelcast integration comes basically with 2 artifacts: + +* The +org.apache.tamaya.hazelcast.HazelcastPropertySource+ is a +PropertySource+. The property source is not automatically + registered. Either register it using the _ServiceLoader_ yourself or implement + and register a corresponding `PropertySourceProvider`. +* If the +tamaya-mutable-config+ module is loaded it is possible to write property values back into the consul cluster, + by accessing a +MutableConfiguration+ using the URI +config:hazelcast+. + +Access of consul key/value pairs is through the normal Tamaya API. + + +=== The HazelcastPropertySource + +The +HazelcastPropertySource+ is not automatically registered and provides different options how to integrate +Tamaya with Hazelcast. + +[source, java] +----------------------------------------------- +/** + * Creates a new instance, hereby using {@code "Hazelcast"} as property source name and + * a default hazelcast backend created by calling {@link Hazelcast#newHazelcastInstance()}. + */ +public HazelcastPropertySource(); + +/** + * Creates a new instance, hereby using {@code "Hazelcast"} as property source name and the + * given hazelcast instance. + * @param hazelcastInstance the hazelcast instance, not null. + */ +public HazelcastPropertySource(HazelcastInstance hazelcastInstance); + +/** + * Creates a new instance, hereby using the given property source name and + * a default hazelcast backend created by calling {@link Hazelcast#newHazelcastInstance()}. + * @param name the property source name, not null. + */ +public HazelcastPropertySource(String name); + +/** + * Creates a new instance, hereby using the given property source name and + * a creating a new hazelcast backend using the given Hazelcast {@link Config}. + * @param config the hazelcast config, not null. + * @param name the property source name, not null. + */ +public HazelcastPropertySource(String name, Config config); + +/** + * Creates a new instance, hereby using the given property source name and the + * hazelcast instance. + * @param name + * @param hazelcastInstance + */ +public HazelcastPropertySource(String name, HazelcastInstance hazelcastInstance); +----------------------------------------------- + +To use hazelcast as a configuration backend, you simply create the corresponding Hazelcast instance +and use it to initialize the Tamaya property source. Given that a hazelcast backedn configuration +can be easily created asillustrated below: + +[source, java] +----------------------------------------------- +Config hazelcastConfig = new Config(); +// define config settings +HazelcastInstance hazelcastInstance = Hazelcast.newInstance(hazelcastConfig); +HazelcastPropertySource ps = new HazelcastPropertySource(hazelcastInstance); +ps.setName("myHazelcast-config"); +ps.setOrdinal(2000); +// Build your own configuration context +ConfigurationContextBuilder b = ConfigurationProvider.createNewConfigurationContextBuilder(); +b.addDefaultPropertyConverters().addDefaultPropertyFilter().addDefaultPropertySources(); +// Add the hazelcast property source (as most significant) +b.addPropertySource(ps); +// build and use the configuration +Configuration config = b.build(); +----------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/blob/8951b7be/content/documentation-new/extensions/mod_injection.adoc ---------------------------------------------------------------------- diff --git a/content/documentation-new/extensions/mod_injection.adoc b/content/documentation-new/extensions/mod_injection.adoc new file mode 100644 index 0000000..facb92c --- /dev/null +++ b/content/documentation-new/extensions/mod_injection.adoc @@ -0,0 +1,495 @@ +:jbake-type: page +:jbake-status: published + += Apache Tamaya - Extension: Injection + +toc::[] + + +[[Injection]] +== Tamaya Injection (Extension Module) + +Tamaya _Injection_ is an extension module. Refer to the link:../extensions.html[extensions documentation] for further details. + +=== What functionality this module provides ? + +Tamaya _Injection_ provides functionality for injecting configured values into beans, or creating configuration +template instances. + +Inversion of Control (aka IoC/the Hollywood Principle) has proven to be very useful 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 that works also in Java SE Tamaya itself has to provide the +according injection services. This module adds this functionality to Tamaya. + +=== Compatibility + +The module is based on Java 7, so it can be used with Java 7 and beyond. + +=== Installation + +Basically Tamaya's injection API is deployed as API artifact: + +[source, xml] +----------------------------------------------- +<dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-injection-api</artifactId> + <version>{tamaya_version}</version> +</dependency> +----------------------------------------------- + +To use injection with Java SE you must add the corresponding dependency to your module: + +[source, xml] +----------------------------------------------- +<dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-injection</artifactId> + <version>{tamaya_version}</version> +</dependency> +----------------------------------------------- + +Similarly there are other injection implementations available, targetig platforms such as + +* link:mod_spring.html[Spring, Spring Boot] +* link:mod_CDI.html[Java EE/CDI] + + +=== Core Concepts + +Basically you annotate fields or methods in your beans with +@Config+ to enable configuration injection. Tamaya +additionally defines further annotations that allo you to define additional aspects such as default values, custom +converters etc. The following example illustrates the basic functionality: +code snippet: + +[source,java] +.Annotated Example Class +-------------------------------------------- +package foo.bar; + +public class ConfiguredClass { + + // resolved by default, using property name, class and package name: foo.bar.ConfiguredClass.testProperty + private String testProperty; + + // Trying to resolve mutiple keys, with a default value, if none could be resolved + @Config({"a.b.c.key1","a.b.legacyKey",area1.key2"}, defaultValue="The current \\${JAVA_HOME} env property is ${env:JAVA_HOME}.") + String value1; + + // Typical case + @Config("a.b.c.key2") + private int value2; + + // resolved by default as foo.bar.ConfiguredClass.accessUrl + // Using a (default) String -> URL converter + @Config(defaultValue="http://127.0.0.1:8080/res/api/v1/info.json") + private URL accessUrl; + + // Config injection disabled for this property + @NoConfig + private Integer int1; + + // Overriding the String -> BigDecimal converter with a custom implementation. + @Config("BD") + @WithPropertyConverter(MyBigDecimalRoundingAdapter.class) + private BigDecimal bigNumber; + + ... +} +-------------------------------------------- + + +When configuring data or configuration classes it is also possible to auto-inject the fields identified. For activating +this feature a class must be annotated with +@ConfigAutoInject+: + +[source, java] +. An autoinjected bean class +-------------------------------------------- +package a.b; + +@ConfigAutoInject +public final class Tenant { + private int id; + private String name; + private String description; + @NoConfig // prevents auto injection for this field + private String id2; + + public int getId(){ + return id; + } + public String getName(){ + return name; + } + public String getDescription(){ + return description; + } +} +-------------------------------------------- + +These examples do not show all possibilities provided. Configuring instance of these +class using Tamaya is very simple: Just 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(); +ConfigurationInjector.configure(configuredClass); + +Tenant tenant = new Tenant(); +ConfigurationInjector.configure(tenant); +-------------------------------------------- + +NOTE: Configuration injection works similarly, when used with other integration modules, e.g. when Tamaya is used +with CDI, Spring or within an OSGI container. For further details refer also to the corresponding integration module's +documentation. + + +==== The ConfigurationInjector + +The +ConfigurationInjector+ interface provides methods that allow any kind of instances to be configured +by passing the instances to +T ConfigurationInjector.getInstance().configure(T);+. The classes passed +hereby must not be annotated with +@Config+ for being configurable. + +==== Accessing Supplier instances + +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( + new Supplier<Tenant>(){ + public Tenant get(){ + return new Tenant(); + } +}); +-------------------------------------------- + +With Java 8 it's even more simple: + +[source, java] +-------------------------------------------- +Supplier<Tenant> configuredTenantSupplier = ConfigurationInjector.getInstance().getConfiguredSupplier( + Tenant::new); +-------------------------------------------- + +Hereby this annotation can be used in multiple ways and combined with other annotations such as ++@WithLoadPolicy+, +@WithConfigOperator+, +@WithPropertyConverter+. + + +==== Minimal Example + +To illustrate the mechanism below the most simple variant of a configured class is given: + +[source,java] +.Most simple configured class +-------------------------------------------- +pubic class ConfiguredItem{ + @Config + private String aValue; +} +-------------------------------------------- + +When this class is configured, e.g. by passing it to +ConfigurationInjector.getInstance().configure(Object)+, +the following is happening: + +* The current valid +Configuration+ is evaluated by calling +Configuration cfg = ConfigurationProvider.getConfiguration();+ +* The current property value (String) is evaluated by calling +cfg.get("aValue");+ for each possible key (mutliple + keys are possible). +* if not successful, an error is thrown (+ConfigException+) +* On success, since no type conversion is involved, the value is injected. + + +=== The Annotations in detail + +==== Using `@Config` + +This is the main annotation targeting a field in a class for configuration injection. + +===== Evaluating of _configuration keys_ + +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 +-------------------------------------------- + + +This behaviour can be adapted, e.g. by using the `@ConfigDefaultSections` annotation on the +declaring type: + +-------------------------------------------- +@ConfigDefaultSections("a.b.c", "deprecated") +pubic class MyClass{ + @Config + private String myField; +} +-------------------------------------------- + +This will result in a modified lookup chain as illustrated below: + +[source, listing] +-------------------------------------------- +a.b.c.myField +a.b.c.my-field +deprecated.myField +deprecated.my-field +-------------------------------------------- + +This helps to reduce redundancy when referring to you configuration keys. Additionally +it is also possible to define absolute key entries, e.g. + +-------------------------------------------- +@ConfigDefaultSections("a.b.c") +pubic class MyClass{ + @Config("myField" /* relative */, "[absolute.key]") + private String myField; +} +-------------------------------------------- + +This will result in a lookup chain as illustrated below: + +[source, listing] +-------------------------------------------- +a.b.c.myField +absolute.key # default sections are ignored +-------------------------------------------- + + +===== Using defaults + +In the next example we explicitly define the _default_ property value: +[source,java] +-------------------------------------------- +pubic class ConfiguredItem{ + + @Config(value={"aValue", "a.b.value","a.b.deprecated.value"}, defaultValue="${env:java.version}") + private String aValue; +} +-------------------------------------------- + + +==== Automatically inject all items using `@ConfigAutoInject` + +Using `@ConfigAutoInject` allows you to automatically select all properties found for +configuration injection: + +[source,java] +-------------------------------------------- +@ConfigAutoInject +pubic class ConfiguredItem{ + + private transient int sum; + + private String a; + private String b; + Private String c; +} +-------------------------------------------- + +Adding the `@NoConfig` annotation prevents a field or method to be auto-injected from +configuration. This is especially useful, if a type is annotated as @ConfigAutoInject with auto-confiuration +turned on as follows: + +[source,java] +-------------------------------------------- +@NoConfig +private transient int sum; +-------------------------------------------- + +In this case the fields +a,b,c+ are configured, whereas the field +sum+ is ignored regarding +configuration. + + +==== Adding custom operators using `@WithConfigOperator` + +The @WithConfigOperator annotation allows you define a class of type +ConfigOperator+, to being applied +to the final +Configuration+, BEFORE the value is injected. This can be used for various use cases, e.g. +filtering or validating the visible properties for a certain use case. + +[source,java] +-------------------------------------------- + +@WithConfigOperator(MyConfigView.class) +pubic class ConfiguredItem{ + + @Config + private String a; + +} +-------------------------------------------- + + +==== Adding custom property converters using `@WithPropertyConverter` + +The @WithPropertyConverter annotation allows you to define a class of type +PropertyConverter+, to be applied +on a property configured to convert the String value to the expected injected type. This can be used for +various use cases, e.g. adding custom formats, config models, decryption. + +[source,java] +-------------------------------------------- + +pubic class ConfiguredItem{ + + @WithPropertyConverter(MyPropertyConverter.class) + @Config + private String a; + +} +-------------------------------------------- + + +==== Inject a `DynamicValue` + +Within this example we evaluate a dynamic value. This mechanism allows you to listen for configuration changes and to +commit new values exactly, when convenient for you. + +[source,java] +-------------------------------------------- +pubic class ConfiguredItem{ + + @Config(value={"aValue", "a.b.value","a.b.deprecated.value"}, defaultValue="${env:java.version}") + private DynamicValue aValue; +} +-------------------------------------------- + +The +DynamicValue+ provides you the following functionality: + +[source,java] +-------------------------------------------- +public interface DynamicValue<T> { + + T get(); + T getNewValue(); + T evaluateValue(); + T commitAndGet(); + void commit(); + void discard(); + boolean updateValue(); + + void setUpdatePolicy(UpdatePolicy updatePolicy); + UpdatePolicy getUpdatePolicy(); + void addListener(PropertyChangeListener l); + void removeListener(PropertyChangeListener l); + + boolean isPresent(); + T orElse(T other); + // Enabled with Java 8 + // T orElseGet(ConfiguredItemSupplier<? extends T> other); + // <X extends Throwable> T orElseThrow(ConfiguredItemSupplier<? extends X> exceptionSupplier) throws X; + +} + +public enum UpdatePolicy{ + IMMEDIATE, + EXPLCIT, + NEVER, + LOG_AND_DISCARD +} +-------------------------------------------- + +//Summarizing +DynamicValue+ looks somehow similar to the new +Optional+ class added with Java 8. It provides +//a wrapper class around a configured instance. Additionally this class provides functionality that gives +//active control, to manage a configured value based on a ++LoadingPolicy+: +// +//* +IMMEDEATE+ means that when the configuration system detects a change on the underlying value, the new value +// is automatically applied without any further notice. +//* +EXPLICIT+ means that a new configuration value is signalled by setting the +newValue+ property. if +getNewValue()+ +// returns a non null value, the new value can be applied by calling +commit()+. You can always access the newest value, +// hereby implicitly applying it, by accessing it via +commitAndGet()+. Also it is possible ti ignore a change by calling +// +discard()+. +//* +NEVER+ means the configured value is evaluated once and never updated. All changes are silently discarded. +//* +LOG_AND_DISCARD+ similar to +NEVER+, but changes are logged before they are discarded. + +Summarizing a +DynamicValue+ allows you + +* to reload actively updates of configured values. +* update implicitly or explicitly all changes on the value. +* add listeners that observe changes of a certain value. + +Dynamic values also allow on-the-fly reevaluation of the value by calling +evaluateValue()+. Hereby the value of the +instance is not changed. + + +===== The Loading policy enum + +The +LoadPolicy+ enum defines different configuration loading behaviour +to be applied: + +[source,java] +-------------------------------------------- +@Deprecated +public enum LoadPolicy { + /** + * The configuration keys is evaluated once, when the owning component is loaded/configured, but never updated later. + */ + INITIAL, + /** + * The configuration keys is evaluated exactly once on its first access/use lazily, but never updated later. + * @see DynamicValue#get() + * @see DynamicValue#commitAndGet() + */ + LAZY, + /** + * The configuration value is evaluated every time it is accessed. + */ + ALWAYS +} +-------------------------------------------- + +This enum type currently is used only internally, so avoid using it as of +now in your code is recommended. + + +=== Configuration Events + +Similar to CDI Tamaya publishes Configuration events, when instances were configured. It depends on the effective +event backend in use, if and how events are published: + +* when you have the CDI extension active events are published using the default CDI event mechanism. +* in all other scenarios events are delegated to the +tamaya-events+ module, if available, +* if no event delegation is available no events are published. + +The event published is very simple: + +[source,java] +-------------------------------------------- +public interface ConfiguredType { + Class getArea(); + String getName(); + Collection<ConfiguredField> getConfiguredFields(); + Collection<ConfiguredMethod> getConfiguredMethods(); + void configure(Object instance, Configuration config); +} + + +public interface ConfiguredField { + Class<?> getArea(); + Collection<String> getConfiguredKeys(); + String getName(); + String getSignature(); + Field getAnnotatedField(); + void configure(Object instance, Configuration config); +} + +public interface ConfiguredMethod { + Collection<String> getConfiguredKeys(); + Class<?>[] getParameterTypes(); + Method getAnnotatedMethod(); + String getName(); + String getSignature(); + void configure(Object instance, Configuration config); +} +---------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/blob/8951b7be/content/documentation-new/extensions/mod_jndi.adoc ---------------------------------------------------------------------- diff --git a/content/documentation-new/extensions/mod_jndi.adoc b/content/documentation-new/extensions/mod_jndi.adoc new file mode 100644 index 0000000..c3f12f8 --- /dev/null +++ b/content/documentation-new/extensions/mod_jndi.adoc @@ -0,0 +1,68 @@ +:jbake-type: page +:jbake-status: published + += Apache Tamaya - Extension: Integration with JNDI + +toc::[] + + +[[JNDI]] +== Integration with JNDI (Extension Module) +Tamaya _JNDI_ is an extension module. Refer to the link:../extensions.html[extensions documentation] for further details. + +=== What functionality this module provides ? + +Tamaya _JNDI_ provides a simple +PropertySource+ that reads values from a +JNDI context. + + +=== Compatibility + +The module is based on Java 7, so it will not run on Java 7 and beyond. + + +=== Installation + +To use _jndi_ as a configuration backend you only must add the corresponding dependency to +your module: + +[source, xml] +----------------------------------------------- +<dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-jndi</artifactId> + <version>{tamaya_version}</version> +</dependency> +----------------------------------------------- + + +=== The Functionality Provided + +Main artifact is the +JNDIPropertySource+ class, which implements a +property source based on a JNDI context: + +[source, java] +----------------------------------------------- +public class JNDIPropertySource extends BasePropertySource { + + public JNDIPropertySource(String name, Context context); + public JNDIPropertySource(String name) throws NamingException; + public JNDIPropertySource() throws NamingException; + + public void setScannable(boolean scannable); + + [...] +} +----------------------------------------------- + +By default the property source is _non scannable_, so a call the `getProperties()` +will return an empty map instance. After calling `setScannable(true);` a call to +`getProperties()` will return a String representation of the JNDI tree. Hereby +leaves of the tree are converted using `String.valueOf(leaveObject)`. + +This module automatically registers an instance of +JNDIPropertySource+ with a +default ordinal of +200+. + +You can extend this class or manually instantiate it, e.g. as part of a ++PropertySourceProvider+. If no `Context` is passed explicitly, a new ++InitialContext+ is created, without any environment parameters set. http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/blob/8951b7be/content/documentation-new/extensions/mod_jodatime.adoc ---------------------------------------------------------------------- diff --git a/content/documentation-new/extensions/mod_jodatime.adoc b/content/documentation-new/extensions/mod_jodatime.adoc new file mode 100644 index 0000000..a49fa7b --- /dev/null +++ b/content/documentation-new/extensions/mod_jodatime.adoc @@ -0,0 +1,80 @@ +:jbake-type: page +:jbake-status: published + += Apache Tamaya - Extension: JodaTime + +toc::[] + +[[JodaTime]] +== Tamaya JodaTime (Extension Module) +Tamaya _JodaTime_ is an extension module. Refer to the link:../extensions.html[extensions documentation] for further details. + +=== What functionality this module provides ? + +Tamaya _JodaTime_ is an extension module to support the usage of http://www.joda.org/joda-time/[Joda-Time] +in conjunction with Tamaya. Tamaya JodaTime defines some additional property +converters to use Joda-Time types when accessing configuration. + + +=== Installation + +To support Joda-Time types as configuration values, you only have to add the following +maven dependency to your project: + +[source, listing] +----------------------------------------------- +<dependency> + <grooupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-jodatime</artifactId> + <version>{tamaya_version}</version> +</dependency> +----------------------------------------------- + + +=== Usage + +After adding this module to your project you can retrieve +Joda-Time based values directly from a given configuration. + +[source,java] +----------------------------------------------- +Configuration configuration = ConfigurationProvider.getConfiguration(); + +DateTime pit = configuration.get("pointInTime", DateTime.class) +----------------------------------------------- + +Currently the following types are supported: + + +[width="80%",options=header] +|================================================================ +| Joda-Time target type | Supported Input Formats +.12+^.<| +org.joda.time.DateTime+ +org.joda.time.Instant+ | `yyyy-MM-dd'T'HH:mm:ss.SSSZ` + | `yyyy-MM-dd'T'HH:mm:ss.SSSz` + | `yyyy-MM-dd'T'HH:mm:ss.SSS z` + | `yyyy-MM-dd'T'HH:mm:ssZ` + | `yyyy-MM-dd'T'HH:mm:ssz` + | `yyyy-MM-dd'T'HH:mm:ss z` + | `yyyy-MM-dd'T'HH:mmZ` + | `yyyy-MM-dd'T'HH:mmz` + | `yyyy-MM-dd'T'HH:mm z` + | `yyyy-MM-dd'T'HHZ` + | `yyyy-MM-dd'T'HHz` + | `yyyy-MM-dd'T'HH z` +.2+^.<| +org.joda.time.DateTimeZone+ | `[+-]hh:mm` (reg.ex.) + | all _timezone ids_ known by Joda-Time. +.3+^.<| +org.joda.time.Duration+ | `PTa.bS` + | `PdDThHmMsS` + | `ddThh:mm:ss` +.2+^.<| +org.joda.time.Period+ | `PyYmMwWdDThHmMsS` + | `Pyyyy-mm-ddThh:mm:ss` +.4+^.<| +org.joda.time.LocalDate+ | `yyyy ['-' MM ['-' dd]]` + | `yyyy ['-' DDD]` + | `LocalDateConverter` + | `yyyy ['-' dd ['-' MM]]` +.4+^.<| +org.joda.time.LocalTime+ | `['T']` _time-element_ + | _time-element_ = HH [_minute-element_] _or_ [_fraction_] + | _minute-element_ = ':' mm [_second-element_] _or_ [_fraction_] + | _second-element_ = ':' ss [_fraction_] + | _fraction_ = ('.' _or_ ',') digit+` +|================================================================ http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/blob/8951b7be/content/documentation-new/extensions/mod_json.adoc ---------------------------------------------------------------------- diff --git a/content/documentation-new/extensions/mod_json.adoc b/content/documentation-new/extensions/mod_json.adoc new file mode 100644 index 0000000..d22ad2f --- /dev/null +++ b/content/documentation-new/extensions/mod_json.adoc @@ -0,0 +1,80 @@ +:jbake-type: page +:jbake-status: published + += Apache Tamaya - Extension: Builder + +toc::[] + + +[[JSON]] +== Tamaya JSON (Extension Module) +Tamaya _JSON_ is an extension module. Refer to the link:../extensions.html[extensions documentation] for further details. + +=== What functionality this module provides ? + +Tamaya _JSON_ provides support for reading configuration using JSON +format: + +[source, json] +----------------------------------------------- +{ + "a.b"{ + "key1": "blabla", + "key2": true, + } +} +----------------------------------------------- + +Hereby the hierarchical structure of the JSON document will be mapped to a +flat key-value pairs of type `String`, e.g. the bove will be mapped to + +[source, properties] +----------------------------------------------- +a.b.key1=blabla +a.b.key2=true +----------------------------------------------- + +This extension uses SPI defined by the +tamaya.formats+ extension module. + + +=== Compatibility + +The module is based on Java 7, so it will run on Java 7 and beyond. + + +=== Installation + +To use the JSON extension module you only must add the corresponding dependency to your module: + +[source, xml] +----------------------------------------------- +<dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-json</artifactId> + <version>{tamaya_version}</version> +</dependency> +----------------------------------------------- + +This extension also transitively requires the +tamaya.formats+ module. + + +=== Reading configuration in JSON + +For reading JSON based onfiguration most easily a +JSONFormat+ can be +used: + +[source, java] +----------------------------------------------- +ConfigurationData dataRead = ConfigurationFormats.readConfig( + getClassLoader().getResource("myFileConfig.json"), new JSONFormat())); +----------------------------------------------- + +Or, if you are fine with the _default_ mapping you can directly create a ++PropertySource+ using the _formats_ API (this works since this module +registers the _json_ format automatically using the `ServiceContext`): + +[source, java] +----------------------------------------------- +PropertySource ps = ConfigurationFormats.createPropertySource( + getClassLoader().getResource("myFileConfig.json")); +----------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/blob/8951b7be/content/documentation-new/extensions/mod_management.adoc ---------------------------------------------------------------------- diff --git a/content/documentation-new/extensions/mod_management.adoc b/content/documentation-new/extensions/mod_management.adoc new file mode 100644 index 0000000..ca38d18 --- /dev/null +++ b/content/documentation-new/extensions/mod_management.adoc @@ -0,0 +1,97 @@ +:jbake-type: page +:jbake-status: published + += Apache Tamaya - Extension: JMX Management Access + +toc::[] + + +[[ExtModel]] +== Tamaya Management (JMX Support) (Extension Module) +Tamaya _Management_ is an extension module. Refer to the link:../extensions.html[extensions documentation] for further details. + +=== What functionality this module provides ? + +The Tamaya _Management_ module provides support for registering a JMX management bean for +accessing configuration. + +=== Compatibility + +The module is based on Java 7, so it will run on Java 7 and beyond. + + +=== Installation + +To use the _management_ extension you only must add the corresponding dependency +to your module: + +[source, xml] +----------------------------------------------- +<dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-management</artifactId> + <version>{tamaya_version}</version> +</dependency> +----------------------------------------------- + + +=== The ManagedConfigMBean bean + +The management model defines the MBean of type +ManagedConfigMBean+ as follows: + + +[source,java] +----------------------------------------------------------------------------- +public interface ManagedConfigMBean { + String getJsonConfigurationInfo(); + String getXmlConfigurationInfo(); + Map<String, String> getConfiguration(); + Map<String, String> getSection(String area, boolean recursive); + Set<String> getSections(); + Set<String> getTransitiveSections(); + boolean isSectionExisting(String area); + default boolean isSectionEmpty(String area); +} +----------------------------------------------------------------------------- + +* +getJsonConfigurationInfo,getXmlConfigurationInfo+ return a JSON or XML representation of the +current configuration. +* +getConfiguration+ access the current configuration properties. +* +getSection+ allows to extract all entries below a certain subkey. With _recursive_ the query + will not only return direct children, but also recursively walk down all subsection of the + given section key. +* +getSections+ returns all current known section names. +* +getTransitiveSections+ return all sections, but also adds all transitive subsection as single + entries to the set as well. +* +isSectionExisting+ and +isSectionEmpty+ allow for quering if entries are present under the given + section keys. + + +=== Registering the ManagedConfigMBean + +For registering the current +ManagedConfigMBean+ instance to the current MBean platform server, the +following static methods are available: + +[source,java] +----------------------------------------------------------------------------- +public final class ConfigManagementSupport{ + + private JMXSupport(){} + + public static ObjectName registerMBean(); + public static ObjectName registerMBean(String context); + public static ObjectName unregisterMBean(); + public static ObjectName unregisterMBean(String context); +} +----------------------------------------------------------------------------- + +* +registerMBean+ creates a new +ManagedConfigMBean+ instance using the +ServiceContextManager+ + and registers it. Optionally an additional _context_ parameter can be passed, which allows + to register the management bean for different classloaders, e.g. for different + ears. +* +unregisterMBean+ does the oppsite than registering obviously. + +NOTE: The instance of +ManagedConfigMBean+ to be created and registered is evaluated by use og the + +ServiceContextManager+. So you can replace the bean implementation by registering your + overriding implementation using the current +ServiceContext+ (by default using + +java.util.ServiceLoader+ and +@Priority+ annotation. http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/blob/8951b7be/content/documentation-new/extensions/mod_metamodel.adoc ---------------------------------------------------------------------- diff --git a/content/documentation-new/extensions/mod_metamodel.adoc b/content/documentation-new/extensions/mod_metamodel.adoc new file mode 100644 index 0000000..bddf076 --- /dev/null +++ b/content/documentation-new/extensions/mod_metamodel.adoc @@ -0,0 +1,632 @@ +:jbake-type: page +:jbake-status: published + += Apache Tamaya - Extension: Metamodel (Configuration of Tamaya) + +toc::[] + + +[[Model]] +== Tamaya Metamodel (Configuration of Tamaya) (Extension Module) + +Tamaya _metamodel_ is an extension module. Refer to the link:../extensions.html[extensions documentation] for further details. + + +=== What functionality this module provides ? + +The Tamaya _metamodel_ module provides support for configuring the Tamaya system itself. It +allows, like a logging configuration, to configure how your configuration framework should +work, where to find configuration and how it is combined using overrides, filters etc. + +By default it uses an XML based configuration format as illustrated below: + +[source, xml] +.Extract from `tamaya-config.xml` +----------------------------------------------- +<configuration> + <!-- Context is evaluated first. --> + <context> + <context-entry name="stage">${properties:system:STAGE?default=DEV}</context-entry> + <context-entry name="configdir">${properties:system:configdir?default=.}</context-entry> + <context-entry name="app">${properties:system.APP?default=NONE}</context-entry> + <context-entry name="context">${java:org.apache.tamaya.context.Context#id()}</context-entry> + <context-entry name="company">Trivadis</context-entry> + <context-entry name="default-formats">yaml,json</context-entry> + <context-entry name="default-refresh-period">5 SECOND</context-entry> + </context> + + <!-- combinationPolicy type="" / --> + + <!-- Configuration definition. --> + + <property-sources> + <source enabled="${stage=TEST || stage=PTA || stage=PROD}" + type="env-properties"> + <filter type="PropertyMapping"> + <param name="mapTarget">ENV.</param> + </filter> + <filter type="AccessMask"> + <param name="roles">admin,power-user</param> + <param name="policy">mask</param> + <param name="mask">*****</param> + <param name="matchExpression">SEC_</param> + </filter> + </source> + <source type="sys-properties" > + <filter type="ImmutablePropertySource" /> + </source> + <source type="file" refreshable="true"> + <name>config.json</name> + <param name="location">config.json</param> + </source> + ... + </property-sources> +</configuration> +----------------------------------------------- + +The module basically provides an XML representation to the +ConfigurationContextBuilder+ API. +It creates a corresponding +ConfigurationContext+ and registers the corresponding +Configuration+ +as the system's _default_ configuration (accessible from `ConfigurationProvider.getConfiguration()`. + + +=== Compatibility + +The module is based on Java 7, so it will not run on Java 7 and beyond. + + +=== Installation + +To use _metamodel_ features you only must add the corresponding dependency to your module: + +[source, xml] +----------------------------------------------- +<dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-model</artifactId> + <version>{tamaya_version}</version> +</dependency> +----------------------------------------------- + + +=== Creating a Configuration using Meta-Configuration + +The basic feature of this module is the capability of creating a +Configuration+ completely +based on a meta-configuration file. For this the +MetaConfiguration+ main singleton +provides different methods: + +[source, java) +----------------------------------------------- +public final class MetaConfiguration { + public static void configure(); + public static void configure(URL metaConfig); + public static ConfigurationContextBuilder createContextBuilder(URL metaConfig); + public static Configuration createConfiguration(URL metaConfig); +----------------------------------------------- + +* If you have supplied your meta-configuration at `META-INF/tamaya-config.xml` you simply + call +MetaConfiguration.configure();+. This will read the meta-configuration and + configure Tamaya's _default_ configuration. Alternatively you can choose your own + metaconfiguration location by passing an alternate `URL` ro read from. +* With +MetaConfiguration.createContextBuilder()+ you can stop a step earlier: a new + instance of +ConfigurationContextBuilder+ is created and configured with all the + entries found in your meta-configuration. Also here you can optionally pass your + custom location for the meta-configuration resouce. +* Finally +MetaConfiguration.createConfiguration(URL)+ allows you to create an + arbitrary +Configuration+ instance using a meta-configuration file. The `Configuration` + instance is completely independent and not registered as _default_ configuration, so + it's lifecycle and usage is completely under your control. + + +=== MetaContext + +When thinking what are the various input parameters for determining a correct configuration, there +might be different things relevant in different scenarios, especially for developers in different +companies. A good example of such an input parameter is the current `STAGE`. All these kinf od inputs +can be summarized in some sort of meta-configuration, commonly known as a _context_. So +the metamodel extension ships with a +MetaContext+ class that allows to define a common meta-context, +that can be accessed by components as needed to determine the correct settings to be applied: + +[source, java) +----------------------------------------------- +public final class MetaContext { + + ... + + public static MetaContext getInstance(String contextName); + + /** + * Access the default context. Contexts are managed as weak references in this class. If no + * such context exists, a new instance is created. + * @return the context instance, never null. + */ + public static MetaContext getDefaultInstance(); + + /** + * Access a context by name. Contexts are managed as weak references in this class. If no + * such valid context exists, a new instance is created, using the given {@code validSupplier}. + * @param contextName the context name, not null. + * @return the context instance, never null. + */ + public static MetaContext getInstance(String contextName, Supplier<Boolean> validSupplier); + + /** + * Access the thread-based context. If no such context + * exists a new one will be created. + * @param reinit if true, clear's the thread's context. + * @return the corresponding context, never null. + */ + public static MetaContext getThreadInstance(boolean reinit); + + /** + * Access the current context, which actually is the current context, combined with the thread based + * context (overriding). + * @return the corresponding context, never null. + */ + public MetaContext getCurrentInstance(); + + /** + * Access the current context, which actually is the current context, combined with the thread based + * context (overriding). + * @param reinit if true, clear's the thread's context. + * @return the corresponding context, never null. + */ + public MetaContext getCurrentInstance(boolean reinit); + + + /** + * Method to evaluate if a context is valid. This basically depends on the + * {@code validSupplier}, if any is set. If no supplier is present the context is valid. + * + * @return true, if this context is valid. + */ + public boolean isValid(); + + /** + * Combine this context with the other contexts given, hereby only contexts are included + * which are {@code valid}, see {@link #isValid()}. + * @param contexts the context to merge with this context. + * @return the newly created Context. + */ + public MetaContext combineWith(MetaContext... contexts); + + /** + * Access the given context property. + * @param key the key, not null + * @return the value, or null. + */ + public String getProperty(String key); + + /** + * Access the given context property. + * @param key the key, not the default value. + * @param defaultValue the default value to be returned, if no value is defined, or the + * stored value's TTL has been reached. + * @return the value, default value or null. + */ + public String getProperty(String key, String defaultValue); + + /** + * Sets the given context property. + * @param key the key, not null. + * @param value the value, not null. + * @return the porevious value, or null. + */ + public String setProperty(String key, String value); + + /** + * Sets the given context property. + * @param key the key, not null. + * @param value the value, not null. + * @param ttl the time to live. Zero or less than zero means, no timeout. + * @param unit the target time unit. + * @return the porevious value, or null. + */ + public String setProperty(String key, String value, int ttl, TimeUnit unit); + + /** + * Sets the given property unless there is already a value defined. + * @param key the key, not null. + * @param value the value, not null. + */ + public void setPropertyIfAbsent(String key, String value); + + /** + * Sets the given property unless there is already a value defined. + * @param key the key, not null. + * @param value the value, not null. + * @param ttl the time to live. Zero or less than zero means, no timeout. + * @param unit the target time unit. + */ + public void setPropertyIfAbsent(String key, String value, long ttl, TimeUnit unit); + + /** + * Adds all properties given, overriding any existing properties. + * @param properties the properties, not null. + */ + public void setProperties(Map<String,String> properties); + + /** + * Adds all properties given, overriding any existing properties. + * @param properties the properties, not null. + * @param ttl the time to live. Zero or less than zero means, no timeout. + * @param unit the target time unit. + */ + public void setProperties(Map<String,String> properties, long ttl, TimeUnit unit); + + /** + * Checks if all the given properties are present. + * @param keys the keys to check, not null. + * @return true, if all the given keys are existing. + */ + public boolean checkProperties(String... keys); + + /** + * Access all the current context properties. + * @return the properties, never null. + */ + public Map<String,String> getProperties(); +} +----------------------------------------------- + +As you see, a +MetaContext+ has the following aspects: + +* there are multiple context's possible, identified by their name. +* Accessing an instance that does not yet exist, will create a new one. +* there is one shared _default_ instance. +* they store ordinary `String,String` key, value pairs. +* they can be _combined_ into a overriging hierarchy +* accessing the _default_ MetaContext returns the global instance combined with + a threaded override instance. Passing `reinit` will clear the thread instance's + data. + + +==== Configuring MetaContexts + +`MetaContext` instances can be configured in the _meta-configuration_ in the first +`meta-context` section as illustrated below: + +[source, xml] +----------------------------------------------- +<!-- Configuring the default context --> +<context> + <context-entry name="stage">${properties:system:STAGE?default=DEV}</context-entry> + <context-entry name="configdir">${properties:system:configdir?default=.}</context-entry> + <context-entry name="app">${properties:system.APP?default=NONE}</context-entry> + <context-entry name="context">${java:org.apache.tamaya.context.Context#id()}</context-entry> + <context-entry name="company">Trivadis</context-entry> + <context-entry name="default-formats">yaml,json</context-entry> + <context-entry name="default-refresh-period">5 SECOND</context-entry> +</context> +<!-- Configuring a context named 'APP' --> +<context name="APP"> + <context-entry name="application">someAppName</context-entry> +</context> +----------------------------------------------- + +As shown above multiple contexts can be configured. Keys and values are of type `String`. + + +===== Using Expressions + +As shown before, it is possible to add simple expressions, enclosed in `${}`. Hereby the +contents must be formatted as `evaluator:expression`, which then internally must be interpreted by +the +org.apache.tamaya.metamodel.internal.SimpleResolver+, which effectively reads and +applied context entries. + +Currently the following placeholders for context entries are provided: + +* properties - mapping to system properties (`properties:sys:KEY`) or + environment properties (`properties:env:KEY`) or other MetaContext + entries initialized already (`properties:ctx[:CTXNAME]:KEY`) +* java - mapping to a static method or field, returning a `String` value. + + +=== General Extensions + +Working with meta-models requires additional aspects to be generalized to separate +concerns and reuse some of the common functionality. These concepts are shown in the following +subsections. + +=== Enabled + +Things can be dynamically enabled or disabled, e.g. based on context. This can be +modelled by the +Enabled+ interface: + +[source, java] +----------------------------------------------- +public interface Enabled { + + /** + * Returns the enabled property. + * @return the enabled value. + */ + boolean isEnabled(); + + /** + * Enables/disables this property source. + * @param enabled the enabled value. + */ + void setEnabled(boolean enabled); +} +----------------------------------------------- + ++Enabled+ can be used as a mixin-logic, e.g. for decorating property sources, +property source providers, filters and converters. The decorator can also, if not +set explicitly, evaluate the _enabled_ property based on the current runtime +context. + + +=== Refreshable + +Similar to _Enabled_ things can also be refreshable. + +[source, java] +----------------------------------------------- +public interface Refreshable { + + /** + * Refreshes the given instance. + */ + void refresh(); +} +----------------------------------------------- + +This can be used to define a common API for refreshing artifctas. Similar to +_Enabled_ this can be applied as a decorator/mix-in interface to property +sources and property source providers. This property also is supported in the +XML metaconfiguration, e.g. + +[source, xml] +----------------------------------------------- +<property-sources> + <source type="file" refreshable="true"> + <name>config.json</name> + <param name="location">config.json</param> + </source> +</property-sources> +----------------------------------------------- + + +=== The MetaConfiguration XML Structure + +In general the `tamaya-config.xml` file does never apply an XML schema or +similar. Nevertheless there is a common DSL structure, which can be extended +as well (see next chapter). + +[source, xml] +----------------------------------------------- +<configuration> + <!-- PART ONE: Contexts initialization. --> + <context> + <context-entry name="stage">${properties:system:STAGE?default=DEV}</context-entry> + <context-entry name="configdir">${properties:system:configdir?default=.}</context-entry> + ... + </context> + <context name="APP"> + <context-entry name="application">someAppName</context-entry> + </context> + + <!-- PART TWO: Global settings of ConfigurationContext. --> + <!-- combinationPolicy type="" / --> + + <!-- PART THREE: Configuration definition. --> + + <property-sources> + <source enabled="${stage=TEST || stage=PTA || stage=PROD}" + type="env-properties"> + <filter type="PropertyMapping"> + <param name="mapTarget">ENV.</param> + </filter> + <filter type="AccessMask"> + <param name="roles">admin,power-user</param> + <param name="policy">mask</param> + <param name="mask">*****</param> + <param name="matchExpression">SEC_</param> + </filter> + </source> + <source type="sys-properties" > + <filter type="ImmutablePropertySource" /> + </source> + <source type="file" refreshable="true"> + <name>config.json</name> + <param name="location">config.json</param> + </source> + <source type="file" refreshable="true"> + <name>config.xml</name> + <param name="location">config.xml</param> + <param name="formats">xml-properties</param> + </source> + <source-provider type="resource"> + <name>classpath:application-config.yml</name> + <param name="location">/META-INF/application-config.yml</param> + </source-provider> + <source type="ch.mypack.MyClassSource" /> + <!--<include enabled="${stage==TEST}">TEST-config.xml</include>--> + <source-provider type="resource" enabled="${configdir != null}"> + <name>config-dir</name> + <param name="location">/${configdir}/**/*.json</param> + </source-provider> + <source type="url" refreshable="true"> + <name>remote</name> + <param name="location">https://www.confdrive.com/cfg/customerId=1234</param> + <param name="formats">json</param> + <filter type="CachedPropertySource"> + <param name="ttl">30 SECOND</param> + </filter> + </source> + </property-sources> + <property-filters> + <filter type="UsageTrackerFilter"/> + <filter type="AccessControl"> + <param name="roles">admin,power-user</param> + <param name="policy">hide</param> + <param name="expression">*.secret</param> + </filter> + <filter type="Cache"> + <param name="ttl">30000</param> + <param name="expression">cached.*</param> + </filter> + </property-filters> + <property-converters> + <!--<converter type="AllInOneConverter"/>--> + <default-converters/> + </property-converters> +</configuration> +----------------------------------------------- + +The different parts in fact are not hardcoded, but implemented +as independent components, where each of them gets access to the +XML DOM tree to read the configuration aspects of interest. +Instances related must implement the ++ interface and register it to +the `ServiceContext`. Reading order is mapped using `@Priority` +annotations. +For further details refer to the SPI section in this document. + + +== Model SPI + +=== Extending the XML DSL + +The XML DSL can be extended in various ways: + +* Basically adding a new feature maps to adding a new section to the + meta-config XML. This can be easily done, by implementing +MetaConfigurationReader+ + and do whatever is appropriate for your use case. +* For adding new expression capabilities for `MetaContext`entries +SimpleResolver+ must + be implemented. +* For allowing customized parameterization of artifacts, e.g. property sources, + property source providers, converters and filters etc. you may implement +ItemFactory+ + instances. + +=== MetaConfigurationReader + +XML metaconfiguration is effectively processed by instances of +type +org.apache.tamaya.metamodel.spi.MetaConfigurationReader+: + +[source,java] +----------------------------------------------------------- +public interface MetaConfigurationReader { + + /** + * Reads meta-configuration from the given document and configures the current + * context builder. The priority of readers is determined by the priorization policy + * implemented by the {@link org.apache.tamaya.spi.ServiceContext}, + * @param document the meta-configuration document + * @param contextBuilder the context builder to use. + */ + void read(Document document, ConfigurationContextBuilder contextBuilder); + + } +----------------------------------------------------------- + +Hereby we also see that an instance of `ConfigurationContextBuilder` is passed. +Remember, we mentioned earlier that meta-configuration basically is a XML +API to the building a configuration using a +ConfigurationContextBuilder+. So +all you can do with the meta-config XML can also be done programmatically using +the Java API. + +This module provides instances of this class for reading of meta-context, +property-sources, property source providers, converters, filters and more. +Look into the +org.apache.tamaya.metamodel.internal+ package for further details. + +New instances implementing this interface must be registered into the current ++ServiceContext+, by default the +ServiceLoader+ is used. + + +=== ItemFactory + +Instances of +ItemFactory+ allow to configure artifacts using XML data: + +[source, java] +----------------------------------------------------------- +public interface ItemFactory<T> { + + /** + * Get the factory name. + * @return the factory name, not null. + */ + String getName(); + + /** + * Create a new instance. + * @param parameters the parameters for configuring the instance. + * @return the new instance, not null. + */ + T create(Map<String,String> parameters); + + /** + * Get the target type created by this factory. This can be used to + * assign the factory to an acording item base type, e.g. a PropertySource, + * PropertySourceProvider, PropertyFilter etc. + * @return the target type, not null. + */ + Class<? extends T> getArea(); + +} +----------------------------------------------------------- + +The factory's name hereby is used as a short cut, e.g. have a look at the following +XML snippet defining a `PropertySource` to be added: + +[source, xml] +----------------------------------------------------------- +<source type="file" refreshable="true"> + <name>config.json</name> + <param name="location">config.json</param> +</source> +----------------------------------------------------------- + +In the above snippet _file_ equals to the factory name, which provides the user +a simple to use short name, instead of adding the fully qualified classname +(which is always possible). + +The _location_ paramter with its value is passed as `Map` to the `create` method. + + +=== ItemFactoryManager + +This singleton class manages the _ItemFactory_ instances found, hereby allowing +accessing and registering instances. This singleton is actually used by the +component parsers (type `MetaConfigurationReader`). + +[source, java] +----------------------------------------------------------- +public final class ItemFactoryManager { + + ... + + public static ItemFactoryManager getInstance(); + + public <T> List<ItemFactory<T>> getFactories(Class<T> type); + public <T> ItemFactory<T> getFactory(Class<T> type, String id); + + public <T> void registerItemFactory(ItemFactory<T> factory); + +} +----------------------------------------------------------- + + +=== Extended Implementations + +The package +org.apache.tamaya.metamodel.ext+ contains a few useful +implementations that also can be used in your meta-configuration and +show how mixin-functionality can be added without touching property source +implementations. + +As of now the package contains + +* +EnabledPropertySource+: a decorator for a `PropertySource` + adding the capability to _enable/disable_ the property source. +* +EnabledPropertySourceProvider+ a decorator for a `PropertySourceProvider` + adding the capability to _enable/disable_ the property source provider. +* +RefreshablePropertySource+: a decorator for a `PropertySource` + adding the capability to _refresh_ the property source. +* +EnabledPropertySourceProvider+ a decorator for a `PropertySourceProvider` + adding the capability to _refresh_ the property source provider. + +Not yet implemented but planned are implementations to add the following +functionality: + +* _caching_ of entries for a given time. +* _immutability_ of entries, so a configuration data (or parts of it) will + never change later. http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/blob/8951b7be/content/documentation-new/extensions/mod_microprofile.adoc ---------------------------------------------------------------------- diff --git a/content/documentation-new/extensions/mod_microprofile.adoc b/content/documentation-new/extensions/mod_microprofile.adoc new file mode 100644 index 0000000..9d5951d --- /dev/null +++ b/content/documentation-new/extensions/mod_microprofile.adoc @@ -0,0 +1,93 @@ +:jbake-type: page +:jbake-status: published + += Apache Tamaya - Extension: Microprofile Implementation + +toc::[] + + +[[Spring]] +== Tamaya Microprofile Implementation (Extension Module) + +Tamaya _Microprofile_ is an extension module. Refer to the link:../extensions.html[extensions documentation] for further details. + + +=== What functionality this module provides ? + +Tamaya _Microprofile_ currently provides full integration for the Microprofile Configuration API: + +* A Microprofile +ConfigSource+ implementation can be used with Tamaya. +* A Tamaya +PropertySource+ can be used with any Microprofile implementation. +* The same is also true for +Converter,PropertyConverter+. +* Nevertheless Tamaya also fully implements the Microprofile API and also successfully is compatible with the + Microprofile TCK. + + +=== Compatibility + +Both modules are based on Java 8, so they will run on Java 8 and beyond. The implemented Microprofile API is currently +version 1.1. + + +=== Installation + +To benefit from Tamaya Microprofile you only must one of the following dependencies to your module: + +[source, xml] +----------------------------------------------- +<dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-microprofile</artifactId> + <version>{tamaya_version}</version> +</dependency> +----------------------------------------------- + + +=== Using Microprofile API + +Refer to http://microprofile.io/project/eclipse/microprofile-config for details on how the API works and should be used. In general, you will see +many similarities with Tamaya, since Tamaya heavily influenced the design of microprofile.io regarding configuration. +Nevertheless Tamaya's API is much more complete and provides far more feature as of now. Further changes in this area +may be good to be expected, since as of now also a corresponding specification (JSR) has been started and will +be supported by Tamaya as well. + +[source, java] +-------------------------------------------------------- +// SE API + +Config config = ConfigProvider.getConfig(); +String serverUrl = config.getValue("acme.myprj.some.url", String.class); +callToServer(serverUrl); + +// ===================================================================== + +// CDI Injection API + +@ApplicationScoped +public class InjectedConfigUsageSample { + + @Inject + private Config config; + + //The property myprj.some.url must exist in one of the configsources, otherwise a + //DeploymentException will be thrown. + @Inject + @ConfigProperty(name="myprj.some.url") + private String someUrl; + //The following code injects an Optional value of myprj.some.port property. + //Contrary to natively injecting the configured value this will not lead to a + //DeploymentException if the configured value is missing. + @Inject + @ConfigProperty(name="myprj.some.port") + private Optional<Integer> somePort; + //Injects a Provider for the value of myprj.some.dynamic.timeout property to + //resolve the property dynamically. Each invocation to Provider#get() will + //resolve the latest value from underlying Config. + //The existence of configured values will get checked during startup. + //Instances of Provider<T> are guaranteed to be Serializable. + @Inject + @ConfigProperty(name="myprj.some.dynamic.timeout", defaultValue="100") + private javax.inject.Provider<Long> timeout; +} +-------------------------------------------------------- + http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/blob/8951b7be/content/documentation-new/extensions/mod_mutable_config.adoc ---------------------------------------------------------------------- diff --git a/content/documentation-new/extensions/mod_mutable_config.adoc b/content/documentation-new/extensions/mod_mutable_config.adoc new file mode 100644 index 0000000..237572c --- /dev/null +++ b/content/documentation-new/extensions/mod_mutable_config.adoc @@ -0,0 +1,236 @@ +:jbake-type: page +:jbake-status: published + += Apache Tamaya - Extension: Mutable Configuration + +toc::[] + + +[[MutableConfiguration]] +== Tamaya Mutable Configuration (Extension Module) + +Tamaya _Mutable Configuration_ is an extension module. Refer to the link:../extensions.html[extensions documentation] for further details. + + +=== What functionality this module provides ? + +Tamaya +Configuration+ by default is read-only, which covers must of the use cases. But there are many legit scenarios +where configuration should be written back to backend systems or the local file system. This module adds this +functionality. + + +=== Compatibility + +The module is based on Java 7, so it can be used with Java 7 and beyond. + + +=== Installation + +To benefit from configuration mutability support you only must add the corresponding dependency to your module: + +[source, xml] +----------------------------------------------- +<dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-mutable-config</artifactId> + <version>{tamaya_version}</version> +</dependency> +----------------------------------------------- + + +=== Core Architecture + +==== Accessing MutableConfiguration + +The core of the module is the +MutableConfigurationProvider+ singleton, which provides access to +MutableConfiguration+ +instance, which extends +Configuration+. This interface adds additional methods to add/update or remove property values. +Hereby each +MutableConfiguration+ manages a transaction like context, which includes +a UUID that identifes a change. +Backends for writing changes applied umst implement +MutablePropertySource+, which extends +PropertySource+. +Registrations and ordering policies are exact the same as with ordinary property sources, but +mutable property sources can be targeted by config write operations. + +The example below shows how a +MutableConfiguration+ can be obtained ,values added, removed and +finally changes written back to the backend: + +[source,java] +.Accessing and changing configuration +-------------------------------------------- +MutableConfiguration config = MutableConfigurationProvider + .createMutableConfiguration(); +config.put("newKey", "newValue") + .put("anotherKey", "updatedValue") + .remove("valueNotValid") + .store(); +-------------------------------------------- + +In the above scenario we use the system's _default_ configuration as the backend to be used. +We can also pass any +Configuration+ to render it into a mutable instance, e.g. + +[source,java] +.Explicitly passing the backing configuration +-------------------------------------------- +Configuration config = ...; +MutableConfiguration config = MutableConfigurationProvider + .createMutableConfiguration(config); +-------------------------------------------- + +NOTE: If a configuration does not contain any +MutablePropertySource+ instances, + a +ConfigurationException+ is thrown since it would not be able to accept + any changes. + + +Following we show the possible methods you can use to create a +MutableConfiguration+. +We will show in the following sections more details on the options provided... + +[source, java] +--------------------------------------------- +public final class MutableConfigurationProvider { + + private MutableConfigurationProvider(){} + + public static MutableConfiguration createMutableConfiguration(); + public static MutableConfiguration createMutableConfiguration( + ChangePropagationPolicy changePropgationPolicy); + public static MutableConfiguration createMutableConfiguration(Configuration configuration); + public static MutableConfiguration createMutableConfiguration( + Configuration configuration, + ChangePropagationPolicy changePropgationPolicy); + + [...] +} +--------------------------------------------- + +As we have not yet shown it, +MutableConfiguration+ is defined as follows: + +[source, java] +--------------------------------------------- +public interface MutableConfiguration extends Configuration { + + void store(); + + ConfigChangeRequest getConfigChangeRequest(); + ChangePropagationPolicy getChangePropagationPolicy(); + + MutableConfiguration put(String key, String value); + MutableConfiguration putAll(Map<String, String> properties); + MutableConfiguration remove(Collection<String> keys); + MutableConfiguration remove(String... keys); + +} +--------------------------------------------- + + +===== Targeting specific MutablePropertySources + +A +Configuration+ may have multiple +MutablePropertySource+ instances present. These are members of Tamaya's ordered list of ++PropertySources+ to evaluate the configuration. Nevertheless writing back changes requires additional aspects to +be considered: +* Should changes written target all mutable property sources? Or should a change only + target the most significant instance (hereby not writing the change to less significant property sources)? +* Or should a change be applied only to specific mutable property source(s), regardless its position in the + processing chain? + +Therefore a _default_ +ChangePropagationPolicy+ can be applied on a +MutableConfiguration+ instance, which allows to +control this aspect: + +[source,java] +.Explicitly passing the backing configuration +-------------------------------------------- +public interface ChangePropagationPolicy { + /** + * Method being called when a multiple key/value pairs are added or updated. + * @param propertySources all property sources, including read-only property sources, of the current configuration, + * never null. + * @param configChange the configuration change, not null. + */ + void applyChange(ConfigChangeRequest configChange, Collection<PropertySource> propertySources); +} +-------------------------------------------- + +By default, changes are applied to all registered +MutablePropertySource+ instances +similarly. + +The +MutableConfigurationProvider+ singleton also provides the most common +change propagation policy implementations: + +[source, java] +--------------------------------------------- +public final class MutableConfigurationProvider { + + [...] + + public static ChangePropagationPolicy getApplyAllChangePolicy(); + public static ChangePropagationPolicy getApplyMostSignificantOnlyChangePolicy(); + public static ChangePropagationPolicy getApplySelectiveChangePolicy(String... propertySourceNames); + public static ChangePropagationPolicy getApplyNonePolicy(); +} +--------------------------------------------- + + +==== Some Aspects to consider + +Due to Tamaya's design the effective effect of your changes to the overall configuration, cannot +be sometimes a bit tricky to be predicted, since it depends on several aspects: + +. is the corresponding configuration resource configured as part of the current system's configuration? +. what is the +PropertySource's+ priority within the configuration context? Is it overriding or overridden + by other sources? +. is the change directly visible to the configuration system? E.g. injected values are normally not updated, + whereas injecting a +DynamicValue<T>+ instance allows to detect and react single value changes. Also the + +PropertySources+ implementation must be able to detect any configuration changes and adapt its values returned + accordingly. Finally values also can be marked as immutable or being cached. +. Is configuration cached, or written/collected directly on access? +. can the changes applied be committed at all? + +So it is part of your application configuration design to clearly define, which property sources may be read-only, which +may be mutable, how overriding should work and to which backends finally any changes should be written back. + + +=== Configuration Changes + +This module does not handle detection of changes to the overall system's +Configuration+. This can be done in +several ways, e.g. by: + +* using the _tamaya-events_ extension, which can be used to observe the system's configuration and + publishing events when things have been changed. +* The SPI implementing the +MutableConfigurationBackendSpi+ may inform/update any affected +PropertySource, + PropertySourceProvider+ instances about the changes applied. + + +=== Supported Backends + +Multiple backends are supported. E.g. _tamaya-etcd_ also registers +corresponding SPI implementations/backends. This module comes with +the following +MutablePropertySource+ implementations: + +* +MutablePropertySource+ resources, targeting local +.properties+ files, using the +java.util.Properties+ + format. +* +MutableXmlPropertySource+ resources, targeting local +.xml+ property files, using the +java.util.Properties+ + XML format. + + +=== SPIs + +The module defines +MutableConfigurationProviderSpi+, that is used as a delegate by the +MutableConfigurationProvider+ +singleton accessor: + +[source,java] +.SPI: MutableConfigurationProviderSpi +-------------------------------------------------- +public interface MutableConfigurationProviderSpi { + /** + * Creates a new {@link MutableConfiguration} with {@code autoCommit = false} as default. + * + * @param configuration the configuration, not null. + * @param propagationPolicy policy that defines how changes are published to the property + * sources. + * @return a new mutable configuration instance. + */ + MutableConfiguration createMutableConfiguration(Configuration configuration, + ChangePropagationPolicy propagationPolicy); +} +-------------------------------------------------- + +Implementations are registered with the current +ServiceContext+ (using by default the + +java.util.ServiceLoader+ service). http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/blob/8951b7be/content/documentation-new/extensions/mod_optional.adoc ---------------------------------------------------------------------- diff --git a/content/documentation-new/extensions/mod_optional.adoc b/content/documentation-new/extensions/mod_optional.adoc new file mode 100644 index 0000000..0b7d948 --- /dev/null +++ b/content/documentation-new/extensions/mod_optional.adoc @@ -0,0 +1,61 @@ +:jbake-type: page +:jbake-status: published + += Apache Tamaya - Extension: Optional Tamaya Configuration + +toc::[] + + +[[Optional]] +== Tamaya Optional (Extension Module) + +Tamaya _Optional_ is an extension module. Refer to the link:../extensions.html[extensions documentation] for further details. + +=== What functionality this module provides ? + +Tamaya _Optional_ is for projects that want to benefit from Tamaya configuration optionally only. +E.g. doing an OSS project you can declare to support configuration with Tamaya as +an optional extension. This module can be added as a hard dependency to your code, hereby adding only +three artifacts. The _optional_ module automatically checks the availability of Tamaya on the +classpath and only if available it tries to access it for configuration evaluation. +Additionally an +EvaluationPolicy+ lets you define the precedence of configured values +(yours, or Tamaya ones, if present). + + +=== Compatibility + +The module is based on Java 7, so it will not run on Java 7 and beyond. + + +=== Installation + +To use Tamaya _optional_ you only must add the corresponding dependency to your module: + +[source, xml] +----------------------------------------------- +<dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-optional</artifactId> + <version>{tamaya_version}</version> +</dependency> +----------------------------------------------- + + +=== Reading configuration using the Tamaya Optional Module + +Tamaya _Optional_ allows reading configuration with a small subset of functionality only. For more + advanced use cases consider using the Apache Tamaya as your main configuration API. When + creating your +OptionalConfiguration+ instance you also pass the logic to access a value + with your own configuration logic. Tamaya Optional will delegate to your logic as needed + (depending on the `EvaluationPolicy`). + +[source, java] +----------------------------------------------- +BigDecimal interestRate = + OptionalConfiguration.of( + EvaluationPolicy.TAMAYA_OVERRIDES_OTHER, + (k) -> MyConfigMechanism.get(k) // String get(String key); + ) + .get("com.mycomp.ratecalculator.rate", BigDecimal.class)) + .orElse(BigDecimal.of(0.05d)); +-----------------------------------------------
