Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id E7038200BB3 for ; Wed, 2 Nov 2016 23:55:45 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id E57D8160AFB; Wed, 2 Nov 2016 22:55:45 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 6C62D160AF0 for ; Wed, 2 Nov 2016 23:55:43 +0100 (CET) Received: (qmail 82028 invoked by uid 500); 2 Nov 2016 22:55:42 -0000 Mailing-List: contact commits-help@tamaya.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@tamaya.incubator.apache.org Delivered-To: mailing list commits@tamaya.incubator.apache.org Received: (qmail 82019 invoked by uid 99); 2 Nov 2016 22:55:42 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd3-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 02 Nov 2016 22:55:42 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd3-us-west.apache.org (ASF Mail Server at spamd3-us-west.apache.org) with ESMTP id 037B718030C for ; Wed, 2 Nov 2016 22:55:42 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd3-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -6.219 X-Spam-Level: X-Spam-Status: No, score=-6.219 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-2.999] autolearn=disabled Received: from mx1-lw-us.apache.org ([10.40.0.8]) by localhost (spamd3-us-west.apache.org [10.40.0.10]) (amavisd-new, port 10024) with ESMTP id PAZNWeXzVeLh for ; Wed, 2 Nov 2016 22:55:29 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-us.apache.org (ASF Mail Server at mx1-lw-us.apache.org) with SMTP id 742D15FC2B for ; Wed, 2 Nov 2016 22:55:28 +0000 (UTC) Received: (qmail 76868 invoked by uid 99); 2 Nov 2016 22:53:12 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 02 Nov 2016 22:53:12 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id E3CC9E9437; Wed, 2 Nov 2016 22:53:11 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: pottlinger@apache.org To: commits@tamaya.incubator.apache.org Date: Wed, 02 Nov 2016 22:53:58 -0000 Message-Id: <3881ca603c1f45fe931890bdbd288711@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [49/57] incubator-tamaya-site git commit: TAMAYA-178: Regenerated freshly without APIdocs archived-at: Wed, 02 Nov 2016 22:55:46 -0000 http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/blob/01943a73/extensions/mod_model.html ---------------------------------------------------------------------- diff --git a/extensions/mod_model.html b/extensions/mod_model.html new file mode 100644 index 0000000..c845752 --- /dev/null +++ b/extensions/mod_model.html @@ -0,0 +1,769 @@ + + + + + + Apache Tamaya&#8201;&#8212;&#8201;Extension: Model Documentation and Validation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+ + + +

2016-11-02

+ +

+
+ +
+
+
+

Tamaya Model Documentation and Validation (Extension Module)

+
+
+

Overview

+
+

The Tamaya model module provides support for documenting configuration and validating configuration read and processed +against this model. Documentation and config models can be provided in different ways:

+
+
+
    +
  • +

    as separate meta-model documents

    +
  • +
  • +

    by providers that check classes/packages for configuration annotations (planned)

    +
  • +
+
+
+
+

Compatibility

+
+

The module is based on Java 7, so it will not run on Java 7 and beyond.

+
+
+
+

Installation

+
+

To benefit from configuration builder support you only must add the corresponding dependency to your module:

+
+
+
+
<dependency>
+  <groupId>org.apache.tamaya.ext</groupId>
+  <artifactId>tamaya-model</artifactId>
+  <version>{tamayaVersion}</version>
+</dependency>
+
+
+
+
+

Describing the Configuration Meta-Model

+
+

Basically configuration is modelled using key, value-pairs. Looking at a keys +a.b.c.param1 and a.b.c.param2 the following concepts can be used to defined/describe +configuration:

+
+
+
    +
  1. +

    the configuration section: In our case this equals to a.b.c, which itself also includes the +transitive entries a.b and a.

    +
  2. +
  3. +

    the configuration parameter: Basically parameters are adressed using their fully qualified names, +which equals to the containing section name and the relative parameter name, separated by the dor separator. +In the above example a.b.c.param1 and a.b.c.param2 are the fully qualified parameter names.

    +
  4. +
+
+
+

Now with only these 2 concepts a simple configuration meta-model can be defined as

+
+
+
    +
  • +

    a meta-model’s name, used just for grouping different meta-models and entries to better separate +descriptions, e.g. in a management console or generated configuration documentation site.

    +
  • +
  • +

    a set of sections.

    +
  • +
  • +

    a set of parameters.

    +
  • +
  • +

    Both, sections (.model.target=Section) as well as parameter models (.model.target=Parameter)

    +
    +
      +
    • +

      can be modelled by a meta-data entry, by default _my.config.key.model.

      +
    • +
    • +

      may be required, or optional (.model.required=true|false)

      +
    • +
    • +

      may have an optional description

      +
    • +
    +
    +
  • +
  • +

    Parameters additionally have

    +
    +
      +
    • +

      a type (.model.type=Classname), described by the fully qualified class name, into which any configured (String) +value must be convertable into. If no type is configured java.ui.lang.String is assumed as default.

      +
    • +
    • +

      an optional regular expression that can be used to validate the String values returned from a +configuration (.model.expression=regexpression).

      +
    • +
    +
    +
  • +
