You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by pl...@apache.org on 2016/09/26 22:19:02 UTC

[21/50] [abbrv] incubator-tamaya-extensions git commit: Simplified events module, adapted documentation as well. Removed model dependency from events, since events is the more general module here.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/java/org/apache/tamaya/events/delta/ConfigurationChangeBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/tamaya/events/delta/ConfigurationChangeBuilder.java b/src/main/java/org/apache/tamaya/events/delta/ConfigurationChangeBuilder.java
deleted file mode 100644
index ff5e26b..0000000
--- a/src/main/java/org/apache/tamaya/events/delta/ConfigurationChangeBuilder.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.events.delta;
-
-import org.apache.tamaya.Configuration;
-
-import java.beans.PropertyChangeEvent;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-/**
- * Models a set current changes applied to a {@link org.apache.tamaya.spi.PropertySource}. Consumers of these events
- * can observing changes to property sources and
- * <ol>
- * <li>Check if their current configuration instance ({@link org.apache.tamaya.spi.ConfigurationContext}
- * contains the changed {@link org.apache.tamaya.spi.PropertySource} (Note: the reference tova property source is never affected by a
- * change, its only the data of the property source).</li>
- * <li>If so corresponding action may be taken, such as reevaluating the configuration values (depending on
- * the update policy) or reevaluating the complete {@link org.apache.tamaya.Configuration} to create a change
- * event on configuration level.
- * </ol>
- */
-public final class ConfigurationChangeBuilder {
-    /**
-     * The recorded changes.
-     */
-    final SortedMap<String, PropertyChangeEvent> delta = new TreeMap<>();
-    /**
-     * The underlying configuration/provider.
-     */
-    Configuration source;
-    /**
-     * The version configured, or null, for generating a default.
-     */
-    String version;
-    /**
-     * The optional timestamp in millis of this epoch.
-     */
-    Long timestamp;
-
-    /**
-     * Constructor.
-     *
-     * @param configuration the underlying configuration, not null.
-     */
-    private ConfigurationChangeBuilder(Configuration configuration) {
-        this.source = Objects.requireNonNull(configuration);
-    }
-
-    /**
-     * Creates a new instance current this builder.
-     *
-     * @param configuration the configuration changed, not null.
-     * @return the builder for chaining.
-     */
-    public static ConfigurationChangeBuilder of(Configuration configuration) {
-        return new ConfigurationChangeBuilder(configuration);
-    }
-
-    /**
-     * Compares the two property config/configurations and creates a collection current all changes
-     * that must be appied to render {@code map1} into {@code map2}.
-     *
-     * @param map1 the source map, not null.
-     * @param map2 the target map, not null.
-     * @return a collection current change events, never null.
-     */
-    public static Collection<PropertyChangeEvent> compare(Configuration map1, Configuration map2) {
-        List<PropertyChangeEvent> changes = new ArrayList<>();
-        for (Map.Entry<String, String> en : map1.getProperties().entrySet()) {
-            String val = map2.get(en.getKey());
-            if (val == null) {
-                changes.add(new PropertyChangeEvent(map1, en.getKey(), null, en.getValue()));
-            } else if (!val.equals(en.getValue())) {
-                changes.add(new PropertyChangeEvent(map1, en.getKey(), val, en.getValue()));
-            }
-        }
-        for (Map.Entry<String, String> en : map2.getProperties().entrySet()) {
-            String val = map1.get(en.getKey());
-            if (val == null) {
-                changes.add(new PropertyChangeEvent(map1, en.getKey(), null, en.getValue()));
-            } else if (!val.equals(en.getValue())) {
-                changes.add(new PropertyChangeEvent(map1, en.getKey(), val, en.getValue()));
-            }
-        }
-        return changes;
-    }
-
-    /*
-     * Apply a version/UUID to the set being built.
-     * @param version the version to apply, or null, to let the system generate a version for you.
-     * @return the builder for chaining.
-     */
-    public ConfigurationChangeBuilder setVersion(String version) {
-        this.version = version;
-        return this;
-    }
-
-    /*
-     * Apply given timestamp to the set being built.
-     * @param version the version to apply, or null, to let the system generate a version for you.
-     * @return the builder for chaining.
-     */
-    public ConfigurationChangeBuilder setTimestamp(long timestamp) {
-        this.timestamp = timestamp;
-        return this;
-    }
-
-    /**
-     * This method records all changes to be applied to the base property provider/configuration to
-     * achieve the given target state.
-     *
-     * @param newState the new target state, not null.
-     * @return the builder for chaining.
-     */
-    public ConfigurationChangeBuilder addChanges(Configuration newState) {
-        for (PropertyChangeEvent c : compare(newState, this.source)) {
-            this.delta.put(c.getPropertyName(), c);
-        }
-        return this;
-    }
-
-    /**
-     * Applies a single key/value change.
-     *
-     * @param key   the changed key
-     * @param value the new value.
-     * @return this instance for chining.
-     */
-    public ConfigurationChangeBuilder addChange(String key, String value) {
-        this.delta.put(key, new PropertyChangeEvent(this.source, key, this.source.get(key), value));
-        return this;
-    }
-
-    /**
-     * Get the current values, also considering any changes recorded within this change set.
-     *
-     * @param key the key current the entry, not null.
-     * @return the keys, or null.
-     */
-    public String get(String key) {
-        PropertyChangeEvent change = this.delta.get(key);
-        if (change != null && !(change.getNewValue() == null)) {
-            return (String) change.getNewValue();
-        }
-        return null;
-    }
-
-    /**
-     * Marks the given key(s) fromMap the configuration/properties to be removed.
-     *
-     * @param key       the key current the entry, not null.
-     * @param otherKeys additional keys to be removed (convenience), not null.
-     * @return the builder for chaining.
-     */
-    public ConfigurationChangeBuilder removeKey(String key, String... otherKeys) {
-        String oldValue = this.source.get(key);
-        if (oldValue == null) {
-            this.delta.remove(key);
-        }
-        this.delta.put(key, new PropertyChangeEvent(this.source, key, oldValue, null));
-        for (String addKey : otherKeys) {
-            oldValue = this.source.get(addKey);
-            if (oldValue == null) {
-                this.delta.remove(addKey);
-            }
-            this.delta.put(addKey, new PropertyChangeEvent(this.source, addKey, oldValue, null));
-        }
-        return this;
-    }
-
-    /**
-     * Apply all the given values to the base configuration/properties.
-     * Note that all values passed must be convertible to String, either
-     * <ul>
-     * <li>the registered codecs provider provides codecs for the corresponding keys, or </li>
-     * <li>default codecs are present for the given type, or</li>
-     * <li>the value is an instanceof String</li>
-     * </ul>
-     *
-     * @param changes the changes to be applied, not null.
-     * @return the builder for chaining.
-     */
-    public ConfigurationChangeBuilder putAll(Map<String, String> changes) {
-        changes.putAll(changes);
-        return this;
-    }
-
-    /**
-     * This method will create a change set that clears all entries fromMap the given base configuration/properties.
-     *
-     * @return the builder for chaining.
-     */
-    public ConfigurationChangeBuilder removeAllKeys() {
-        this.delta.clear();
-        for (Map.Entry<String, String> en : this.source.getProperties().entrySet()) {
-            this.delta.put(en.getKey(), new PropertyChangeEvent(this.source, en.getKey(), en.getValue(), null));
-        }
-//        this.source.getProperties().forEach((k, v) ->
-//                this.delta.put(k, new PropertyChangeEvent(this.source, k, v, null)));
-        return this;
-    }
-
-    /**
-     * Checks if the change set is empty, i.e. does not contain any changes.
-     *
-     * @return true, if the set is empty.
-     */
-    public boolean isEmpty() {
-        return this.delta.isEmpty();
-    }
-
-    /**
-     * Resets this change set instance. This will clear all changes done to this builder, so the
-     * set will be empty.
-     */
-    public void reset() {
-        this.delta.clear();
-    }
-
-    /**
-     * Builds the corresponding change set.
-     *
-     * @return the new change set, never null.
-     */
-    public ConfigurationChange build() {
-        return new ConfigurationChange(this);
-    }
-
-    /*
-     * (non-Javadoc)
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "ConfigurationChangeSetBuilder [config=" + source + ", " +
-                ", delta=" + delta + "]";
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/java/org/apache/tamaya/events/delta/ConfigurationContextChange.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/tamaya/events/delta/ConfigurationContextChange.java b/src/main/java/org/apache/tamaya/events/delta/ConfigurationContextChange.java
deleted file mode 100644
index 0aef2fd..0000000
--- a/src/main/java/org/apache/tamaya/events/delta/ConfigurationContextChange.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.events.delta;
-
-import org.apache.tamaya.spi.PropertySource;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Event that contains a set current changes that were applied or could be applied.
- * This class is immutable and thread-safe. To create instances use
- * {@link org.apache.tamaya.events.delta.PropertySourceChangeBuilder}.
- *
- * Created by Anatole on 22.10.2014.
- */
-public final class ConfigurationContextChange implements Serializable{
-
-    private static final long serialVersionUID = 1L;
-    /** The base property provider/configuration. */
-    private List<PropertySourceChange> changedPropertySources = new ArrayList<>();
-    /** The base version, usable for optimistic locking. */
-    private String version = UUID.randomUUID().toString();
-    /** The timestamp of the change set in millis from the epoch. */
-    private long timestamp = System.currentTimeMillis();
-
-    /**
-     * Get an empty change set for the given provider.
-     * @return an empty ConfigurationChangeSet instance.
-     */
-    public static ConfigurationContextChange emptyChangeSet(){
-        return ConfigurationContextChangeBuilder.of().build();
-    }
-
-    /**
-     * Constructor used by {@link org.apache.tamaya.events.delta.PropertySourceChangeBuilder}.
-     * @param builder The builder used, not null.
-     */
-    ConfigurationContextChange(ConfigurationContextChangeBuilder builder) {
-        this.changedPropertySources.addAll(builder.changedPropertySources);
-        if(builder.version!=null){
-            this.version = builder.version;
-        }
-        if(builder.timestamp!=null){
-            this.timestamp = builder.timestamp;
-        }
-    }
-
-    /**
-     * Get the base version, usable for optimistic locking.
-     * @return the base version.
-     */
-    public String getVersion(){
-        return version;
-    }
-
-    /**
-     * Get the timestamp in millis from the current epoch. it is expected that the timestamp and the version are unique to
-     * identify a changeset.
-     * @return the timestamp, when this changeset was created.
-     */
-    public long getTimestamp(){
-        return timestamp;
-    }
-
-    /**
-     * Get the changes recorded.
-     * @return the recorded changes, never null.
-     */
-    public Collection<PropertySourceChange> getPropertySourceChanges(){
-        return Collections.unmodifiableCollection(this.changedPropertySources);
-    }
-
-    /**
-     * Get the property source updates.
-     * @return the recorded changes, never null.
-     */
-    public Collection<PropertySourceChange> getPropertySourceUpdates(){
-        List<PropertySourceChange> result = new ArrayList<>();
-        for (PropertySourceChange pc : this.changedPropertySources) {
-            if (pc.getChangeType() == ChangeType.UPDATED) {
-                result.add(pc);
-            }
-        }
-        return result;
-//        return Collections.unmodifiableCollection(this.changedPropertySources).stream()
-//                .filter(pc -> pc.getChangeType()==ChangeType.UPDATED).collect(Collectors.toList());
-    }
-
-    /**
-     * Get the property sources to be removed.
-     * @return the recorded changes, never null.
-     */
-    public Collection<PropertySource> getRemovedPropertySources(){
-        List<PropertySource> result = new ArrayList<>();
-        for (PropertySourceChange pc : this.changedPropertySources) {
-            if (pc.getChangeType() == ChangeType.DELETED) {
-                result.add(pc.getResource());
-            }
-        }
-        return result;
-//        return getPropertySourceChanges().stream().filter(pc -> pc.getChangeType()==ChangeType.DELETED).
-//                map(ps -> ps.getPropertySource()).collect(Collectors.toList());
-    }
-
-    /**
-     * Get the property sources to be added.
-     * @return the recorded changes, never null.
-     */
-    public Collection<PropertySource> getAddedPropertySources(){
-        List<PropertySource> result = new ArrayList<>();
-        for (PropertySourceChange pc : this.changedPropertySources) {
-            if (pc.getChangeType() == ChangeType.NEW) {
-                result.add(pc.getResource());
-            }
-        }
-        return result;
-//        return getPropertySourceChanges().stream().filter(pc -> pc.getChangeType()==ChangeType.NEW).
-//                map(ps -> ps.getPropertySource()).collect(Collectors.toList());
-    }
-
-    /**
-     * Get the property sources to be updated.
-     * @return the recorded changes, never null.
-     */
-    public Collection<PropertySource> getUpdatedPropertySources(){
-        List<PropertySource> result = new ArrayList<>();
-        for (PropertySourceChange pc : this.changedPropertySources) {
-            if (pc.getChangeType() == ChangeType.UPDATED) {
-                result.add(pc.getResource());
-            }
-        }
-        return result;
-//        return getPropertySourceChanges().stream().filter(pc -> pc.getChangeType()==ChangeType.UPDATED).
-//                map(ps -> ps.getPropertySource()).collect(Collectors.toList());
-    }
-
-    /**
-     * Checks if the given propertySource is affected (added, changed or removed).
-     * @param propertySource the propertySource, not null.
-     * @return true, if the given propertySource ia affected.
-     */
-    public boolean isAffected(PropertySource propertySource) {
-        for (PropertySourceChange ps : this.changedPropertySources) {
-            if (ps.getResource() == propertySource ||
-                    ps.getResource().getName().equals(propertySource.getName())) {
-                return true;
-            }
-        }
-        return false;
-//        return this.changedPropertySources.stream().filter(ps ->  ps.getPropertySource()==propertySource ||
-//                ps.getPropertySource().getName().equals(propertySource.getName())).findAny().isPresent();
-    }
-
-    /**
-     * CHecks if the current change set does not contain any changes.
-     * @return tru, if the change set is empty.
-     */
-    public boolean isEmpty(){
-        return this.changedPropertySources.isEmpty();
-    }
-
-
-    @Override
-    public String toString() {
-        return "ConfigurationContextChange{" +
-                "changedPropertySources=" + changedPropertySources +
-                ", version='" + version + '\'' +
-                ", timestamp=" + timestamp +
-                '}';
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/java/org/apache/tamaya/events/delta/ConfigurationContextChangeBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/tamaya/events/delta/ConfigurationContextChangeBuilder.java b/src/main/java/org/apache/tamaya/events/delta/ConfigurationContextChangeBuilder.java
deleted file mode 100644
index 3e21635..0000000
--- a/src/main/java/org/apache/tamaya/events/delta/ConfigurationContextChangeBuilder.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.events.delta;
-
-import org.apache.tamaya.spi.PropertySource;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Models a set current changes applied to a {@link org.apache.tamaya.spi.PropertySource}. Consumers of these events
- * can observing changes to property sources and
- * <ol>
- *     <li>Check if their current configuration instance ({@link org.apache.tamaya.spi.ConfigurationContext}
- *     contains the changed {@link org.apache.tamaya.spi.PropertySource} (Note: the reference tova property source is never affected by a
- *     change, its only the data of the property source).</li>
- *     <li>If so corresponding action may be taken, such as reevaluating the configuration values (depending on
- *     the update policy) or reevaluating the complete {@link org.apache.tamaya.Configuration} to create a change
- *     event on configuration level.
- * </ol>
- */
-public final class ConfigurationContextChangeBuilder {
-    /**
-     * The recorded changes.
-     */
-    final List<PropertySourceChange> changedPropertySources = new ArrayList<>();
-    /**
-     * The version configured, or null, for generating a default.
-     */
-    String version;
-    /**
-     * The optional timestamp in millis of this epoch.
-     */
-    Long timestamp;
-
-    /**
-     * Constructor.
-     */
-    private ConfigurationContextChangeBuilder() {
-    }
-
-    /**
-     * Creates a new instance current this builder.
-     *
-     * @return the builder for chaining.
-     */
-    public static ConfigurationContextChangeBuilder of() {
-        return new ConfigurationContextChangeBuilder();
-    }
-
-    /*
-     * Apply a version/UUID to the set being built.
-     * @param version the version to apply, or null, to let the system generate a version for you.
-     * @return the builder for chaining.
-     */
-    public ConfigurationContextChangeBuilder setVersion(String version) {
-        this.version = version;
-        return this;
-    }
-
-    /*
-     * Apply given timestamp to the set being built.
-     * @param version the version to apply, or null, to let the system generate a version for you.
-     * @return the builder for chaining.
-     */
-    public ConfigurationContextChangeBuilder setTimestamp(long timestamp) {
-        this.timestamp = timestamp;
-        return this;
-    }
-
-    /**
-     * This method records all changes to be applied to the base property provider/configuration to
-     * achieve the given target state.
-     *
-     * @param propertySource the new target state, not null.
-     * @return the builder for chaining.
-     */
-    public ConfigurationContextChangeBuilder newPropertySource(PropertySource propertySource) {
-        this.changedPropertySources.add(PropertySourceChange.ofAdded(propertySource));
-        return this;
-    }
-
-    /**
-     * This method records all changes to be applied to the base property provider/configuration to
-     * achieve the given target state.
-     *
-     * @param propertySource the new target state, not null.
-     * @return the builder for chaining.
-     */
-    public ConfigurationContextChangeBuilder removedPropertySource(PropertySource propertySource) {
-        this.changedPropertySources.add(PropertySourceChange.ofDeleted(propertySource));
-        return this;
-    }
-
-    /**
-     * This method records all changes to be applied to the base property provider/configuration to
-     * achieve the given target state.
-     *
-     * @param propertySourceChange the change state, not null.
-     * @return the builder for chaining.
-     */
-    public ConfigurationContextChangeBuilder changedPropertySource(PropertySourceChange propertySourceChange) {
-        this.changedPropertySources.add(Objects.requireNonNull(propertySourceChange));
-        return this;
-    }
-
-    /**
-     * Checks if the change set is empty, i.e. does not contain any changes.
-     *
-     * @return true, if the set is empty.
-     */
-    public boolean isEmpty() {
-        return this.changedPropertySources.isEmpty();
-    }
-
-    /**
-     * Resets this change set instance. This will clear all changes done to this builder, so the
-     * set will be empty.
-     */
-    public void reset() {
-        this.changedPropertySources.clear();
-    }
-
-    /**
-     * Builds the corresponding change set.
-     *
-     * @return the new change set, never null.
-     */
-    public ConfigurationContextChange build() {
-        return new ConfigurationContextChange(this);
-    }
-
-    /*
-     * (non-Javadoc)
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "ConfigurationContextChangeBuilder [propertySources=" + changedPropertySources + "]";
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/java/org/apache/tamaya/events/delta/PropertySourceChange.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/tamaya/events/delta/PropertySourceChange.java b/src/main/java/org/apache/tamaya/events/delta/PropertySourceChange.java
deleted file mode 100644
index 330f3b0..0000000
--- a/src/main/java/org/apache/tamaya/events/delta/PropertySourceChange.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.events.delta;
-
-import org.apache.tamaya.events.ChangeNotification;
-import org.apache.tamaya.events.FrozenPropertySource;
-import org.apache.tamaya.spi.PropertySource;
-
-import java.beans.PropertyChangeEvent;
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-
-/**
- * Event that contains a set current changes that were applied or could be applied.
- * This class is immutable and thread-safe. To create instances use
- * {@link org.apache.tamaya.events.delta.PropertySourceChangeBuilder}.
- *
- * Created by Anatole on 22.10.2014.
- */
-public final class PropertySourceChange implements ChangeNotification<PropertySource>, Serializable{
-
-    private static final long serialVersionUID = 1L;
-    /** The base property provider/configuration. */
-    private FrozenPropertySource propertySource;
-    /** The base version, usable for optimistic locking. */
-    private String version = UUID.randomUUID().toString();
-    /** The timestamp of the change set in millis from the epoch. */
-    private long timestamp = System.currentTimeMillis();
-    /** The recorded changes. */
-    private Map<String,PropertyChangeEvent> changes = new HashMap<>();
-    /** The overall type of change. */
-    private ChangeType changeType;
-
-    /**
-     * Constructor used by {@link org.apache.tamaya.events.delta.PropertySourceChangeBuilder}.
-     * @param builder The builder used, not null.
-     */
-    PropertySourceChange(PropertySourceChangeBuilder builder) {
-        this.propertySource = FrozenPropertySource.of(builder.source);
-        for (PropertyChangeEvent c : builder.delta.values()) {
-            this.changes.put(c.getPropertyName(), c);
-        }
-        if(builder.version!=null){
-            this.version = builder.version;
-        }
-        if(builder.timestamp!=null){
-            this.timestamp = builder.timestamp;
-        }
-        this.changeType = builder.changeType;
-    }
-
-    /**
-     * Gets the type of change for this PropertySource.
-     * @return the type of change for this PropertySource, never null.
-     */
-    public ChangeType getChangeType(){
-        return this.changeType;
-    }
-
-    /**
-     * Get the underlying property provider/configuration.
-     * @return the underlying property provider/configuration, or null, if the change instance was deserialized.
-     */
-    public PropertySource getResource(){
-        return this.propertySource;
-    }
-
-    /**
-     * Get the base version, usable for optimistic locking.
-     * @return the base version.
-     */
-    public String getVersion(){
-        return version;
-    }
-
-    /**
-     * Get the timestamp in millis from the current epoch. it is expected that the timestamp and the version are unique to
-     * identify a changeset.
-     * @return the timestamp, when this changeset was created.
-     */
-    public long getTimestamp(){
-        return timestamp;
-    }
-
-    /**
-     * Get the changes recorded.
-     * @return the recorded changes, never null.
-     */
-    public Collection<PropertyChangeEvent> getChanges(){
-        return Collections.unmodifiableCollection(this.changes.values());
-    }
-
-    /**
-     * Access the number current removed entries.
-     * @return the number current removed entries.
-     */
-    public int getRemovedSize() {
-        int removedCount = 0;
-        for (PropertyChangeEvent ev : this.changes.values()) {
-            if (ev.getNewValue() == null) {
-                removedCount++;
-            }
-        }
-        return removedCount;
-//        return (int) this.changes.values().stream().filter((e) -> e.getNewValue() == null).count();
-    }
-
-    /**
-     * Access the number current added entries.
-     * @return the number current added entries.
-     */
-    public int getAddedSize() {
-        int addedCount = 0;
-        for (PropertyChangeEvent ev : this.changes.values()) {
-            if (ev.getOldValue() == null &&
-                    ev.getNewValue() != null) {
-                addedCount++;
-            }
-        }
-        return addedCount;
-//        return (int) this.changes.values().stream().filter((e) -> e.getOldValue() == null).count();
-    }
-
-    /**
-     * Access the number current updated entries.
-     * @return the number current updated entries.
-     */
-    public int getUpdatedSize() {
-        int updatedCount = 0;
-        for (PropertyChangeEvent ev : this.changes.values()) {
-            if (ev.getOldValue() != null && ev.getNewValue() != null) {
-                updatedCount++;
-            }
-        }
-        return updatedCount;
-//        return (int) this.changes.values().stream().filter((e) -> e.getOldValue()!=null && e.getNewValue()!=null).count();
-    }
-
-
-    /**
-     * Checks if the given key was removed.
-     * @param key the target key, not null.
-     * @return true, if the given key was removed.
-     */
-    public boolean isRemoved(String key) {
-        PropertyChangeEvent change = this.changes.get(key);
-        return change != null && change.getNewValue() == null;
-    }
-
-    /**
-     * Checks if the given key was added.
-     * @param key the target key, not null.
-     * @return true, if the given key was added.
-     */
-    public boolean isAdded(String key) {
-        PropertyChangeEvent change = this.changes.get(key);
-        return change != null && change.getOldValue() == null;
-    }
-
-    /**
-     * Checks if the given key was updated.
-     * @param key the target key, not null.
-     * @return true, if the given key was updated.
-     */
-    public boolean isUpdated(String key) {
-        PropertyChangeEvent change = this.changes.get(key);
-        return change != null && change.getOldValue() != null && change.getNewValue() != null;
-    }
-
-    /**
-     * Checks if the given key is added, or updated AND NOT removed.
-     * @param key the target key, not null.
-     * @return true, if the given key was added, or updated BUT NOT removed.
-     */
-    public boolean isKeyAffected(String key) {
-        PropertyChangeEvent change = this.changes.get(key);
-        return change != null && change.getNewValue() != null;
-    }
-
-    /**
-     * CHecks if the current change set does not contain any changes.
-     * @return tru, if the change set is empty.
-     */
-    public boolean isEmpty(){
-        return this.changes.isEmpty();
-    }
-
-
-    /**
-     * Create a change event for a new PropertySource that was added.
-     * @param propertySource the new property source, not null.
-     * @return a new PropertySourceChange, representing a PropertySource that was added.
-     */
-    public static PropertySourceChange ofAdded(PropertySource propertySource) {
-        return PropertySourceChangeBuilder.of(propertySource, ChangeType.NEW).build();
-    }
-
-    /**
-     * Create a change event for a deleted PropertySource.
-     * @param propertySource the deleted property source, not null.
-     * @return a new PropertySourceChange, representing a PropertySource that was deleted.
-     */
-    public static PropertySourceChange ofDeleted(PropertySource propertySource) {
-        return PropertySourceChangeBuilder.of(propertySource, ChangeType.DELETED).build();
-    }
-
-    @Override
-    public String toString() {
-        return "PropertySourceChange{" +
-                "changeType=" + changeType +
-                ", propertySource=" + propertySource +
-                ", version='" + version + '\'' +
-                ", timestamp=" + timestamp +
-                '}';
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/java/org/apache/tamaya/events/delta/PropertySourceChangeBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/tamaya/events/delta/PropertySourceChangeBuilder.java b/src/main/java/org/apache/tamaya/events/delta/PropertySourceChangeBuilder.java
deleted file mode 100644
index a0c0027..0000000
--- a/src/main/java/org/apache/tamaya/events/delta/PropertySourceChangeBuilder.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.events.delta;
-
-import org.apache.tamaya.spi.PropertySource;
-
-import java.beans.PropertyChangeEvent;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-/**
- * Models a set current changes applied to a {@link org.apache.tamaya.spi.PropertySource}. Consumers of these events
- * can observing changes to property sources and
- * <ol>
- *     <li>Check if their current configuration instance ({@link org.apache.tamaya.spi.ConfigurationContext}
- *     contains the changed {@link org.apache.tamaya.spi.PropertySource} (Note: the reference tova property source is never affected by a
- *     change, its only the data of the property source).</li>
- *     <li>If so corresponding action may be taken, such as reevaluating the configuration values (depending on
- *     the update policy) or reevaluating the complete {@link org.apache.tamaya.Configuration} to create a change
- *     event on configuration level.
- * </ol>
- */
-public final class PropertySourceChangeBuilder {
-    /**
-     * The recorded changes.
-     */
-    final SortedMap<String, PropertyChangeEvent> delta = new TreeMap<>();
-    /**
-     * The underlying configuration/provider.
-     */
-    PropertySource source;
-    /**
-     * The version configured, or null, for generating a default.
-     */
-    String version;
-    /**
-     * The optional timestamp in millis of this epoch.
-     */
-    Long timestamp;
-
-    /** The type of change. */
-    ChangeType changeType;
-
-    /**
-     * Constructor.
-     *
-     * @param source the underlying configuration/provider, not null.
-     */
-    private PropertySourceChangeBuilder(PropertySource source, ChangeType changeType) {
-        this.source = Objects.requireNonNull(source);
-        this.changeType = Objects.requireNonNull(changeType);
-    }
-
-    /**
-     * Creates a new instance current this builder.
-     *
-     * @param source the underlying property provider/configuration, not null.
-     * @return the builder for chaining.
-     */
-    public static PropertySourceChangeBuilder of(PropertySource source, ChangeType changeType) {
-        return new PropertySourceChangeBuilder(source, changeType);
-    }
-
-    /**
-     * Compares the two property config/configurations and creates a collection current all changes
-     * that must be appied to render {@code map1} into {@code map2}.
-     *
-     * @param map1 the source map, not null.
-     * @param map2 the target map, not null.
-     * @return a collection current change events, never null.
-     */
-    public static Collection<PropertyChangeEvent> compare(PropertySource map1, PropertySource map2) {
-        List<PropertyChangeEvent> changes = new ArrayList<>();
-        for (Map.Entry<String, String> en : map1.getProperties().entrySet()) {
-            String val = map2.get(en.getKey());
-            if (val == null) {
-                changes.add(new PropertyChangeEvent(map1, en.getKey(), null, en.getValue()));
-            } else if (!val.equals(en.getValue())) {
-                changes.add(new PropertyChangeEvent(map1, en.getKey(), val, en.getValue()));
-            }
-        }
-        for (Map.Entry<String, String> en : map2.getProperties().entrySet()) {
-            String val = map1.get(en.getKey());
-            if (val == null) {
-                changes.add(new PropertyChangeEvent(map1, en.getKey(), en.getValue(), null));
-            } else if (!val.equals(en.getValue())) {
-                changes.add(new PropertyChangeEvent(map1, en.getKey(), en.getValue(), val));
-            }
-        }
-        return changes;
-    }
-
-    /*
-     * Apply a version/UUID to the set being built.
-     * @param version the version to apply, or null, to let the system generate a version for you.
-     * @return the builder for chaining.
-     */
-    public PropertySourceChangeBuilder setVersion(String version) {
-        this.version = version;
-        return this;
-    }
-
-    /*
-     * Apply given timestamp to the set being built.
-     * @param version the version to apply, or null, to let the system generate a version for you.
-     * @return the builder for chaining.
-     */
-    public PropertySourceChangeBuilder setTimestamp(long timestamp) {
-        this.timestamp = timestamp;
-        return this;
-    }
-
-    /**
-     * This method records all changes to be applied to the base property provider/configuration to
-     * achieve the given target state.
-     *
-     * @param newState the new target state, not null.
-     * @return the builder for chaining.
-     */
-    public PropertySourceChangeBuilder addChanges(PropertySource newState) {
-        Collection<PropertyChangeEvent> events = PropertySourceChangeBuilder.compare(newState, this.source);
-        for (PropertyChangeEvent c : events) {
-            this.delta.put(c.getPropertyName(), c);
-        }
-        return this;
-    }
-
-    /**
-     * Get the current values, also considering any changes recorded within this change set.
-     *
-     * @param key the key current the entry, not null.
-     * @return the keys, or null.
-     */
-    public String get(String key) {
-        PropertyChangeEvent change = this.delta.get(key);
-        if (change != null && !(change.getNewValue() == null)) {
-            return (String) change.getNewValue();
-        }
-        return null;
-    }
-
-    /**
-     * Marks the given key(s) fromMap the configuration/properties to be removed.
-     *
-     * @param key       the key current the entry, not null.
-     * @param otherKeys additional keys to be removed (convenience), not null.
-     * @return the builder for chaining.
-     */
-    public PropertySourceChangeBuilder remove(String key, String... otherKeys) {
-        String oldValue = this.source.get(key);
-        if (oldValue == null) {
-            this.delta.remove(key);
-        }
-        this.delta.put(key, new PropertyChangeEvent(this.source, key, oldValue, null));
-        for (String addKey : otherKeys) {
-            oldValue = this.source.get(addKey);
-            if (oldValue == null) {
-                this.delta.remove(addKey);
-            }
-            this.delta.put(addKey, new PropertyChangeEvent(this.source, addKey, oldValue, null));
-        }
-        return this;
-    }
-
-    /**
-     * Apply all the given values to the base configuration/properties.
-     * Note that all values passed must be convertible to String, either
-     * <ul>
-     * <li>the registered codecs provider provides codecs for the corresponding keys, or </li>
-     * <li>default codecs are present for the given type, or</li>
-     * <li>the value is an instanceof String</li>
-     * </ul>
-     *
-     * @param changes the changes to be applied, not null.
-     * @return the builder for chaining.
-     */
-    public PropertySourceChangeBuilder putAll(Map<String, String> changes) {
-        changes.putAll(changes);
-        return this;
-    }
-
-    /**
-     * This method will create a change set that clears all entries fromMap the given base configuration/properties.
-     *
-     * @return the builder for chaining.
-     */
-    public PropertySourceChangeBuilder deleteAll() {
-        this.delta.clear();
-        for (Map.Entry<String, String> en : this.source.getProperties().entrySet()) {
-            this.delta.put(en.getKey(), new PropertyChangeEvent(this.source, en.getKey(), en.getValue(), null));
-        }
-        return this;
-    }
-
-    /**
-     * Checks if the change set is empty, i.e. does not contain any changes.
-     *
-     * @return true, if the set is empty.
-     */
-    public boolean isEmpty() {
-        return this.delta.isEmpty();
-    }
-
-    /**
-     * Resets this change set instance. This will clear all changes done to this builder, so the
-     * set will be empty.
-     */
-    public void reset() {
-        this.delta.clear();
-    }
-
-    public PropertySourceChangeBuilder setChangeType(ChangeType changeType) {
-        this.changeType = changeType;
-        return this;
-    }
-
-    /**
-     * Builds the corresponding change set.
-     *
-     * @return the new change set, never null.
-     */
-    public PropertySourceChange build() {
-        return new PropertySourceChange(this);
-    }
-
-    /*
-     * (non-Javadoc)
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "PropertiesChangeBuilder [source=" + source + ", " +
-                ", delta=" + delta + "]";
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/java/org/apache/tamaya/events/folderobserver/FileChangeListener.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/tamaya/events/folderobserver/FileChangeListener.java b/src/main/java/org/apache/tamaya/events/folderobserver/FileChangeListener.java
index dd64145..af51063 100644
--- a/src/main/java/org/apache/tamaya/events/folderobserver/FileChangeListener.java
+++ b/src/main/java/org/apache/tamaya/events/folderobserver/FileChangeListener.java
@@ -19,6 +19,7 @@
 package org.apache.tamaya.events.folderobserver;
 
 import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.events.PropertySourceChange;
 
 import java.io.IOException;
 import java.nio.file.FileSystem;
@@ -34,7 +35,7 @@ import java.util.logging.Logger;
 
 /**
  * Class that has the responsibility to watch the folder and then publish the changes to a
- * {@link org.apache.tamaya.events.delta.PropertySourceChange}.
+ * {@link PropertySourceChange}.
  * @see ObservingPropertySourceProvider
  * This listener will wait to events and wait to one second to watch again.
  * <p>If new file was created or modified will commit from this file.</p>

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/java/org/apache/tamaya/events/folderobserver/ObservingPropertySourceProvider.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/tamaya/events/folderobserver/ObservingPropertySourceProvider.java b/src/main/java/org/apache/tamaya/events/folderobserver/ObservingPropertySourceProvider.java
index 9b88c0a..14692f4 100644
--- a/src/main/java/org/apache/tamaya/events/folderobserver/ObservingPropertySourceProvider.java
+++ b/src/main/java/org/apache/tamaya/events/folderobserver/ObservingPropertySourceProvider.java
@@ -19,9 +19,11 @@
 package org.apache.tamaya.events.folderobserver;
 
 import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.ConfigurationProvider;
 import org.apache.tamaya.events.ConfigEventManager;
-import org.apache.tamaya.events.delta.ConfigurationContextChange;
-import org.apache.tamaya.events.delta.ConfigurationContextChangeBuilder;
+import org.apache.tamaya.events.PropertySourceChange;
+import org.apache.tamaya.events.ConfigurationContextChange;
+import org.apache.tamaya.events.ConfigurationContextChangeBuilder;
 import org.apache.tamaya.format.ConfigurationData;
 import org.apache.tamaya.format.ConfigurationFormat;
 import org.apache.tamaya.format.FlattenedDefaultPropertySource;
@@ -50,7 +52,7 @@ import java.util.logging.Logger;
  * This implementation run in a folder taking up all file compatible with the given
  * ConfigurationFormats. When a file is added, deleted or modified the PropertySourceProvider
  * will adapt the changes automatically and trigger according
- * {@link org.apache.tamaya.events.delta.PropertySourceChange} events.
+ * {@link PropertySourceChange} events.
  * The default folder is META-INF/config, but you can change using the absolute path in
  * "-Dtamaya.configdir" parameter.
  */

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/java/org/apache/tamaya/events/internal/DefaultConfigChangeObserver.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/tamaya/events/internal/DefaultConfigChangeObserver.java b/src/main/java/org/apache/tamaya/events/internal/DefaultConfigChangeObserver.java
new file mode 100644
index 0000000..8903566
--- /dev/null
+++ b/src/main/java/org/apache/tamaya/events/internal/DefaultConfigChangeObserver.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.events.internal;
+
+import org.apache.tamaya.ConfigurationProvider;
+import org.apache.tamaya.events.*;
+
+import java.util.*;
+import java.util.logging.Logger;
+
+/**
+ * Timer task that regularly checks the configuration for changes.
+ */
+public class DefaultConfigChangeObserver {
+
+    private static final long START_DELAY = 5000L;
+
+    private static final Logger LOG = Logger.getLogger(DefaultConfigChangeObserver.class.getName());
+
+    private Timer timer = new Timer("DefaultConfigChangeObserver", true);
+
+    private long checkPeriod = 2000L;
+
+    private volatile FrozenConfiguration lastConfig;
+
+    private volatile boolean running;
+
+    /**
+     * Constructor. Also loads all registered listeners.
+     */
+    public DefaultConfigChangeObserver() {
+        LOG.info("Registering config change observer, rechecking config changes every " + checkPeriod + " ms.");
+        timer.scheduleAtFixedRate(new TimerTask() {
+            @Override
+            public void run() {
+                if(running) {
+                    checkConfigurationUpdate();
+                }
+            }
+        }, START_DELAY, checkPeriod);
+    }
+
+
+    public void checkConfigurationUpdate() {
+        LOG.finest("Checking configuration for changes...");
+        FrozenConfiguration newConfig = FrozenConfiguration.of(ConfigurationProvider.getConfiguration());
+        ConfigurationChange changes = null;
+        if(lastConfig==null){
+            changes = ConfigurationChangeBuilder.of(newConfig).putAll(newConfig.getProperties())
+                    .build();
+        }else{
+            changes = ConfigurationChangeBuilder.of(lastConfig).addChanges(newConfig)
+                    .build();
+        }
+        if(!changes.isEmpty()) {
+            LOG.info("Identified configuration changes, publishing change event...");
+            ConfigEventManager.fireEvent(changes);
+        }
+    }
+
+    public long getCheckPeriod() {
+        return checkPeriod;
+    }
+
+    public boolean isMonitoring(){
+        return running;
+    }
+
+    public void enableMonitoring(boolean enable){
+        this.running = true;
+    }
+
+    /**
+     * Sets the new check period, cancels the currently running timer and schedules a new task with the new checkperiod
+     * and a startup delay of 500ms.
+     * @param checkPeriod
+     */
+    public void setCheckPeriod(long checkPeriod) {
+        LOG.finest("Resetting check period to " + checkPeriod + " ms, reregistering timer.");
+        this.checkPeriod = checkPeriod;
+        timer.cancel();
+        timer.scheduleAtFixedRate(new TimerTask() {
+            @Override
+            public void run() {
+                if(running) {
+                    checkConfigurationUpdate();
+                }
+            }
+        }, 500L, checkPeriod);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/java/org/apache/tamaya/events/internal/DefaultConfigEventManagerSpi.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/tamaya/events/internal/DefaultConfigEventManagerSpi.java b/src/main/java/org/apache/tamaya/events/internal/DefaultConfigEventManagerSpi.java
index 6773c7d..75f2c91 100644
--- a/src/main/java/org/apache/tamaya/events/internal/DefaultConfigEventManagerSpi.java
+++ b/src/main/java/org/apache/tamaya/events/internal/DefaultConfigEventManagerSpi.java
@@ -18,18 +18,15 @@
  */
 package org.apache.tamaya.events.internal;
 
-import org.apache.tamaya.TypeLiteral;
+import org.apache.tamaya.events.ConfigEvent;
 import org.apache.tamaya.events.ConfigEventListener;
 import org.apache.tamaya.events.spi.ConfigEventManagerSpi;
 import org.apache.tamaya.spi.ServiceContextManager;
 
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -41,14 +38,18 @@ public class DefaultConfigEventManagerSpi implements ConfigEventManagerSpi {
 
     private static final Logger LOG = Logger.getLogger(DefaultConfigEventManagerSpi.class.getName());
 
-    private Map<Type, List<ConfigEventListener<?>>> listenerMap = new ConcurrentHashMap<>();
+    private Map<Class,List<ConfigEventListener>> listeners = new ConcurrentHashMap<>();
+
+    private ExecutorService publisher = Executors.newCachedThreadPool();
+
+    private DefaultConfigChangeObserver changeObserver = new DefaultConfigChangeObserver();
 
     /**
      * Constructor. Also loads all registered listeners.
      */
     public DefaultConfigEventManagerSpi() {
         try {
-            for (ConfigEventListener<?> l : ServiceContextManager.getServiceContext().getServices(ConfigEventListener.class)) {
+            for (ConfigEventListener l : ServiceContextManager.getServiceContext().getServices(ConfigEventListener.class)) {
                 try {
                     addListener(l);
                 } catch (Exception e) {
@@ -61,37 +62,76 @@ public class DefaultConfigEventManagerSpi implements ConfigEventManagerSpi {
     }
 
     @Override
-    public <T> void addListener(ConfigEventListener<T> l) {
-        Type type = TypeLiteral.getGenericInterfaceTypeParameters(l.getClass(), ConfigEventListener.class)[0];
-        List<ConfigEventListener<?>> listeners = listenerMap.get(type);
-        if (listeners == null) {
-            listeners = Collections.synchronizedList(new ArrayList<ConfigEventListener<?>>());
-            listenerMap.put(type, listeners);
+    public void addListener(ConfigEventListener l){
+        addListener(l, ConfigEvent.class);
+    }
+
+    @Override
+    public <T extends ConfigEvent> void addListener(ConfigEventListener l, Class<T> eventType){
+        List<ConfigEventListener> ls = listeners.get(eventType);
+        if(ls==null){
+            ls = Collections.synchronizedList(new ArrayList<ConfigEventListener>());
+            listeners.put(eventType, ls);
         }
-        synchronized (listeners) {
-            if (!listeners.contains(l)) {
-                listeners.add(l);
+        synchronized (ls){
+            if(!ls.contains(l)){
+                ls.add(l);
             }
         }
     }
 
     @Override
-    public <T> void removeListener(ConfigEventListener<T> l) {
-        Type type = TypeLiteral.getGenericInterfaceTypeParameters(l.getClass(), ConfigEventListener.class)[0];
-        List<ConfigEventListener<?>> listeners = listenerMap.get(type);
-        if (listeners != null) {
-            synchronized (listeners) {
-                listeners.remove(l);
+    public void removeListener(ConfigEventListener l){
+        removeListener(l, ConfigEvent.class);
+    }
+
+    @Override
+    public <T extends ConfigEvent> void removeListener(ConfigEventListener l, Class<T> eventType) {
+        List<ConfigEventListener> targets = this.listeners.get(eventType);
+        if(targets!=null) {
+            // forward to explicit listeners
+            synchronized (targets) {
+                targets.remove(l);
             }
         }
     }
 
     @Override
-    public <T> void fireEvent(T event, Class<T> eventType) {
-        List<ConfigEventListener<?>> listeners = listenerMap.get(eventType);
-        if (listeners != null) {
-            synchronized (listeners) {
-                for (ConfigEventListener l : listeners) {
+    public Collection<? extends ConfigEventListener> getListeners(Class<? extends ConfigEvent> eventType) {
+        List<ConfigEventListener> targets = this.listeners.get(eventType);
+        if(targets!=null){
+            synchronized(targets){
+                return new ArrayList<>(targets);
+            }
+        }
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Collection<? extends ConfigEventListener> getListeners() {
+        Set<ConfigEventListener> targets = new HashSet<>();
+        for(List<ConfigEventListener> l:this.listeners.values()){
+            targets.addAll(l);
+        }
+        return targets;
+    }
+
+    @Override
+    public void fireEvent(ConfigEvent<?> event) {
+        List<ConfigEventListener> targets = this.listeners.get(event.getClass());
+        if(targets!=null) {
+            // forward to explicit listeners
+            synchronized (targets) {
+                for (ConfigEventListener l : targets) {
+                    l.onConfigEvent(event);
+                }
+            }
+        }
+        // forward to global listeners
+        targets = this.listeners.get(ConfigEvent.class);
+        if(targets!=null) {
+            synchronized (targets) {
+                for (ConfigEventListener l : targets) {
                     l.onConfigEvent(event);
                 }
             }
@@ -99,12 +139,64 @@ public class DefaultConfigEventManagerSpi implements ConfigEventManagerSpi {
     }
 
     @Override
-    public <T> Collection<ConfigEventListener<T>> getListeners(Class<T> eventType) {
-        List<ConfigEventListener<?>> listeners =
-                listenerMap.get(eventType);
-        if (listeners != null) {
-            return Collection.class.cast(listeners);
+    public void fireEventAsynch(ConfigEvent<?> event) {
+        List<ConfigEventListener> targets = this.listeners.get(event.getClass());
+        if(targets!=null) {
+            // forward to explicit listeners
+            synchronized (targets) {
+                for (ConfigEventListener l : targets) {
+                    publisher.execute(new PublishConfigChangeTask(l, event));
+                }
+            }
+        }
+        // forward to global listeners
+        targets = this.listeners.get(ConfigEvent.class);
+        if(targets!=null) {
+            synchronized (targets) {
+                for (ConfigEventListener l : targets) {
+                    publisher.execute(new PublishConfigChangeTask(l, event));
+                }
+            }
+        }
+    }
+
+    @Override
+    public long getChangeMonitoringPeriod() {
+        return changeObserver.getCheckPeriod();
+    }
+
+    @Override
+    public void setChangeMonitoringPeriod(long millis){
+        changeObserver.setCheckPeriod(millis);
+    }
+
+    @Override
+    public boolean isChangeMonitorActive() {
+        return changeObserver.isMonitoring();
+    }
+
+    @Override
+    public void enableChangeMonitor(boolean enable) {
+        changeObserver.enableMonitoring(enable);
+    }
+
+
+    /**
+     * Tasks to inform observers on detected configuration changes.
+     */
+    private static final class PublishConfigChangeTask implements Runnable{
+
+        private ConfigEventListener l;
+        private ConfigEvent<?> changes;
+
+        public PublishConfigChangeTask(ConfigEventListener l, ConfigEvent<?> changes) {
+            this.l = Objects.requireNonNull(l);
+            this.changes = Objects.requireNonNull(changes);
+        }
+
+        @Override
+        public void run() {
+            l.onConfigEvent(changes);
         }
-        return Collections.emptyList();
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/java/org/apache/tamaya/events/internal/DefaultConfigObserverSpi.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/tamaya/events/internal/DefaultConfigObserverSpi.java b/src/main/java/org/apache/tamaya/events/internal/DefaultConfigObserverSpi.java
deleted file mode 100644
index 6bcb44c..0000000
--- a/src/main/java/org/apache/tamaya/events/internal/DefaultConfigObserverSpi.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.events.internal;
-
-import org.apache.tamaya.ConfigurationProvider;
-import org.apache.tamaya.events.ConfigEventManager;
-import org.apache.tamaya.events.ConfigListener;
-import org.apache.tamaya.events.FrozenConfiguration;
-import org.apache.tamaya.events.delta.ConfigurationChange;
-import org.apache.tamaya.events.delta.ConfigurationChangeBuilder;
-import org.apache.tamaya.events.spi.ConfigObserverSpi;
-import org.apache.tamaya.spi.ServiceContextManager;
-
-import java.beans.PropertyChangeEvent;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.Set;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Default implementation of {@link org.apache.tamaya.events.spi.ConfigObserverSpi} just forwarding all
- * events synchronously to the listeners.
- */
-public class DefaultConfigObserverSpi implements ConfigObserverSpi {
-
-    private static final long START_DELAY = 5000L;
-
-    private static final Logger LOG = Logger.getLogger(DefaultConfigObserverSpi.class.getName());
-
-    private Set<String> keys = new HashSet<>();
-
-    private Timer timer = new Timer("ConfigurationObserver", true);
-
-    private long checkPeriod = 2000L;
-
-    private volatile FrozenConfiguration lastConfig;
-
-    private ExecutorService publisher = Executors.newCachedThreadPool();
-
-    private volatile boolean running;
-
-    /**
-     * Constructor. Also loads all registered listeners.
-     */
-    public DefaultConfigObserverSpi() {
-        try {
-            // Load and register ConfigListener from the current ServiceContext
-            for (ConfigListener l : ServiceContextManager.getServiceContext().getServices(ConfigListener.class)) {
-                ConfigEventManager.addListener(l);
-            }
-        } catch (Exception e) {
-            LOG.log(Level.WARNING, "Failed to load configured listeners.", e);
-        }
-        timer.scheduleAtFixedRate(new TimerTask() {
-            @Override
-            public void run() {
-                if(running) {
-                    checkConfigurationUpdate();
-                }
-            }
-        }, START_DELAY, checkPeriod);
-    }
-
-    public void checkConfigurationUpdate() {
-        LOG.finest("Checking configuration for changes...");
-        FrozenConfiguration newConfig = FrozenConfiguration.of(ConfigurationProvider.getConfiguration());
-        ConfigurationChange changes = null;
-        if(lastConfig==null){
-            changes = ConfigurationChangeBuilder.of(newConfig).putAll(newConfig.getProperties())
-                    .build();
-        }else{
-            changes = ConfigurationChangeBuilder.of(lastConfig).addChanges(newConfig)
-                    .build();
-        }
-        Set<ConfigListener> affected = new HashSet<>();
-        for(PropertyChangeEvent evt: changes.getChanges()) {
-            for (String key : keys) {
-                if (evt.getPropertyName().matches(key)) {
-                    ConfigEventManager.fireEvent(changes);
-                    return;
-                }
-            }
-        }
-    }
-
-    @Override
-    public synchronized <T> void addObservedKeys(Collection<String> keys) {
-        this.keys.addAll(keys);
-    }
-
-    @Override
-    public synchronized <T> void removeObservedKeys(Collection<String> keys) {
-        this.keys.removeAll(keys);
-    }
-
-
-    @Override
-    public synchronized Set<String> getObservedKeys() {
-        return Collections.unmodifiableSet(this.keys);
-    }
-
-    @Override
-    public long getCheckPeriod() {
-        return checkPeriod;
-    }
-
-    @Override
-    public boolean isRunning(){
-        return running;
-    }
-
-    @Override
-    public void enableObservation(boolean enable){
-        this.running = true;
-    }
-
-    /**
-     * Tasks to inform observers on detected configuration changes.
-     */
-    private static final class PublishConfigChangeTask implements Runnable{
-
-        private ConfigListener l;
-        private ConfigurationChange changes;
-
-        public PublishConfigChangeTask(ConfigListener l, ConfigurationChange changes) {
-            this.l = Objects.requireNonNull(l);
-            this.changes = Objects.requireNonNull(changes);
-        }
-
-        @Override
-        public void run() {
-            l.onConfigEvent(changes);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/java/org/apache/tamaya/events/internal/DefaultConfigurationContextChangeListener.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/tamaya/events/internal/DefaultConfigurationContextChangeListener.java b/src/main/java/org/apache/tamaya/events/internal/DefaultConfigurationContextChangeListener.java
index fed5e40..e49856d 100644
--- a/src/main/java/org/apache/tamaya/events/internal/DefaultConfigurationContextChangeListener.java
+++ b/src/main/java/org/apache/tamaya/events/internal/DefaultConfigurationContextChangeListener.java
@@ -19,13 +19,17 @@
 package org.apache.tamaya.events.internal;
 
 import org.apache.tamaya.ConfigurationProvider;
+import org.apache.tamaya.events.ConfigEvent;
 import org.apache.tamaya.events.ConfigEventListener;
-import org.apache.tamaya.events.delta.ConfigurationContextChange;
+import org.apache.tamaya.events.ConfigurationContextChange;
 import org.apache.tamaya.spi.ConfigurationContext;
 import org.apache.tamaya.spi.ConfigurationContextBuilder;
 import org.apache.tamaya.spi.PropertySource;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -33,35 +37,38 @@ import java.util.logging.Logger;
  * Default ConfigEventListener for ConfigurationContextChange events that updates the current context, if resources were
  * affected.
  */
-public class DefaultConfigurationContextChangeListener implements ConfigEventListener<ConfigurationContextChange> {
+public class DefaultConfigurationContextChangeListener implements ConfigEventListener {
 
     private static final Logger LOG = Logger.getLogger(DefaultConfigurationContextChangeListener.class.getName());
 
     @Override
-    public void onConfigEvent(ConfigurationContextChange event) {
-        ConfigurationContext context = ConfigurationProvider.getConfigurationContext();
-        List<PropertySource> affectedPropertySources = new ArrayList<>();
-        for (PropertySource ps : context.getPropertySources()) {
-            if (event.isAffected(ps)) {
-                affectedPropertySources.add(ps);
+    public void onConfigEvent(ConfigEvent<?> event) {
+        if(event.getClass() == ConfigurationContextChange.class) {
+            ConfigurationContextChange contextChange = (ConfigurationContextChange) event;
+            ConfigurationContext context = ConfigurationProvider.getConfigurationContext();
+            List<PropertySource> affectedPropertySources = new ArrayList<>();
+            for (PropertySource ps : context.getPropertySources()) {
+                if (contextChange.isAffected(ps)) {
+                    affectedPropertySources.add(ps);
+                }
             }
-        }
-        ConfigurationContextBuilder newContextBuilder = ConfigurationProvider.getConfigurationContextBuilder()
-                .setContext(context);
-        if (!affectedPropertySources.isEmpty()) {
-            Set<String> propertySourceNames = new HashSet<>();
-            for (PropertySource removed : event.getRemovedPropertySources()) {
-                propertySourceNames.add(removed.getName());
+            ConfigurationContextBuilder newContextBuilder = ConfigurationProvider.getConfigurationContextBuilder()
+                    .setContext(context);
+            if (!affectedPropertySources.isEmpty()) {
+                Set<String> propertySourceNames = new HashSet<>();
+                for (PropertySource removed : contextChange.getRemovedPropertySources()) {
+                    propertySourceNames.add(removed.getName());
+                }
+                newContextBuilder.removePropertySources(propertySourceNames);
+            }
+            newContextBuilder.addPropertySources(contextChange.getAddedPropertySources());
+            newContextBuilder.addPropertySources(contextChange.getUpdatedPropertySources());
+            ConfigurationContext newContext = newContextBuilder.build();
+            try {
+                ConfigurationProvider.setConfigurationContext(newContext);
+            } catch (Exception e) {
+                LOG.log(Level.INFO, "Failed to update the current ConfigurationContext due to config model changes", e);
             }
-            newContextBuilder.removePropertySources(propertySourceNames);
-        }
-        newContextBuilder.addPropertySources(event.getAddedPropertySources());
-        newContextBuilder.addPropertySources(event.getUpdatedPropertySources());
-        ConfigurationContext newContext = newContextBuilder.build();
-        try {
-            ConfigurationProvider.setConfigurationContext(newContext);
-        } catch (Exception e) {
-            LOG.log(Level.INFO, "Failed to update the current ConfigurationContext due to config model changes", e);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/java/org/apache/tamaya/events/internal/LoggingConfigListener.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/tamaya/events/internal/LoggingConfigListener.java b/src/main/java/org/apache/tamaya/events/internal/LoggingConfigListener.java
index 43b2700..41d6924 100644
--- a/src/main/java/org/apache/tamaya/events/internal/LoggingConfigListener.java
+++ b/src/main/java/org/apache/tamaya/events/internal/LoggingConfigListener.java
@@ -18,20 +18,24 @@
  */
 package org.apache.tamaya.events.internal;
 
-import org.apache.tamaya.events.ConfigListener;
-import org.apache.tamaya.events.delta.ConfigurationChange;
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.events.ConfigEvent;
+import org.apache.tamaya.events.ConfigEventListener;
+import org.apache.tamaya.events.ConfigurationChange;
 
 import java.util.logging.Logger;
 
 /**
  * Simple ConfigListener that simply logs any detected config changes to INFO level.
  */
-public class LoggingConfigListener implements ConfigListener{
+public class LoggingConfigListener implements ConfigEventListener {
 
     private static final Logger LOG = Logger.getLogger(LoggingConfigListener.class.getName());
 
     @Override
-    public void onConfigEvent(ConfigurationChange event) {
-        LOG.info("Configuration changed: " + event);
+    public void onConfigEvent(ConfigEvent<?> event) {
+        if(event.getResourceType()== Configuration.class) {
+            LOG.info("Configuration changed: " + event);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/java/org/apache/tamaya/events/package-info.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/tamaya/events/package-info.java b/src/main/java/org/apache/tamaya/events/package-info.java
index 33f5f25..e175ceb 100644
--- a/src/main/java/org/apache/tamaya/events/package-info.java
+++ b/src/main/java/org/apache/tamaya/events/package-info.java
@@ -18,6 +18,7 @@
  */
 /**
  * This package provides the main building blocks for handling configuration changes, such as
- * {@link org.apache.tamaya.events.ConfigEventManager}, {@link org.apache.tamaya.events.ConfigEventListener}.
+ * {@link org.apache.tamaya.events.ConfigEventManager}, {@link org.apache.tamaya.events.ConfigEventListener} and
+ * artifacts to describe the changes (delta) of a Configuration or a PropertySource.
  */
 package org.apache.tamaya.events;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/java/org/apache/tamaya/events/spi/BaseConfigEvent.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/tamaya/events/spi/BaseConfigEvent.java b/src/main/java/org/apache/tamaya/events/spi/BaseConfigEvent.java
new file mode 100644
index 0000000..15f3dfd
--- /dev/null
+++ b/src/main/java/org/apache/tamaya/events/spi/BaseConfigEvent.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.events.spi;
+
+import org.apache.tamaya.events.ConfigEvent;
+
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ * Abstract base class for implementing your own configuration events.
+ * @param <T> the vent type
+ */
+public abstract class BaseConfigEvent<T> implements ConfigEvent<T> {
+        private long timestamp = System.currentTimeMillis();
+        protected String version = UUID.randomUUID().toString();
+        protected T paylod;
+        private Class<T> type;
+
+        public BaseConfigEvent(T paylod, Class<T> type){
+            this.paylod = Objects.requireNonNull(paylod);
+            this.type = Objects.requireNonNull(type);
+        }
+
+        @Override
+        public Class<T> getResourceType() {
+            return type;
+        }
+
+        @Override
+        public T getResource() {
+            return paylod;
+        }
+
+        @Override
+        public String getVersion() {
+            return version;
+        }
+
+        @Override
+        public long getTimestamp() {
+            return timestamp;
+        }
+
+        @Override
+        public String toString() {
+            return getClass().getSimpleName() + '{' +
+                    "timestamp=" + timestamp +
+                    ", version='" + version + '\'' +
+                    ", paylod='" + paylod + '\'' +
+                    '}';
+        }
+    }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/java/org/apache/tamaya/events/spi/ConfigEventManagerSpi.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/tamaya/events/spi/ConfigEventManagerSpi.java b/src/main/java/org/apache/tamaya/events/spi/ConfigEventManagerSpi.java
index 7cb47a0..1ac1055 100644
--- a/src/main/java/org/apache/tamaya/events/spi/ConfigEventManagerSpi.java
+++ b/src/main/java/org/apache/tamaya/events/spi/ConfigEventManagerSpi.java
@@ -18,9 +18,11 @@
  */
 package org.apache.tamaya.events.spi;
 
+import org.apache.tamaya.events.ConfigEvent;
 import org.apache.tamaya.events.ConfigEventListener;
 
 import java.util.Collection;
+import java.util.Set;
 
 /**
  * SPI interface to implement the {@link org.apache.tamaya.events.ConfigEventManager} singleton.
@@ -35,29 +37,88 @@ public interface ConfigEventManagerSpi {
      *
      * @param l the listener not null.
      */
-    <T> void addListener(ConfigEventListener<T> l);
+    <T> void addListener(ConfigEventListener l);
 
+    /**
+     * Adds a listener for observing events of a given type.
+     *
+     * @param l the listener not null.
+     * @param eventType the type of concrete configuration event this listeners should be informed about. All other
+     *                  event types will never be delivered toe this listener instance.
+     */
+    <T extends ConfigEvent> void addListener(ConfigEventListener l, Class<T> eventType);
 
     /**
      * Removes a listener for observing events.
      *
      * @param l the listener not null.
      */
-    <T> void removeListener(ConfigEventListener<T> l);
+    void removeListener(ConfigEventListener l);
+
+    /**
+     * Removes a listener for observing events of a certain type.
+     *
+     * @param l the listener not null.
+     * @param eventType the type of concrete configuration event this listeners should be informed about. All other
+     *                  event types will never be delivered toe this listener instance.
+     */
+    <T extends ConfigEvent> void removeListener(ConfigEventListener l, Class<T> eventType);
 
     /**
-     * Publishes an event to all interested listeners.
+     * Access all globally registered listeners.
      *
-     * @param event     the event, not null.
-     * @param eventType the event type.
+     * @return the listeners found, never null.
+     */
+    Collection<? extends ConfigEventListener> getListeners();
+
+    /**
+     * Access all listeners listening for a certain event type, including any global listeners.
+     * @param eventType the type of concrete configuration event this listeners should be informed about. All other
+     *                  event types will never be delivered toe this listener instance.
+     * @return the listeners found, never null.
      */
-    <T> void fireEvent(T event, Class<T> eventType);
+    Collection<? extends ConfigEventListener> getListeners(Class<? extends ConfigEvent> eventType);
 
     /**
-     * Access all known listeners for a given targe type.
-     * @param type the type.
-     * @param <T> the listener type.
-     * @return the items found, never null.
+     * Publishes an event to all interested listeners, hereby executing all registered listeners sequentually and
+     * synchronously.,
+     *
+     * @param event the event, not null.
      */
-    <T> Collection<? extends ConfigEventListener<T>> getListeners(Class<T> type);
+    void fireEvent(ConfigEvent<?> event);
+
+    /**
+     * Publishes an event to all interested listeners, hereby publishing the change events asynchrously and in
+     * parallel (multithreaded).
+     *
+     * @param event the event, not null.
+     */
+    void fireEventAsynch(ConfigEvent<?> event);
+
+    /**
+     * Get the current check period to check for configuration changes.
+     *
+     * @return the check period in ms.
+     */
+    long getChangeMonitoringPeriod();
+
+    void setChangeMonitoringPeriod(long millis);
+
+    /**
+     * Check if the observer is running currently.
+     *
+     * @return true, if the change monitoring service is currently running.
+     */
+    boolean isChangeMonitorActive();
+
+    /**
+     * Start/Stop the change monitoring service, which will observe/reevaluate the current configuration regularly
+     * and triggers ConfigurationChange events is something changed. This is quite handy for publishing
+     * configuration changes to whatever systems are interested in. Hereby the origin of a configuration change
+     * can be on this machine, or also remotedly. FOr handling corresponding {@link ConfigEventListener} have
+     * to be registered, e.g. listening on {@link org.apache.tamaya.events.ConfigurationChange} events.
+     */
+    void enableChangeMonitor(boolean enable);
+
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/java/org/apache/tamaya/events/spi/ConfigObserverSpi.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/tamaya/events/spi/ConfigObserverSpi.java b/src/main/java/org/apache/tamaya/events/spi/ConfigObserverSpi.java
deleted file mode 100644
index 95eb6e7..0000000
--- a/src/main/java/org/apache/tamaya/events/spi/ConfigObserverSpi.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tamaya.events.spi;
-
-import java.util.Collection;
-import java.util.Set;
-
-/**
- * SPI interface to implement the {@link org.apache.tamaya.events.ConfigurationObserver} singleton.
- * Implementations of this interface must be registered with the current {@link org.apache.tamaya.spi.ServiceContext},
- * by default this equals to registering it with {@link java.util.ServiceLoader}. Add {@link javax.annotation.Priority}
- * annotations for overriding (higher values overriden lower values).
- */
-public interface ConfigObserverSpi {
-    /**
-     * Add key expressions for generating ConfigurationChange events.
-     *
-     * @param keys             the keys to be observed for changes.
-     */
-    <T> void addObservedKeys(Collection<String> keys);
-
-    /**
-     * Remove key expressions for generating ConfigurationChange events.
-     *
-     * @param keys the keys to be observed for changes.
-     */
-    <T> void removeObservedKeys(Collection<String> keys);
-
-    /**
-     * Get all registered key expressions for generating ConfigurationChange events.
-     *
-     * @return a set with the keys found, never null.
-     */
-    Set<String> getObservedKeys();
-
-    /**
-     * Get the current check period to check for configuration changes.
-     *
-     * @return the check period in ms.
-     */
-    long getCheckPeriod();
-
-    /**
-     * Check if the observer is running currently.
-     *
-     * @return true, if the observer is running.
-     */
-    boolean isRunning();
-
-    /**
-     * Start/Stop the observer container.
-     */
-    void enableObservation(boolean enable);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/resources/META-INF/services/org.apache.tamaya.events.ConfigEventListener
----------------------------------------------------------------------
diff --git a/src/main/resources/META-INF/services/org.apache.tamaya.events.ConfigEventListener b/src/main/resources/META-INF/services/org.apache.tamaya.events.ConfigEventListener
index f675fd6..f9942c1 100644
--- a/src/main/resources/META-INF/services/org.apache.tamaya.events.ConfigEventListener
+++ b/src/main/resources/META-INF/services/org.apache.tamaya.events.ConfigEventListener
@@ -16,4 +16,4 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-org.apache.tamaya.events.internal.DefaultConfigurationContextChangeListener
\ No newline at end of file
+org.apache.tamaya.events.internal.DefaultConfigurationContextChangeListener

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/main/resources/META-INF/services/org.apache.tamaya.events.spi.ConfigObserverSpi
----------------------------------------------------------------------
diff --git a/src/main/resources/META-INF/services/org.apache.tamaya.events.spi.ConfigObserverSpi b/src/main/resources/META-INF/services/org.apache.tamaya.events.spi.ConfigObserverSpi
index de5ee6f..99670e3 100644
--- a/src/main/resources/META-INF/services/org.apache.tamaya.events.spi.ConfigObserverSpi
+++ b/src/main/resources/META-INF/services/org.apache.tamaya.events.spi.ConfigObserverSpi
@@ -16,4 +16,4 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-org.apache.tamaya.events.internal.DefaultConfigObserverSpi
\ No newline at end of file
+org.apache.tamaya.events.internal.DefaultConfigChangeObserver
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/384b09eb/src/test/java/org/apache/tamaya/events/ChangeableGlobalPropertySource.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/tamaya/events/ChangeableGlobalPropertySource.java b/src/test/java/org/apache/tamaya/events/ChangeableGlobalPropertySource.java
new file mode 100644
index 0000000..c93b2ca
--- /dev/null
+++ b/src/test/java/org/apache/tamaya/events/ChangeableGlobalPropertySource.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.events;
+
+import org.apache.tamaya.core.propertysource.BasePropertySource;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * PropertySource implementation that accesses properties that are statically stored.
+ */
+public class ChangeableGlobalPropertySource extends BasePropertySource{
+
+    private static Map<String,String> STORED_ENTRIES = new ConcurrentHashMap<>();
+
+    @Override
+    public String getName() {
+        return getClass().getSimpleName();
+    }
+
+    @Override
+    public Map<String, String> getProperties() {
+        return null;
+    }
+
+    /**
+     * Put a value (globally) into this property source.
+     * @param key the key, not null
+     * @param value the value, not null
+     * @return the entry replaced, or null.
+     */
+    public static String put(String key, String value){
+        return STORED_ENTRIES.put(key,value);
+    }
+
+    /**
+     * Put all the properties, overriding any existing ones with the same key.
+     * @param properties the properties, not null.
+     */
+    public static void putAll(Map<String,String> properties){
+        STORED_ENTRIES.putAll(properties);
+    }
+
+}