+
+
+

Given these concepts a configuration can be fully described. Entries that are not contained in one of the given +sections (or its children), or parameters not described or marked as valid (e.g. for dynamic configModels of +a section), are called undefined. Undefined parameters should be grouped with its parent section. Each section, as +well as all parent sections, including transitive) of any parametet read, should similarly marked as undefined, if and +only if

+
+
+
    +
  1. +

    the section itself is (directly) undefined

    +
  2. +
  3. +

    the section is not a super section of a defined section.

    +
  4. +
+
+
+

As en example the section definition of a.b.c also implicitly includes the sections a.b and a to be defined +sections, despite the fact that section properties, such as description and custom configModels are not inherited to +its parent, or child section.

+
+
+
+

Defining Meta-Configuration Model

+
+

The configuration meta-model is defined by simple configuration meta-data entries. The section for all model +configuration by default is called model, which results in entries such as _my.config.key.model.target=Section. +Within this section fully qualified configuration keys defines +which part of the configuration is targeted by certain entries.

+
+
+

Defining Sections

+
+

First we start to define some configuration sections, the example below starts with the most important +variants supported:

+
+
+
+
# Metamodel information
+_model.provider=ConfigModel Extension
+
+# org.mycompany.root (optional section)
+_org.mycompany.root.model.target=Section
+_org.mycompany.root.model.description=Root section defining my company configuration.
+
+# org.mycompany.security (required section)
+_org.mycompany.security.model.target=Section
+_org.mycompany.security.model.required=true
+_org.mycompany.security.model.description=Security related settings.\
+         refer for further details to XXX.
+
+# minmal section
+_minimal.model.target=Section
+
+# custom validated section
+_validated.model.target=Section
+_validated.model.validator=org.apache.tamaya.model.TestValidator
+
+
+
+

Above org.mycompany.root transitively defines 3 sections:

+
+
+
    +
  • +

    org

    +
  • +
  • +

    org.mycompany

    +
  • +
  • +

    org.mycompany.root

    +
  • +
+
+
+

All sections are optional. Additionally the model above also defines a required section org.mycompany.security. +Required sections are checked so the section is not empty. It is not checked for any specific parameter hereby, +only the existance of any child parameter is validated.

+
+
+

The class attribute has to be defined for any section definition, because if not set a model entry is, by default, +defined to be a parameter configModel entry. Given above the entry for the section minimal shows such a minimal +entry.

+
+
+

validated defines a section, which is validated through a customizable validator. Hereby an ordered list of validators +can be provided, separated by commas.

+
+
+
+

Defining Parameters

+
+

Similarly parameters also can be defined:

+
+
+
+
# org.mycompany.root.name (required parameter)
+_org.mycompany.root.name.model.target=Parameter
+_org.mycompany.root.name.model.required=true
+_org.mycompany.root.name.model.description=The company's name, also used in the application's main header.
+
+# org.mycompany.security (required parameters)
+_org.mycompany.security.uid.model.required=true
+_org.mycompany.security.uid.model.description=The user id.
+_org.mycompany.security.realm.model.required=true
+_org.mycompany.security.realm.model.validator=org.apache.tamaya.model.RealmValidator
+_org.mycompany.security.realm.model.description=The security realm required.
+_org.mycompany.security.tokenid.model.description=The token id, if the token service is used (optional).
+
+# A minmal parameter
+_minimalClass.model.target=Class
+
+
+
+

Similarly as when defining section also parameter entries define transitively its containing sections. E.g. +the entry above for org.mycompany.security.realm also defines the following sections (as optional).

+
+
+
    +
  • +

    org

    +
  • +
  • +

    org.mycompany

    +
  • +
  • +

    org.mycompany.security

    +
  • +
+
+
+

Additional entries for section, e.g. configModels to be done, can be added as described in the previous section, +but are optional.

+
+
+

Since the parameter is the default type for model entries, a minmal parameter model entry only only needs it’s +parameter type to be defined. In the example above we define a parameter minimalClass of type Class. +Types hereby are fully qualified class names, whereas as 'java.ui.lang' for built-in language types can be +ommitted.

+
+
+
+

Model Locations

+
+

By default the configuration model can be defined at the following locations:

+
+
+
    +
  • +

    classpath*:META-INF/configmodel.properties, separate to the current Configuration. This functionality is enabled +by default, but can be disabled by adding org.apache.tamaya.model.default.enabled=false to your current +Configuration.

    +
  • +
  • +

    implicitly as part of the current +Configuration. THis can be disabled by setting +the org.apache.tamaya.model.integrated.enabled configuration poarameter to false.

    +
  • +
  • +

    customized by configuring the org.apache.tamaya.model.resources in the current Configuration. This +parameter allows to define the locations from where the model extension is trying to read the +model configuration. If the resources extension is available in your system it is used to +evaluate the locations. If not the default Classloader.getResources command is issued. Also it +is required that the formats extension is available, since this is used to effectively read the +data. This extension also allows you to use alternate representation formats such as ini, xml, yml, json.

    +
  • +
+
+
+
+
+

Tracking Configuration Access

+
+

The model module also allows tracking which code accesses configuration properties or configuration parameters. +It checks the stacktrace to evaluate the calling code location, hereby any unwanted packages can be implicitly +ommitted from the stacktrace. Also the maximal length of the stacktrace retained can be constraint in length. +The usages are recorded as Usage instances. Hereby for each parameter accessed a corresponding Usage +instance is created. It can be accessed by calling Usage ConfigUsageStats.getUsage(String key). Usage +statistics for calling Configuration.getProperties() can be obtained calling Usage getUsageAllProps();.

+
+
+

Usage tracking is disabled by default. It can be enabled by calling ConfigUsageStats.enableUsageTracking(true);. +ConfigUsageStats.isUsageTrackingEnabled() returns the current tracking status.

+
+
+

The Usage class itself provides access to further fainer grained usage data (AccessDetail) containing:

+
+
+
    +
  • +

    the access point (fqn.ClassName#method(line: xxx)).

    +
  • +
  • +

    the number of accesses

    +
  • +
  • +

    the first an last access

    +
  • +
  • +

    the values read

    +
  • +
  • +

    the access stacktrace (filtered by ignored packages).

    +
  • +
+
+
+
+
public final class Usage {
+    [...]
+    public String getKey();
+    public void clearMetrics();
+    public int getReferenceCount();
+    public int getUsageCount();
+    public Collection<AccessDetail> getAccessDetails(Class type);
+    public Collection<AccessDetail> getAccessDetails(Package pack);
+    public Collection<AccessDetail> getAccessDetails(String lookupExpression);
+    public Collection<AccessDetail> getAccessDetails();
+    public void trackUsage(String value);
+    public void trackUsage(String value, int maxTraceLength);
+
+
+    public static final class AccessDetail {
+        [...]
+        public void clearStats();
+        public long trackAccess(String value);
+        public long getAccessCount();
+        public String getAccessPoint();
+        public long getFirstAccessTS();
+        public long getLastAccessTS();
+        public String[] getStackTrace();
+        public Map<Long, String> getTrackedValues();
+    }
+
+}
+
+
+
+

With ConfigUsageStats.clearUsageStats() the collected statistics can be reset at any time. Summarizing the main +singleton for configuration statistics is defined as follows:

+
+
+
+
public final class ConfigUsageStats{
+    public static Set<String> getIgnoredUsagePackages();
+    public static void addIgnoredUsagePackages(String... packageName);
+    public static void enableUsageTracking(boolean enabled);
+    public static Usage getUsage(String key);
+    public static Collection<Usage> getUsages();
+    public static void clearUsageStats();
+    public static Usage getUsageAllProperties();
+    public static boolean isUsageTrackingEnabled();
+    public static String getUsageInfo();
+}
+
+
+
+

Customizing the Stacktrage for Usage Reporting

+
+

The stacktrace tracked by the system can be customized in several ways:

+
+
+
    +
  • +

    ConfigUsageStats.addIgnoredPackageNames(String...) allows to add additional ignored package names.

    +
  • +
  • +

    With Usage.setMaxTraceLength(int) the maximal size of the stacktraces logged can be set. Setting a +negative value will disable stacktrace logging completelely.

    +
  • +
+
+
+
+
+

Accessing Usage Statistics

+
+

Bascially usage statistics are available in two forms:

+
+
+
    +
  • +

    The Usage/AccessDetail object tree can be accessed programmatically from the ConfigUsageStats +singleton.

    +
  • +
  • +

    With ConfigUsageStats.getUsageInfo() also a textual representation of the usage statistics +can be obtained, as illustrated below (a snipped from the current test output):

    +
  • +
+
+
+
+
Apache Tamaya Configuration Usage Metrics
+=========================================
+DATE: Sat Apr 30 21:51:09 CEST 2016
+
+220    <<all>>:
+  - 220   <unknown/filtered/internal>                       , first=Sat Apr 30 21:51:09 CEST 2016, last=Sat Apr 30 21:51:09 CEST 2016
+3      java.version:
+  - 2     test.model.TestConfigAccessor#readProperty(line:43), first=Sat Apr 30 21:51:09 CEST 2016, last=Sat Apr 30 21:51:09 CEST 2016
+  - 1     <unknown/filtered/internal>                       , first=Sat Apr 30 21:51:09 CEST 2016, last=Sat Apr 30 21:51:09 CEST 2016
+
+
+
+

Programmatic API

+
+

Basically the configModel module provides a simple API to access the defined ConfigModel instances and +validating the current Configuration against the models as follows:

+
+
+
+
public final class ConfigModelManager {
+
+    private ConfigModelManager() {}
+
+    public static Collection<ConfigModel> getModels();
+    public static Collection<ConfigModel> findModels(ModelType type, String namePattern);
+    public static <T extends ConfigModel> T getModel(String name, Class<T> modelType);
+    public static Collection<ConfigModel> findModels(String namePattern);
+
+    public static Collection<ValidationResult> validate();
+    public static Collection<ValidationResult> validate(boolean showUndefined);
+    public static Collection<ValidationResult> validate(Configuration config);
+    public static Collection<ValidationResult> validate(Configuration config, boolean showUndefined);
+
+    public static void registerMBean();
+    public static void registerMBean(String context);
+
+}
+
+
+
+

This singleton allows to validate the current or any Configuration instance. All the ConfigModels read also are +available from the getModels method. This models can be used to provide documentation, e.g. as part of a CLI interface +or shown on a documentation web server.

+
+
+

A ConfigModel hereby is defined as one single part of configuration, typically corresponding to a specific concern +of your system. As an example you can define different models for different modules or products plugged together. +With resolution mechanism in place you can also define a shared module that is targeted by multiple modules as a +single configuration source (e.g. for configuring the machine’s IP address and subnet settings only once.

+
+
+
+
public interface ConfigModel {
+
+    ModelTarget getType();
+    String getName();
+    String getProvider();
+    boolean isRequired();
+    String getDescription();
+    Collection<ValidationResult> validate(Configuration config);
+}
+
+
+
+

Hereby ModelTarget defines more details on the kind of model:

+
+
+
+
public enum ModelTarget {
+    /**
+     * A configuration section.
+     */
+    Section,
+    /**
+     * A configuration paramter.
+     */
+    Parameter,
+    /**
+     * ConfigModel that is a container of other validations.
+     */
+    Group
+}
+
+
+
+

A ValidationResult models one validation executed by a ConfigModel on a certain Configuration instance:

+
+
+
+
public final class ValidationResult {
+
+    public static ValidationResult ofValid(ConfigModel configModel);
+    public static ValidationResult ofMissing(ConfigModel configModel);
+    public static ValidationResult ofMissing(ConfigModel configModel, String message);
+    public static ValidationResult ofError(ConfigModel configModel, String error);
+    public static ValidationResult ofWarning(ConfigModel configModel, String warning);
+    public static ValidationResult ofDeprecated(ConfigModel configModel, String alternateUsage);
+    public static ValidationResult ofDeprecated(ConfigModel configModel);
+    public static ValidationResult ofUndefined(final String key);
+    public static ValidationResult of(ConfigModel configModel, ValidationState result, String message);
+
+    public ConfigModel getConfigModel();
+    public ValidationState getResult();
+    public String getMessage(),
+}
+
+
+
+

The result of a complete validation on a concrete Configuration instance finally is mapped as a +Collection<ValidationResult>, refer to the methods on ConfigModelManager.

+
+
+
+
+

Auto-Documentation of Classes with Configuration Injection

+
+

A special feature of this module is that it observes ConfigEvent published through Tamaya’as event channel +(tamaya-events module). If no metaconfiguration model is found the model manager by default automatically creates +models for all injected instances on the fly. In the case of CDI integration this happens typically during deployment +time, since CDI initializes during deployment time. Other runtime platforms, such as OSGI, may have rather different +behaviour. Nevertheless this means that after your system has been started you should have access to a complete +set of ConfigModel instances that automatically document all the classes in your system that consume configuration +(through injection).

+
+
+
+
+
+

Model SPI

+
+
+

Registering Configuration Models

+
+

The model extension also provides an SPI where customized functionality can be added. The main abstraction hereby is +the ModelProviderSpi interface, which allows any kind of additional config models to be added to the system:

+
+
+
+
public interface ModelProviderSpi {
+
+    Collection<ConfigModel> getConfigModels();
+
+}
+
+
+
+

New instances implementing this interface must be registered into the current ServiceContext, by default the +ServiceLoader is used.

+
+
+
+

The ConfigUsageStatsSpi

+
+

The methods for managing and tracking of configuration changes are similarly delegated to an +implementation of the org.apache.tamaya.model.spi.ConfigUsageStatsSpi SPI. +By implementing this SPI and registerting it with the ServiceContext the usage tracking +logic can be adapted or replaced.

+
+
+
+

Other Utility Classes

+
+

The module also provides further utility classes that may be useful for implementing models or testing:

+
+
+
    +
  • +

    AbstractModel provides a base class that can be extended, when implementing ConfigModel.

    +
  • +
  • +

    AreaConfigModel provides a ConfigModel implementation (with a corresponding Builder) to model the +requirement of certain configuration sections being present, or opionally present, in the model.

    +
  • +
  • +

    ParameterModel provides an implementation base class for validating parameters on existence and compliance +with a regular expression.

    +
  • +
  • +

    ConfigDocumentationMBean is the MBean registered that models similar functionality as ConfigModelManager.

    +
  • +
  • +

    ConfigModelGroup provides a ConfigModel that groups several child models.

    +
  • +
  • +

    ConfigModelReader allows to read ConfigModels from properties files as described at the beginning of this +document.

    +
  • +
+
+
+
+

Switches to enable/disable functionality

+
+

The model module provides different switches that can be used to activate or deactivate features:

+
+
+
    +
  • +

    tamaya.model.integrated.enabled allows to deactivate reading inline metaconfiguration delivered with +the normal Tamaya Configuration. By default inline entries (_.abcd.model.*) are evaluated.

    +
  • +
  • +

    tamaya.model.default.enabled allows to deactivate reading metamodel information from +classpath:META-INF/configmodel.properties. By default it is active.

    +
  • +
  • +

    tamaya.model.resources allows to define additional resources (loaded through the resources extension), +that can be used to read metamodel information in any format using Tamaya’s format module.

    +
  • +
  • +

    the system property tamaya.model.autoModelEvents allows to activate/deactivate the automatic +documentation of classes configured and published by Tamaya ConfiguredType event instances (e.g. published by +Tamaya’s injection modules).

    +
  • +
+
+
+
+

+ +
+
+
+
+
+ + + + + + + + + +
+ + http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/blob/01943a73/extensions/mod_mutable_config.html ---------------------------------------------------------------------- diff --git a/extensions/mod_mutable_config.html b/extensions/mod_mutable_config.html new file mode 100644 index 0000000..ef344a0 --- /dev/null +++ b/extensions/mod_mutable_config.html @@ -0,0 +1,447 @@ + + + + + + Apache Tamaya&#8201;&#8212;&#8201;Extension: Mutable Configuration + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+ + + +

2016-11-02

+ +

+
+ +
+
+
+

Tamaya Mutable Configuration (Extension Module)

+
+
+

Overview

+
+

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 some 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:

+
+
+
+
<dependency>
+  <groupId>org.apache.tamaya.ext</groupId>
+  <artifactId>tamaya-mutable-config</artifactId>
+  <version>{tamayaVersion}</version>
+</dependency>
+
+
+
+
+

Core Architecture

+
+

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 changes applied are managed in a transaction like context, called ConfigChangeContext. Each context defines +a UUID that identifes a change. +Backends for writing changes applied are of type MutablePropertySource, similarly extending the PropertySource +SPI with methods for writing changes back. Registrations and ordering policies are like with ordinary property sources, +with one important difference. Mutable property source can be targeted by write operations.

+
+
+

Summarizing a MutableConfiguration can be obtained as follows:

+
+
+
Accessing and changing a configuration
+
+
MutableConfiguration config = MutableConfigurationProvider.createMutableConfiguration();
+config.set("newKey", "newValue")
+      .set("anotherKey", "updatedValue")
+      .remove("valueNotValid")
+      .commit();
+
+
+
+

In the above scenario we use the overall system’s configuration as the backend to be used. +We can also pass any Configuration to render it into a mutable instance, e.g.

+
+
+
Explicitly passing the backing configuration
+
+
Configuration config = ...;
+MutableConfiguration config =
+    MutableConfigurationProvider.createMutableConfiguration(config);
+
+
+
+ + + + + +
+
Note
+
+If a configuration does not contain any MutablePropertySource instances, a MutableConfiguration built + from it will not be able to accept any changes. +
+
+
+

Following is the complete listing of the MutableConfigurationProvider accessor:

+
+
+
+
public final class MutableConfigurationProvider {
+
+    private MutableConfigurationProvider(){}
+
+    public static MutableConfiguration getMutableConfiguration();
+    public static MutableConfiguration getMutableConfiguration(Configuration configuration);
+
+    [...]
+}
+
+
+
+

Hereby MutableConfiguration is defined as follows:

+
+
+
+
public interface MutableConfiguration extends Configuration {
+
+    UUID startTransaction();
+    void commitTransaction();
+    void rollbackTransaction();
+    UUID getTransactionId();
+    boolean getAutoCommit();
+    void setAutoCommit(boolean autoCommit);
+
+    void setChangePropagationPolicy(ChangePropagationPolicy changePropagationPolicy);
+    ChangePropagationPolicy getChangePropagationPolicy();
+
+    boolean isWritable(String keyExpression);
+    boolean isRemovable(String keyExpression);
+    boolean isExisting(String keyExpression);
+    List<MutablePropertySource> getMutablePropertySources();
+    List<MutablePropertySource> getPropertySourcesThatCanWrite(String keyExpression);
+    List<MutablePropertySource> getPropertySourcesThatCanRemove(String keyExpression);
+    List<MutablePropertySource> getPropertySourcesThatKnow(String keyExpression);
+
+    MutableConfiguration put(String key, String value);
+    MutableConfiguration putAll(Map<String, String> properties);
+    MutableConfiguration remove(Collection<String> keys);
+    MutableConfiguration remove(String... keys);
+
+}
+
+
+
+

Targeting the right MutablePropertySources

+
+

A Configuration may have multiple MutablePropertySource present. These are members of Tamaya’s oredered list of +PropertySources to evaluate the configuration. Nevertheless writing back changes requires additional aspects to +be considered: +* Should changes being written back to all mutable property sources? Or should a key that could be added or removed + on a more significant instance not be written/removed on less significant property source instances? +* Should a change be applied only to a specific mutable property source, regardless its position in the + processing chain?

+
+
+

Therefore a ChangePropagationPolicy can be set on a MutableConfiguration instance, which allows to control +this aspect:

+
+
+
Explicitly passing the backing configuration
+
+
public interface ChangePropagationPolicy {
+    void applyChanges(Collection<PropertySource> propertySources, UUID transactionID, Map<String,String> changes);
+    void applyChange(Collection<PropertySource> propertySources, UUID transactionID, String key, String value);
+    void applyRemove(Collection<PropertySource> propertySources, UUID transactionID, String... keys);
+
+}
+
+
+
+

By default, changes are applied to all registered MutablePropertySources similarly.

+
+
+

Also the MutableConfigurationProvider provides access to the most commonly used change propagation policies:

+
+
+
+
public final class MutableConfigurationProvider {
+
+    private MutableConfigurationProvider(){}
+
+    public static MutableConfiguration getMutableConfiguration();
+    public static MutableConfiguration getMutableConfiguration(Configuration configuration);
+
+    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 easily predicted, since it depends on several aspects:

+
+
+
    +
  1. +

    is the corresponding configuration resource configured as part of the current system’s configuration?

    +
  2. +
  3. +

    what is the PropertySource's ordinal? Is it overriding or overridden by other sources?

    +
  4. +
  5. +

    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.

    +
  6. +
  7. +

    Is configuration cached, or written/collected directly on access?

    +
  8. +
  9. +

    can the changes applied be committed at all?

    +
  10. +
+
+
+

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. To +support such fine granular scenarios a MutableConfiguration also offers methods to determine if a key +is writable at all or can be removed or updated:

+
+
+
Checking for mutability
+
+
MutableConfiguration config = MutableConfigurationProvider.createMutableConfiguration();
+
+if(config,isWritable("mycluster.shared.appKey")){
+    config.set("newKey", "newValue");
+}
+if(config,isRemovable("mycluster.myapp.myKey")){
+    config.remove("mycluster.myapp.myKey");
+}
+config.commit();
+
+
+
+
+
+

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. the etcd integration module of Tamaya also registers +corresponding SPI implementations/backends. By default this module comes with +the following MutablePropertySource implementations:

+
+
+
    +
  • +

    MutablePropertySource resources, targeting local .properties files, following the java.util.Properties +format.

    +
  • +
  • +

    MutableXmlPropertySource resources, targeting local .xml property files, following the java.util.Properties +XML format.

    +
  • +
+
+
+
+

SPIs

+
+

The module defines MutableConfigurationProviderSpi, that is used as a delegate by the MutableConfigurationProvider +singleton accessor:

+
+
+
SPI: MutableConfigurationProviderSpi
+
+
public interface MutableConfigurationProviderSpi {
+   MutableConfiguration createMutableConfiguration(Configuration configuration);
+}
+
+
+
+

Implementations are registered with the current ServiceContext, by default as a + java.util.ServiceLoader service.

+
+
+

As convenience the following base classes are provided:

+
+
+
    +
  • +

    org.apache.tamaya.mutableconfig.propertysource.AbstractMutablePropertySource simplifying implementation of +MutablePropertySource.

    +
  • +
+
+
+
+

+ +
+
+
+
+
+ + + + + + + + + +
+ + http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/blob/01943a73/extensions/mod_optional.html ---------------------------------------------------------------------- diff --git a/extensions/mod_optional.html b/extensions/mod_optional.html new file mode 100644 index 0000000..e6ed768 --- /dev/null +++ b/extensions/mod_optional.html @@ -0,0 +1,202 @@ + + + + + + Apache Tamaya&#8201;&#8212;&#8201;Extension: Optional Tamaya Configuration + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+ + + +

2016-11-02

+ +

+
+ +
+
+
+

Tamaya Optional Configuration (Extension Module)

+
+
+

Overview

+
+

The Tamaya optional module provides contains three types only. It 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 artofacts. +It automatically checks the availability of Tamaya on the classpath and only if available 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 benefit from configuration builder support you only must add the corresponding dependency to your module:

+
+
+
+
<dependency>
+  <groupId>org.apache.tamaya.ext</groupId>
+  <artifactId>tamaya-optional</artifactId>
+  <version>{tamayaVersion}</version>
+</dependency>
+
+
+
+
+

Reading configuration using the Tamaya Optional Module

+
+

The optional module allows reading configuration with a small subset of functionality only. For extended of full +featured config please consider using the Apache Tamaya as a full configuration backend.

+
+
+
+
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));
+
+
+
+
+

+ +
+
+
+
+
+ + + + + + + + + +
+ + http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/blob/01943a73/extensions/mod_osgi.html ---------------------------------------------------------------------- diff --git a/extensions/mod_osgi.html b/extensions/mod_osgi.html new file mode 100644 index 0000000..c4241c6 --- /dev/null +++ b/extensions/mod_osgi.html @@ -0,0 +1,292 @@ + + + + + + Apache Tamaya&#8201;&#8212;&#8201;Extensions: OSGI Integrations + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+ + + +

2016-11-02

+ +

+
+ +
+
+
+

Tamaya OSGI Support

+
+
+

Overview

+
+

Tamaya provides also support for integration with OSGI. Hereby several options are available how Tamaya can be used in +an OSGI context:

+
+
+
    +
  1. +

    All Tamaya modules, its API and core library are actually valid OSGI bundles. So adding them into your OSGI modules +and using Tamaya is basically directly supported. Nevertheless OSGI works rather differently from a class- and +resource loading perspective. As long as you rely on Tamaya’s mechanisms for resource loading things should work +out of the box. In the back Tamaya’s core module actually comes with implicit OSGI support, which is automatically +activated, if Tamaya is running in an OSGI context. This support actually

    +
    +
      +
    • +

      Listens on deployed bundles and actively reads all resources configured as java.util.ServiceLoader services and +registers them as OSGI services. Hereby integration is complete meaning you can also register Tamaya services +as normal OSGI services, e.g. your own PropertySource instances.

      +
    • +
    • +

      Uses the OSGI bundle to resolve for resources, because accessing them from the classloader directly +typically fails in an OSGI context.

      +
    • +
    +
    +
  2. +
  3. +

    Adding Tamaya’s OSGI integration module replaces the existing OSGI ConfigAdmin service with an istance based on +Tamaya. Hereby several aspects can be configured using system properties:

    +
    +
      +
    • +

      org.tamaya.integration.osgi.cm.ranking (int) allows to configure the OSGI service ranking used by the Tamaya +BundleActivator to register Tamaya’s ConfigAdmin service. In OSGI higher ranking precede lower rankings. By default +Tamaya’s OSGI extending service registration mechanism is reusing any annotated @Priority priority values as +corresponsing rankings.

      +
    • +
    • +

      org.tamaya.integration.osgi.cm.override (boolean) allows to configure if Tamaya is overriding any existing +values from the default ConfigAdmin instance, or only extending them. In other words this setting allows you to +define, which configuration subsystem has precedence for evaluating the final values, either Tamaya based +configuration (default) or the configuration mechanisms provided by default from your OSGI container (when this flag +is set to false).

      +
    • +
    • +

      org.tamaya.integration.osgi.cm.inject allows you to deactivate injection of configuration values into your +OSGI services (by default injection is enabled). In all cases accessing the OSGI ConfigAdmin service to +read your configuration is working as usual. But Tamaya adds additional injection functionality, which allows +to inject typed configuration as described by the Tamaya injection api.

      +
    • +
    +
    +
  4. +
+
+
+

It is also possible to combine things, e.g. when you only define a low ranking for Tamaya’s configuration service and +the same time allow injection to be active, you will have Tamaya’s injection support based on your default +OSGI configuration.

+
+
+
+

Compatibility

+
+

All module described are based on Java 7, so it will run on Java 7 and beyond. +The modules are built against OSGI Compendium version 5.0.

+
+
+
+

Installation

+
+

To benefit from Tamaya in an OSGI context you must deploy at least the following modules to your OSGI runtime +environment:

+
+
+
+
# API and core
+org.apache.tamaya:tamaya-api:{tamayaVersion}
+org.apache.tamaya:tamaya-core:{tamayaVersion}
+org.apache.geronimo.specs:geronimo-annotation_1.2_spec:1.0-alpha-1
+# injection API. SE injection module and dependencies
+org.apache.tamaya.ext:tamaya-injection-api:{tamayaVersion}
+org.apache.tamaya.ext:tamaya-injection:{tamayaVersion}
+org.apache.geronimo.specs:geronimo-atinject_1.0_spec:1.0
+org.apache.geronimo.specs:geronimo-el_2.2_spec:1.0.4
+org.apache.geronimo.specs:geronimo-interceptor_1.1_spec:1.0
+org.apache.geronimo.specs:geronimo-jcdi_1.1_spec:1.0
+# OSGI integration and dependencies
+org.apache.tamaya.ext:tamaya-osgi:{tamayaVersion}
+org.apache.tamaya.ext:tamaya-functions:{tamayaVersion}
+
+
+
+
+

Usage

+
+

As an example, what is possible you can implement an OSGI service as a normal POJO and publish it as an OSGI service. +Given that configuration can be injected very easily:

+
+
+
+
public class HelloServiceImpl implements HelloService{
+
+    @Config("example.message")
+    @ConfigDefault("A Tamaya default.")
+    private String message;
+
+    @Override
+    public String sayHello() {
+        System.err.println("HELLO: " + message);
+        return message;
+    }
+}
+
+
+
+
+

SPI

+
+

By defauklt the OSGI pid or factory pid is mapped to a corresponding root section in Tamaya’s configuration. We are +well aware that this might not always be the desired approach. Therefore there as an SPI service provided that allows +to determine this mapping:

+
+
+
OSGIConfigRootMapper
+
+
public interface OSGIConfigRootMapper {
+
+    String getTamayaConfigRoot(String pid, String factoryPid);
+}
+
+
+
+

Registering your own implementation as an OSGI service allows you to redefine the key mapping. +By default a configuration mapping for pid/factoryPid==myBundle is mapped to [bundle:myBundle]. +This mapping is used as a prefix when collecting the corresponding entries for the OSGI configuration.

+
+
+
+

+ +
+
+
+
+
+ + + + + + + + + +
+ + http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/blob/01943a73/extensions/mod_remote.html ---------------------------------------------------------------------- diff --git a/extensions/mod_remote.html b/extensions/mod_remote.html new file mode 100644 index 0000000..1b052e9 --- /dev/null +++ b/extensions/mod_remote.html @@ -0,0 +1,265 @@ + + + + + + Apache Tamaya&#8201;&#8212;&#8201;Extension: Remote Configuration + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+ + + +

2016-11-02

+ +

+
+ +
+
+
+

Tamaya Remote Configuration (Extension Module)

+
+
+

Overview

+
+

The Tamaya remote module provides support for reading configuration from remote resources. It provides +especially out-of-the-box support for reading scoped configuration from a configuration server as +provided with the Tamaya server module .

+
+
+
+

Compatibility

+
+

The module is based on Java 7, so it will not run on Java 7 and beyond.

+
+
+
+

Installation

+
+

To benefit from configuration builder support you only must add the corresponding dependency to your module:

+
+
+
+
<dependency>
+  <groupId>org.apache.tamaya.ext</groupId>
+  <artifactId>tamaya-remote</artifactId>
+  <version>{tamayaVersion}</version>
+</dependency>
+
+
+
+
+

Reading Remote configuration from a Tamaya Configuration Server

+
+

The remote module allows reading JSON formatted onfiguration as provided by the Tamaya server extension . The JSON +format used looks as follows:

+
+
+
+
{
+  "java.vendor.url": "http://java.oracle.com/",
+  "java.vendor.url.bug": "http://bugreport.sun.com/bugreport/",
+  "java.vm.info": "mixed mode",
+  "java.vm.name": "Java HotSpot(TM) 64-Bit Server VM",
+  "java.vm.specification.name": "Java Virtual Machine Specification",
+  "java.vm.specification.vendor": "Oracle Corporation",
+  "java.vm.specification.version": "1.8",
+  "java.vm.vendor": "Oracle Corporation",
+  "java.vm.version": "25.45-b02",
+  "sun.arch.data.model": "64",
+  "sun.boot.class.path": "C:\apps\jdk18\jre\lib\resources.jar;C:\apps\jdk18\jre\lib\rt.jar;C:\apps\jdk18\jre\lib\sunrsasign.jar;C:\apps\jdk18\jre\lib\jsse.jar;C:\apps\jdk18\jre\lib\jce.jar;C:\apps\jdk18\jre\lib\charsets.jar;C:\apps\jdk18\jre\lib\jfr.jar;C:\apps\jdk18\jre\classes",
+  "sun.boot.library.path": "C:\apps\jdk18\jre\bin",
+  "sun.cpu.endian": "little",
+  "sun.cpu.isalist": "amd64",
+  "sun.desktop": "windows",
+  "sun.io.unicode.encoding": "UnicodeLittle",
+  "sun.java.command": "com.intellij.rt.execution.application.AppMain org.apache.tamaya.examples.remote.server.Start",
+  "sun.java.launcher": "SUN_STANDARD",
+  "sun.jnu.encoding": "Cp1252",
+  "sun.management.compiler": "HotSpot 64-Bit Tiered Compilers",
+  "sun.os.patch.level": "",
+  "{meta}class": "org.apache.tamaya.functions.FilteredConfiguration",
+  "{meta}info.filter": "java.v,sun",
+  "{meta}info.format": "application/json",
+  "{meta}info.timestamp": "1441463200571",
+  "{meta}timestamp": "1441463200571",
+  "{meta}type": "Configuration"
+}
+
+
+
+

Basically there are no constraints about they keys provided. By default Tamaya uses keys prefixed with +{xxx} to identify meta-data entries, but this is not a required precondition.

+
+
+

Finally such a remote configuration can be easily integrated by inheriting from the provided base +class. Hereby a default ordinal must be defined and the protected Collection<URL> getAccessURLs() +method must be implemented to define the URL from where the configuration should be accessible. Hereby +multiple URLs can be provided, which are accesed in order as provided by the collection’s iterator. The +first URL that is successfully accessed determines the configuration read and imported into the +PropertySource.

+
+
+
+
public class RemotePropertySource extends BaseRemotePropertySource{
+    /** Current remote property source default ordinal. */
+    private static final int REMOTE_ORDINAL = 15000;
+
+    @Override
+    public int getDefaultOrdinal(){
+        return REMOTE_ORDINAL;
+    }
+
+    @Override
+    protected Collection<URL> getAccessURLs() {
+        try {
+            String configServerUrl = System.getenv("CONFIG_SERVER");
+            if(configServerUrl==null){
+                configServerUrl = System.getProperty("configServer");
+            }
+            if(configServerUrl==null){
+                configServerUrl = "http://localhost:8888/config?scope=CLIENT&scopeId={clientId}&format=application/json";
+            }
+            System.out.println("Reading config from " + configServerUrl.replace("{clientId}", Client.getClientId()));
+            return Arrays.asList(new URL[]{new URL(configServerUrl.replace("{clientId}", Client.getClientId()))});
+        } catch (MalformedURLException e) {
+            Logger.getLogger(getClass().getName()).log(Level.WARNING, "Failed to configure remote config location,", e);
+            return Collections.emptySet();
+        }
+    }
+
+}
+
+
+
+
+

+ +
+
+
+
+
+ + + + + + + + + +
+ +