You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by an...@apache.org on 2016/02/18 00:43:14 UTC

[6/8] incubator-tamaya git commit: Redesigned component slightly.

Redesigned component slightly.


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

Branch: refs/heads/master
Commit: 1547d4a9c0c05b50a605f2e44ae871b77a467266
Parents: 89bf981
Author: anatole <an...@apache.org>
Authored: Thu Feb 18 00:38:01 2016 +0100
Committer: anatole <an...@apache.org>
Committed: Thu Feb 18 00:38:01 2016 +0100

----------------------------------------------------------------------
 ...aya.mutableconfig.spi.ConfigChangeManagerSpi |  19 --
 ...g.spi.MutableConfigurationBackendProviderSpi |  19 ++
 .../mutableconfig/ConfigChangeManager.java      | 238 -------------------
 .../mutableconfig/ConfigChangeRequest.java      | 164 -------------
 .../mutableconfig/MutableConfiguration.java     | 164 +++++++++++++
 .../MutableConfigurationQuery.java              | 238 +++++++++++++++++++
 .../internal/DefaultConfigChangeManagerSpi.java |  52 ----
 .../DefaultConfigurationBackendSpi.java         |  52 ++++
 .../PropertiesFileConfigBackendSpi.java         | 114 +++++++++
 .../PropertiesFileConfigChangeRequest.java      | 116 ---------
 .../XmlPropertiesFileConfigBackendSpi.java      | 114 +++++++++
 .../XmlPropertiesFileConfigChangeRequest.java   | 116 ---------
 .../spi/AbstractConfigChangeRequest.java        | 167 -------------
 .../spi/AbstractMutableConfiguration.java       | 167 +++++++++++++
 ...stractMutableConfigurationBackendSpiSpi.java | 107 +++++++++
 .../spi/ConfigChangeManagerSpi.java             |  39 ---
 .../MutableConfigurationBackendProviderSpi.java |  40 ++++
 .../spi/MutableConfigurationBackendSpi.java     | 143 +++++++++++
 ...aya.mutableconfig.spi.ConfigChangeManagerSpi |  19 --
 ...g.spi.MutableConfigurationBackendProviderSpi |  19 ++
 .../mutableconfig/ConfigChangeManagerTest.java  |  78 ------
 .../MutableConfigurationQueryTest.java          |  78 ++++++
 .../PropertiesFileConfigBackendTest.java        | 161 +++++++++++++
 .../PropertiesFileConfigChangeRequestTest.java  | 161 -------------
 24 files changed, 1416 insertions(+), 1169 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/integration/etcd/src/main/resources/META-INF/services/org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi
----------------------------------------------------------------------
diff --git a/modules/integration/etcd/src/main/resources/META-INF/services/org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi b/modules/integration/etcd/src/main/resources/META-INF/services/org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi
deleted file mode 100644
index 2189807..0000000
--- a/modules/integration/etcd/src/main/resources/META-INF/services/org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi
+++ /dev/null
@@ -1,19 +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 current 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.
-#
-org.apache.tamaya.etcd.internal.MutableConfigSupport
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/integration/etcd/src/main/resources/META-INF/services/org.apache.tamaya.mutableconfig.spi.MutableConfigurationBackendProviderSpi
----------------------------------------------------------------------
diff --git a/modules/integration/etcd/src/main/resources/META-INF/services/org.apache.tamaya.mutableconfig.spi.MutableConfigurationBackendProviderSpi b/modules/integration/etcd/src/main/resources/META-INF/services/org.apache.tamaya.mutableconfig.spi.MutableConfigurationBackendProviderSpi
new file mode 100644
index 0000000..2189807
--- /dev/null
+++ b/modules/integration/etcd/src/main/resources/META-INF/services/org.apache.tamaya.mutableconfig.spi.MutableConfigurationBackendProviderSpi
@@ -0,0 +1,19 @@
+#
+# 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 current 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.
+#
+org.apache.tamaya.etcd.internal.MutableConfigSupport
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeManager.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeManager.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeManager.java
deleted file mode 100644
index 8142fcc..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeManager.java
+++ /dev/null
@@ -1,238 +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.mutableconfig;
-
-import org.apache.tamaya.ConfigException;
-import org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi;
-import org.apache.tamaya.spi.ServiceContextManager;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.UUID;
-
-
-/**
- * Accessor for creating {@link ConfigChangeRequest} instances to change and commit configuration.
- */
-public final class ConfigChangeManager {
-
-    /** Singleton constructor. */
-    private ConfigChangeManager(){}
-
-    /**
-     * Creates a new change request for the given configurationSource
-     *
-     * @param configurationTargets the configuration targets (String to create URIs) to use to write the changes/config. By passing multiple
-     *                             URIs you can write back changes into multiple configuration backends, e.g.
-     *                             one for redistributing changes using multicast mechanism, a local property file
-     *                             for failover as well as the shared etcd server.
-     * @return a new ChangeRequest
-     * @throws org.apache.tamaya.ConfigException if the given configurationSource cannot be edited.
-     */
-    public static ConfigChangeRequest createChangeRequest(String... configurationTargets){
-        try {
-            URI[] uris = new URI[configurationTargets.length];
-            for (int i = 0; i < configurationTargets.length; i++) {
-                uris[i] = new URI(configurationTargets[i]);
-            }
-            return createChangeRequest(uris);
-        } catch(URISyntaxException e){
-            throw new ConfigException("Invalid URIs enocuntered in " + Arrays.toString(configurationTargets));
-        }
-    }
-
-    /**
-     * Creates a new change request for the given configurationSource
-     *
-     * @param configurationTargets the configuration targets to use to write the changes/config. By passing multiple
-     *                             URIs you can write back changes into multiple configuration backends, e.g.
-     *                             one for redistributing changes using multicast mechanism, a local property file
-     *                             for failover as well as the shared etcd server.
-     * @return a new ChangeRequest
-     * @throws org.apache.tamaya.ConfigException if the given configurationSource cannot be edited.
-     */
-    public static ConfigChangeRequest createChangeRequest(URI... configurationTargets){
-        if(Objects.requireNonNull(configurationTargets).length==0){
-            throw new IllegalArgumentException("At least one target URI is required.");
-        }
-        List<ConfigChangeRequest> targets = new ArrayList<>();
-        for(ConfigChangeManagerSpi spi:ServiceContextManager.getServiceContext()
-                .getServices(ConfigChangeManagerSpi.class)){
-            for(URI target:configurationTargets) {
-                ConfigChangeRequest req = spi.createChangeRequest(target);
-                if (req != null) {
-                    targets.add(req);
-                }
-            }
-        }
-        if(targets.isEmpty()) {
-            throw new ConfigException("Not an editable configuration target for: " +
-                    Arrays.toString(configurationTargets));
-        }
-        if(targets.size()==1){
-            return targets.get(0);
-        }
-        return new CompoundConfigChangeRequest(targets);
-    }
-
-
-    /**
-     * Compound request that contains internally multiple change requests. Changes are committed to all members.
-     */
-    private static final class CompoundConfigChangeRequest implements ConfigChangeRequest{
-
-        private final List<ConfigChangeRequest> targets;
-        private final List<URI> backendURIs = new ArrayList<>();
-        private String requestId = UUID.randomUUID().toString();
-
-        CompoundConfigChangeRequest(List<ConfigChangeRequest> targets){
-            this.targets = targets;
-            for(ConfigChangeRequest req:targets){
-                req.setRequestId(requestId);
-                backendURIs.addAll(req.getBackendURIs());
-            }
-        }
-
-        @Override
-        public String getRequestID() {
-            return requestId;
-        }
-
-        @Override
-        public List<URI> getBackendURIs() {
-            return Collections.unmodifiableList(backendURIs);
-        }
-
-        @Override
-        public boolean isWritable(String keyExpression) {
-            for(ConfigChangeRequest req:targets){
-                if(req.isWritable(keyExpression)){
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public boolean isRemovable(String keyExpression) {
-            for(ConfigChangeRequest req:targets){
-                if(req.isRemovable(keyExpression)){
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public boolean exists(String keyExpression) {
-            for(ConfigChangeRequest req:targets){
-                if(req.exists(keyExpression)){
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public ConfigChangeRequest put(String key, String value) {
-            for(ConfigChangeRequest req:targets){
-                if(req.isWritable(key)){
-                    req.put(key, value);
-                }
-            }
-            return this;
-        }
-
-        @Override
-        public ConfigChangeRequest putAll(Map<String, String> properties) {
-            for(ConfigChangeRequest req:targets){
-                for(Map.Entry<String,String> en:properties.entrySet()) {
-                    if (req.isWritable(en.getKey())) {
-                        req.put(en.getKey(), en.getValue());
-                    }
-                }
-            }
-            return this;
-        }
-
-        @Override
-        public ConfigChangeRequest remove(String... keys) {
-            for(ConfigChangeRequest req:targets){
-                for(String key:keys){
-                    if (req.isRemovable(key)) {
-                        req.remove(key);
-                    }
-                }
-            }
-            return this;
-        }
-
-        @Override
-        public ConfigChangeRequest remove(Collection<String> keys) {
-            for(ConfigChangeRequest req:targets){
-                for(String key:keys){
-                    if (req.isRemovable(key)) {
-                        req.remove(key);
-                    }
-                }
-            }
-            return this;
-        }
-
-        @Override
-        public void commit() {
-            for(ConfigChangeRequest req:targets){
-                req.commit();
-            }
-        }
-
-        @Override
-        public void cancel() {
-            for(ConfigChangeRequest req:targets){
-                req.cancel();
-            }
-        }
-
-        @Override
-        public boolean isClosed() {
-            for(ConfigChangeRequest req:targets){
-                if(req.isClosed()){
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public void setRequestId(String requestId) {
-            if(isClosed()){
-                throw new IllegalStateException("Cannot set requestId, already closed.");
-            }
-            this.requestId = Objects.requireNonNull(requestId);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeRequest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeRequest.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeRequest.java
deleted file mode 100644
index a192f50..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeRequest.java
+++ /dev/null
@@ -1,164 +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.mutableconfig;
-
-import java.net.URI;
-import java.util.Collection;
-import java.util.Map;
-
-
-/**
- * This interface extends the Configuration interface hereby adding methods to change configuration entries.
- * Hereby not all configuration entries are necessarily mutable, since some entries may be read from non
- * mutable areas of configuration. Of course, it is always possible to add a mutable shadow layer on top of all
- * configuration to enable whatever changes applied. The exact management and storage persistence algorithm should be
- * transparent.<br>
- * As a consequence clients should first check, using the corresponding methods, if entries are to edited or removed
- * actually are eligible for change/creation or removal.
- */
-public interface ConfigChangeRequest {
-
-    /**
-     * Get the unique id of this change request (UUID).
-     *
-     * @return the unique id of this change request (UUID).
-     */
-    String getRequestID();
-
-    /**
-     * Identifies the configuration backends that participate in this request instance and which are
-     * also responsible for writing back the changes applied.
-     *
-     * @return the backend URI, never null.
-     */
-    Collection<URI> getBackendURIs();
-
-    /**
-     * Checks if a configuration key is writable (or it can be added).
-     *
-     * @param keyExpression the key to be checked for write access (including creation), not null. Here this could also
-     *                      be a regular expression, such "as a.b.c.*".
-     * @return the boolean
-     */
-    boolean isWritable(String keyExpression);
-
-    /**
-     * Checks if a configuration key is removable. This also implies that it is writable, but there might be writable
-     * keys that cannot be removed.
-     *
-     * @param keyExpression the keyExpression the key to be cheched for write access (including creation), not null.
-     *                      Here this could also
-     *                      be a regulat expression, such "as a.b.c.*".
-     * @return the boolean
-     */
-    boolean isRemovable(String keyExpression);
-
-    /**
-     * Checks if any keys of the given type already exist in the backend. <b>NOTE:</b> there may be backends that
-     * are not able to support lookups with regular expressions. In most such cases you should pass the keys to
-     * lookup explicitly.
-     *
-     * @param keyExpression the key to be checked for write access (including creation), not null. Here this could
-     *                      also be a regular expression, such "as a.b.c.*".
-     * @return true, if there is any key found matching the expression.
-     */
-    boolean exists(String keyExpression);
-
-    /**
-     * Sets a property.
-     *
-     * @param key   the property's key, not null.
-     * @param value the property's value, not null.
-     * @return the former property value, or null.
-     * @throws org.apache.tamaya.ConfigException if the key/value cannot be added, or the request is read-only.
-     */
-    ConfigChangeRequest put(String key, String value);
-
-    /**
-     * Puts all given configuration entries. This method should check that all given properties are
-     * basically removable, as defined by #isWritable. If any of the passed keys is not writable during this initial
-     * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
-     * occur afterwards, when the properties are effectively written back to the backends, the errors should be
-     * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
-     * remove all entries as far as possible and abort the writing operation.
-     *
-     * @param properties the properties tobe written, not null.
-     * @return the config change request
-     * @throws org.apache.tamaya.ConfigException if any of the given properties could not be written, or the request is read-only.
-     */
-    ConfigChangeRequest putAll(Map<String, String> properties);
-
-    /**
-     * Removes all given configuration entries. This method should check that all given properties are
-     * basically removable, as defined by #isRemovable. If any of the passed keys is not removable during this initial
-     * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
-     * occur afterwards, when the properties are effectively written back to the backends, the errors should be
-     * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
-     * remove all entries as far as possible and abort the writing operation.
-     *
-     * @param keys the property's keys to be removed, not null.
-     * @return the config change request
-     * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removed, or the request is read-only.
-     */
-    ConfigChangeRequest remove(Collection<String> keys);
-
-    /**
-     * Removes all given configuration entries. This method should check that all given properties are
-     * basically removable, as defined by #isRemovable. If any of the passed keys is not removable during this initial
-     * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
-     * occur afterwards, when the properties are effectively written back to the backends, the errors should be
-     * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
-     * remove all entries as far as possible and abort the writing operation.
-     *
-     * @param keys the property's keys to be removed, not null.
-     * @return the config change request
-     * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removed, or the request is read-only.
-     */
-    ConfigChangeRequest remove(String... keys);
-
-    /**
-     * Commits the request. After a commit the change is not editable anymore. All changes applied will be written to
-     * the corresponding configuration backend.
-     * " @throws ConfigException if the request already has been committed or cancelled, or the commit fails.
-     */
-    void commit();
-
-    /**
-     * Cancel the given request, leaving everything unchanged. Cancelled requests are read-only and can not be used
-     * for preparing/submitting any configuration changes.
-     *
-     * @throws org.apache.tamaya.ConfigException if the request already has been committed or cancelled.
-     */
-    void cancel();
-
-    /**
-     * Operation to check, if the current request is closed (either commited or cancelled). Closed requests are
-     * read-only and can not be used for preparing/submitting any configuration changes.
-     *
-     * @return true, if this instance is closed.
-     */
-    boolean isClosed();
-
-    /**
-     * Method to set the request id to be used.
-     * @param requestId the id to  be used, not null
-     * @throws IllegalStateException if the request is already closed.
-     */
-    void setRequestId(String requestId);
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfiguration.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfiguration.java
new file mode 100644
index 0000000..fed3151
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfiguration.java
@@ -0,0 +1,164 @@
+/*
+ * 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.mutableconfig;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.Map;
+
+
+/**
+ * This interface extends the Configuration interface hereby adding methods to change configuration entries.
+ * Hereby not all configuration entries are necessarily mutable, since some entries may be read from non
+ * mutable areas of configuration. Of course, it is always possible to add a mutable shadow layer on top of all
+ * configuration to enable whatever changes applied. The exact management and storage persistence algorithm should be
+ * transparent.<br>
+ * As a consequence clients should first check, using the corresponding methods, if entries are to edited or removed
+ * actually are eligible for change/creation or removal.
+ */
+public interface MutableConfiguration {
+
+    /**
+     * Get the unique id of this change request (UUID).
+     *
+     * @return the unique id of this change request (UUID).
+     */
+    String getRequestID();
+
+    /**
+     * Identifies the configuration backends that participate in this request instance and which are
+     * also responsible for writing back the changes applied.
+     *
+     * @return the backend URI, never null.
+     */
+    Collection<URI> getBackendURIs();
+
+    /**
+     * Checks if a configuration key is writable (or it can be added).
+     *
+     * @param keyExpression the key to be checked for write access (including creation), not null. Here this could also
+     *                      be a regular expression, such "as a.b.c.*".
+     * @return the boolean
+     */
+    boolean isWritable(String keyExpression);
+
+    /**
+     * Checks if a configuration key is removable. This also implies that it is writable, but there might be writable
+     * keys that cannot be removed.
+     *
+     * @param keyExpression the keyExpression the key to be cheched for write access (including creation), not null.
+     *                      Here this could also
+     *                      be a regulat expression, such "as a.b.c.*".
+     * @return the boolean
+     */
+    boolean isRemovable(String keyExpression);
+
+    /**
+     * Checks if any keys of the given type already exist in the backend. <b>NOTE:</b> there may be backends that
+     * are not able to support lookups with regular expressions. In most such cases you should pass the keys to
+     * lookup explicitly.
+     *
+     * @param keyExpression the key to be checked for write access (including creation), not null. Here this could
+     *                      also be a regular expression, such "as a.b.c.*".
+     * @return true, if there is any key found matching the expression.
+     */
+    boolean exists(String keyExpression);
+
+    /**
+     * Sets a property.
+     *
+     * @param key   the property's key, not null.
+     * @param value the property's value, not null.
+     * @return the former property value, or null.
+     * @throws org.apache.tamaya.ConfigException if the key/value cannot be added, or the request is read-only.
+     */
+    MutableConfiguration put(String key, String value);
+
+    /**
+     * Puts all given configuration entries. This method should check that all given properties are
+     * basically removable, as defined by #isWritable. If any of the passed keys is not writable during this initial
+     * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
+     * occur afterwards, when the properties are effectively written back to the backends, the errors should be
+     * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
+     * remove all entries as far as possible and abort the writing operation.
+     *
+     * @param properties the properties tobe written, not null.
+     * @return the config change request
+     * @throws org.apache.tamaya.ConfigException if any of the given properties could not be written, or the request is read-only.
+     */
+    MutableConfiguration putAll(Map<String, String> properties);
+
+    /**
+     * Removes all given configuration entries. This method should check that all given properties are
+     * basically removable, as defined by #isRemovable. If any of the passed keys is not removable during this initial
+     * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
+     * occur afterwards, when the properties are effectively written back to the backends, the errors should be
+     * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
+     * remove all entries as far as possible and abort the writing operation.
+     *
+     * @param keys the property's keys to be removed, not null.
+     * @return the config change request
+     * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removed, or the request is read-only.
+     */
+    MutableConfiguration remove(Collection<String> keys);
+
+    /**
+     * Removes all given configuration entries. This method should check that all given properties are
+     * basically removable, as defined by #isRemovable. If any of the passed keys is not removable during this initial
+     * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
+     * occur afterwards, when the properties are effectively written back to the backends, the errors should be
+     * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
+     * remove all entries as far as possible and abort the writing operation.
+     *
+     * @param keys the property's keys to be removed, not null.
+     * @return the config change request
+     * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removed, or the request is read-only.
+     */
+    MutableConfiguration remove(String... keys);
+
+    /**
+     * Commits the request. After a commit the change is not editable anymore. All changes applied will be written to
+     * the corresponding configuration backend.
+     * " @throws ConfigException if the request already has been committed or cancelled, or the commit fails.
+     */
+    void commit();
+
+    /**
+     * Cancel the given request, leaving everything unchanged. Cancelled requests are read-only and can not be used
+     * for preparing/submitting any configuration changes.
+     *
+     * @throws org.apache.tamaya.ConfigException if the request already has been committed or cancelled.
+     */
+    void cancel();
+
+    /**
+     * Operation to check, if the current request is closed (either commited or cancelled). Closed requests are
+     * read-only and can not be used for preparing/submitting any configuration changes.
+     *
+     * @return true, if this instance is closed.
+     */
+    boolean isClosed();
+
+    /**
+     * Method to set the request id to be used.
+     * @param requestId the id to  be used, not null
+     * @throws IllegalStateException if the request is already closed.
+     */
+    void setRequestId(String requestId);
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfigurationQuery.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfigurationQuery.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfigurationQuery.java
new file mode 100644
index 0000000..7aaf2bf
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfigurationQuery.java
@@ -0,0 +1,238 @@
+/*
+ * 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.mutableconfig;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi;
+import org.apache.tamaya.spi.ServiceContextManager;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.UUID;
+
+
+/**
+ * Accessor for creating {@link MutableConfiguration} instances to change and commit configuration.
+ */
+public final class MutableConfigurationQuery {
+
+    /** Singleton constructor. */
+    private MutableConfigurationQuery(){}
+
+    /**
+     * Creates a new change request for the given configurationSource
+     *
+     * @param configurationTargets the configuration targets (String to create URIs) to use to write the changes/config. By passing multiple
+     *                             URIs you can write back changes into multiple configuration backends, e.g.
+     *                             one for redistributing changes using multicast mechanism, a local property file
+     *                             for failover as well as the shared etcd server.
+     * @return a new ChangeRequest
+     * @throws org.apache.tamaya.ConfigException if the given configurationSource cannot be edited.
+     */
+    public static MutableConfiguration createChangeRequest(String... configurationTargets){
+        try {
+            URI[] uris = new URI[configurationTargets.length];
+            for (int i = 0; i < configurationTargets.length; i++) {
+                uris[i] = new URI(configurationTargets[i]);
+            }
+            return createChangeRequest(uris);
+        } catch(URISyntaxException e){
+            throw new ConfigException("Invalid URIs enocuntered in " + Arrays.toString(configurationTargets));
+        }
+    }
+
+    /**
+     * Creates a new change request for the given configurationSource
+     *
+     * @param configurationTargets the configuration targets to use to write the changes/config. By passing multiple
+     *                             URIs you can write back changes into multiple configuration backends, e.g.
+     *                             one for redistributing changes using multicast mechanism, a local property file
+     *                             for failover as well as the shared etcd server.
+     * @return a new ChangeRequest
+     * @throws org.apache.tamaya.ConfigException if the given configurationSource cannot be edited.
+     */
+    public static MutableConfiguration createChangeRequest(URI... configurationTargets){
+        if(Objects.requireNonNull(configurationTargets).length==0){
+            throw new IllegalArgumentException("At least one target URI is required.");
+        }
+        List<MutableConfiguration> targets = new ArrayList<>();
+        for(ConfigChangeManagerSpi spi:ServiceContextManager.getServiceContext()
+                .getServices(ConfigChangeManagerSpi.class)){
+            for(URI target:configurationTargets) {
+                MutableConfiguration req = spi.createChangeRequest(target);
+                if (req != null) {
+                    targets.add(req);
+                }
+            }
+        }
+        if(targets.isEmpty()) {
+            throw new ConfigException("Not an editable configuration target for: " +
+                    Arrays.toString(configurationTargets));
+        }
+        if(targets.size()==1){
+            return targets.get(0);
+        }
+        return new CompoundConfigChangeRequest(targets);
+    }
+
+
+    /**
+     * Compound request that contains internally multiple change requests. Changes are committed to all members.
+     */
+    private static final class CompoundConfigChangeRequest implements MutableConfiguration {
+
+        private final List<MutableConfiguration> targets;
+        private final List<URI> backendURIs = new ArrayList<>();
+        private String requestId = UUID.randomUUID().toString();
+
+        CompoundConfigChangeRequest(List<MutableConfiguration> targets){
+            this.targets = targets;
+            for(MutableConfiguration req:targets){
+                req.setRequestId(requestId);
+                backendURIs.addAll(req.getBackendURIs());
+            }
+        }
+
+        @Override
+        public String getRequestID() {
+            return requestId;
+        }
+
+        @Override
+        public List<URI> getBackendURIs() {
+            return Collections.unmodifiableList(backendURIs);
+        }
+
+        @Override
+        public boolean isWritable(String keyExpression) {
+            for(MutableConfiguration req:targets){
+                if(req.isWritable(keyExpression)){
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public boolean isRemovable(String keyExpression) {
+            for(MutableConfiguration req:targets){
+                if(req.isRemovable(keyExpression)){
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public boolean exists(String keyExpression) {
+            for(MutableConfiguration req:targets){
+                if(req.exists(keyExpression)){
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public MutableConfiguration put(String key, String value) {
+            for(MutableConfiguration req:targets){
+                if(req.isWritable(key)){
+                    req.put(key, value);
+                }
+            }
+            return this;
+        }
+
+        @Override
+        public MutableConfiguration putAll(Map<String, String> properties) {
+            for(MutableConfiguration req:targets){
+                for(Map.Entry<String,String> en:properties.entrySet()) {
+                    if (req.isWritable(en.getKey())) {
+                        req.put(en.getKey(), en.getValue());
+                    }
+                }
+            }
+            return this;
+        }
+
+        @Override
+        public MutableConfiguration remove(String... keys) {
+            for(MutableConfiguration req:targets){
+                for(String key:keys){
+                    if (req.isRemovable(key)) {
+                        req.remove(key);
+                    }
+                }
+            }
+            return this;
+        }
+
+        @Override
+        public MutableConfiguration remove(Collection<String> keys) {
+            for(MutableConfiguration req:targets){
+                for(String key:keys){
+                    if (req.isRemovable(key)) {
+                        req.remove(key);
+                    }
+                }
+            }
+            return this;
+        }
+
+        @Override
+        public void commit() {
+            for(MutableConfiguration req:targets){
+                req.commit();
+            }
+        }
+
+        @Override
+        public void rollback() {
+            for(MutableConfiguration req:targets){
+                req.rollback();
+            }
+        }
+
+        @Override
+        public boolean isClosed() {
+            for(MutableConfiguration req:targets){
+                if(req.isClosed()){
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public void setRequestId(String requestId) {
+            if(isClosed()){
+                throw new IllegalStateException("Cannot set requestId, already closed.");
+            }
+            this.requestId = Objects.requireNonNull(requestId);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigChangeManagerSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigChangeManagerSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigChangeManagerSpi.java
deleted file mode 100644
index d1d8371..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigChangeManagerSpi.java
+++ /dev/null
@@ -1,52 +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.mutableconfig.internal;
-
-import org.apache.tamaya.mutableconfig.ConfigChangeRequest;
-import org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi;
-
-import java.io.File;
-import java.net.URI;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Mutable Config Request factory that tries to convert given URIs to file references, if successful, it returns
- * ConfigChangeRequests fir .properties and .xml files.
- */
-public class DefaultConfigChangeManagerSpi implements ConfigChangeManagerSpi{
-
-    private static final Logger LOG = Logger.getLogger(XmlPropertiesFileConfigChangeRequest.class.getName());
-
-    @Override
-    public ConfigChangeRequest createChangeRequest(URI uri) {
-        try{
-            File f = new File(uri);
-            if(f.getName().endsWith(".properties")){
-                return new PropertiesFileConfigChangeRequest(f);
-            }else if(f.getName().endsWith(".xml")){
-                return new XmlPropertiesFileConfigChangeRequest(f);
-            }
-        } catch(Exception e){
-            LOG.log(Level.FINEST, "URI not convertible to file, ignoring " + uri, e);
-        }
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigurationBackendSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigurationBackendSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigurationBackendSpi.java
new file mode 100644
index 0000000..e5def2e
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigurationBackendSpi.java
@@ -0,0 +1,52 @@
+/*
+ * 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.mutableconfig.internal;
+
+import org.apache.tamaya.mutableconfig.MutableConfiguration;
+import org.apache.tamaya.mutableconfig.spi.ConfigurationBackendSpi;
+
+import java.io.File;
+import java.net.URI;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Mutable Config Request factory that tries to convert given URIs to file references, if successful, it returns
+ * ConfigChangeRequests fir .properties and .xml files.
+ */
+public class DefaultConfigurationBackendSpi implements ConfigurationBackendSpi {
+
+    private static final Logger LOG = Logger.getLogger(XmlPropertiesFileConfigChangeRequest.class.getName());
+
+    @Override
+    public MutableConfiguration getBackend(URI uri) {
+        try{
+            File f = new File(uri);
+            if(f.getName().endsWith(".properties")){
+                return new PropertiesFileConfigChangeRequest(f);
+            }else if(f.getName().endsWith(".xml")){
+                return new XmlPropertiesFileConfigChangeRequest(f);
+            }
+        } catch(Exception e){
+            LOG.log(Level.FINEST, "URI not convertible to file, ignoring " + uri, e);
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendSpi.java
new file mode 100644
index 0000000..15a68cb
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendSpi.java
@@ -0,0 +1,114 @@
+/*
+ * 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.mutableconfig.internal;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.mutableconfig.spi.AbstractMutableConfigurationBackendSpiSpi;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Date;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Change Request implementation based on .properties file.
+ */
+class PropertiesFileConfigBackendSpi extends AbstractMutableConfigurationBackendSpiSpi {
+
+    private static final Logger LOG = Logger.getLogger(PropertiesFileConfigBackendSpi.class.getName());
+
+    private final File file;
+
+    private final Properties properties = new Properties();
+
+    /**
+     * Instantiates a new Properties file config change request.
+     *
+     * @param file the file
+     */
+    PropertiesFileConfigBackendSpi(File file){
+        super(file.toURI());
+        this.file = file;
+        if(file.exists()) {
+            try (InputStream is = getBackendURI().toURL().openStream()) {
+                properties.load(is);
+            } catch (Exception e) {
+                LOG.log(Level.SEVERE, "Failed to load properties from " + file, e);
+            }
+        }
+    }
+
+    @Override
+    public boolean isExisting(String keyExpression) {
+        if(properties.containsKey(keyExpression)){
+            return true;
+        }
+        for(Object key:properties.keySet()){
+            if(key.toString().matches(keyExpression)){
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+    @Override
+    protected void commitInternal() {
+        if(!file.exists()){
+            try {
+                if(!file.createNewFile()){
+                    throw new ConfigException("Failed to create config file " + file);
+                }
+            } catch (IOException e) {
+                throw new ConfigException("Failed to create config file " + file, e);
+            }
+        }
+        for(Map.Entry<String,String> en:super.addedProperties.entrySet()){
+            int index = en.getKey().indexOf('?');
+            if(index>0){
+                this.properties.put(en.getKey().substring(0, index), en.getValue());
+            }else{
+                this.properties.put(en.getKey(), en.getValue());
+            }
+        }
+        for(String rmKey:super.removedProperties){
+            this.properties.remove(rmKey);
+        }
+        try(BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))){
+            properties.store(bos, "Properties written from Tamaya on : " + new Date());
+            bos.flush();
+        }
+        catch(Exception e){
+            throw new ConfigException("Failed to write config to " + file, e);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "PropertiesFileConfigBackend{" +
+                "file=" + file +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigChangeRequest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigChangeRequest.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigChangeRequest.java
deleted file mode 100644
index 94d3f2e..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigChangeRequest.java
+++ /dev/null
@@ -1,116 +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.mutableconfig.internal;
-
-import org.apache.tamaya.ConfigException;
-import org.apache.tamaya.mutableconfig.spi.AbstractConfigChangeRequest;
-
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.Map;
-import java.util.Properties;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Change Request implementation based on .properties file.
- */
-class PropertiesFileConfigChangeRequest extends AbstractConfigChangeRequest{
-
-    private static final Logger LOG = Logger.getLogger(PropertiesFileConfigChangeRequest.class.getName());
-
-    private final File file;
-
-    private final Properties properties = new Properties();
-
-    /**
-     * Instantiates a new Properties file config change request.
-     *
-     * @param file the file
-     */
-    PropertiesFileConfigChangeRequest(File file){
-        super(file.toURI());
-        this.file = file;
-        if(file.exists()) {
-            for(URI uri:getBackendURIs()) {
-                try (InputStream is = uri.toURL().openStream()) {
-                    properties.load(is);
-                } catch (Exception e) {
-                    LOG.log(Level.SEVERE, "Failed to load properties from " + file, e);
-                }
-            }
-        }
-    }
-
-    @Override
-    public boolean exists(String keyExpression) {
-        if(properties.containsKey(keyExpression)){
-            return true;
-        }
-        for(Object key:properties.keySet()){
-            if(key.toString().matches(keyExpression)){
-                return true;
-            }
-        }
-        return false;
-    }
-
-
-    @Override
-    protected void commitInternal() {
-        if(!file.exists()){
-            try {
-                if(!file.createNewFile()){
-                    throw new ConfigException("Failed to create config file " + file);
-                }
-            } catch (IOException e) {
-                throw new ConfigException("Failed to create config file " + file, e);
-            }
-        }
-        for(Map.Entry<String,String> en:super.properties.entrySet()){
-            int index = en.getKey().indexOf('?');
-            if(index>0){
-                this.properties.put(en.getKey().substring(0, index), en.getValue());
-            }else{
-                this.properties.put(en.getKey(), en.getValue());
-            }
-        }
-        for(String rmKey:super.removed){
-            this.properties.remove(rmKey);
-        }
-        try(BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))){
-            properties.store(bos, "Properties written from Tamaya, request: " + getRequestID());
-            bos.flush();
-        }
-        catch(Exception e){
-            throw new ConfigException("Failed to write config to " + file, e);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "PropertiesFileConfigChangeRequest{" +
-                "file=" + file +
-                '}';
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigBackendSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigBackendSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigBackendSpi.java
new file mode 100644
index 0000000..cdca80d
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigBackendSpi.java
@@ -0,0 +1,114 @@
+/*
+ * 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.mutableconfig.internal;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.mutableconfig.spi.AbstractMutableConfigurationBackendSpiSpi;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Date;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Change Request implementation based on .xml properties file.
+ */
+class XmlPropertiesFileConfigBackendSpi extends AbstractMutableConfigurationBackendSpiSpi {
+
+    private static final Logger LOG = Logger.getLogger(XmlPropertiesFileConfigBackendSpi.class.getName());
+
+    private final File file;
+
+    private final Properties properties = new Properties();
+
+    /**
+     * Instantiates a new Xml properties file config change request.
+     *
+     * @param file the file
+     */
+    XmlPropertiesFileConfigBackendSpi(File file){
+        super(file.toURI());
+        this.file = file;
+        if(file.exists()) {
+            try (InputStream is = getBackendURI().toURL().openStream()) {
+                properties.loadFromXML(is);
+            } catch (Exception e) {
+                LOG.log(Level.SEVERE, "Failed to load properties from " + file, e);
+            }
+        }
+    }
+
+    @Override
+    public boolean isExisting(String keyExpression) {
+        if(properties.containsKey(keyExpression)){
+            return true;
+        }
+        for(Object key:properties.keySet()){
+            if(key.toString().matches(keyExpression)){
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+    @Override
+    protected void commitInternal() {
+        if(!file.exists()){
+            try {
+                if(!file.createNewFile()){
+                    throw new ConfigException("Failed to create config file " + file);
+                }
+            } catch (IOException e) {
+                throw new ConfigException("Failed to create config file " + file, e);
+            }
+        }
+        for(Map.Entry<String,String> en:super.addedProperties.entrySet()){
+            int index = en.getKey().indexOf('?');
+            if(index>0){
+                this.properties.put(en.getKey().substring(0, index), en.getValue());
+            }else{
+                this.properties.put(en.getKey(), en.getValue());
+            }
+        }
+        for(String rmKey:super.removedProperties){
+            this.properties.remove(rmKey);
+        }
+        try(BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))){
+            properties.storeToXML(bos, "Properties written from Tamaya on " + new Date());
+            bos.flush();
+        }
+        catch(Exception e){
+            throw new ConfigException("Failed to write config to " + file, e);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "XmlPropertiesFileConfigBackend{" +
+                "file=" + file +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigChangeRequest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigChangeRequest.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigChangeRequest.java
deleted file mode 100644
index 9211641..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigChangeRequest.java
+++ /dev/null
@@ -1,116 +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.mutableconfig.internal;
-
-import org.apache.tamaya.ConfigException;
-import org.apache.tamaya.mutableconfig.spi.AbstractConfigChangeRequest;
-
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.Map;
-import java.util.Properties;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Change Request implementation based on .xml properties file.
- */
-class XmlPropertiesFileConfigChangeRequest extends AbstractConfigChangeRequest{
-
-    private static final Logger LOG = Logger.getLogger(XmlPropertiesFileConfigChangeRequest.class.getName());
-
-    private final File file;
-
-    private final Properties properties = new Properties();
-
-    /**
-     * Instantiates a new Xml properties file config change request.
-     *
-     * @param file the file
-     */
-    XmlPropertiesFileConfigChangeRequest(File file){
-        super(file.toURI());
-        this.file = file;
-        if(file.exists()) {
-            for(URI uri:getBackendURIs()) {
-                try (InputStream is = uri.toURL().openStream()) {
-                    properties.loadFromXML(is);
-                } catch (Exception e) {
-                    LOG.log(Level.SEVERE, "Failed to load properties from " + file, e);
-                }
-            }
-        }
-    }
-
-    @Override
-    public boolean exists(String keyExpression) {
-        if(properties.containsKey(keyExpression)){
-            return true;
-        }
-        for(Object key:properties.keySet()){
-            if(key.toString().matches(keyExpression)){
-                return true;
-            }
-        }
-        return false;
-    }
-
-
-    @Override
-    protected void commitInternal() {
-        if(!file.exists()){
-            try {
-                if(!file.createNewFile()){
-                    throw new ConfigException("Failed to create config file " + file);
-                }
-            } catch (IOException e) {
-                throw new ConfigException("Failed to create config file " + file, e);
-            }
-        }
-        for(Map.Entry<String,String> en:super.properties.entrySet()){
-            int index = en.getKey().indexOf('?');
-            if(index>0){
-                this.properties.put(en.getKey().substring(0, index), en.getValue());
-            }else{
-                this.properties.put(en.getKey(), en.getValue());
-            }
-        }
-        for(String rmKey:super.removed){
-            this.properties.remove(rmKey);
-        }
-        try(BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))){
-            properties.storeToXML(bos, "Properties written from Tamaya, request: " + getRequestID());
-            bos.flush();
-        }
-        catch(Exception e){
-            throw new ConfigException("Failed to write config to " + file, e);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "XmlPropertiesFileConfigChangeRequest{" +
-                "file=" + file +
-                '}';
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractConfigChangeRequest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractConfigChangeRequest.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractConfigChangeRequest.java
deleted file mode 100644
index 5e319db..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractConfigChangeRequest.java
+++ /dev/null
@@ -1,167 +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.mutableconfig.spi;
-
-import org.apache.tamaya.ConfigException;
-import org.apache.tamaya.mutableconfig.ConfigChangeRequest;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.UUID;
-
-/**
- * Base class for implementing a ConfigChangeRequest.
- */
-public abstract class AbstractConfigChangeRequest implements ConfigChangeRequest {
-
-    private final List<URI> uris = new ArrayList<>();
-    private String requestID = UUID.randomUUID().toString();
-    /**
-     * The Properties.
-     */
-    protected final Map<String,String> properties = new HashMap<>();
-    /**
-     * The Removed.
-     */
-    protected final Set<String> removed = new HashSet<>();
-    private boolean closed = false;
-
-    protected Set<String> getRemoved() {
-        return removed;
-    }
-
-    protected Map<String,String> getProperties() {
-        return properties;
-    }
-
-    /**
-     * Instantiates a new Abstract config change request.
-     *
-     * @param uris the uris
-     */
-    protected AbstractConfigChangeRequest(URI... uris){
-        for(URI uri:uris){
-            this.uris.add(Objects.requireNonNull(uri));
-        }
-        if(this.uris.isEmpty()){
-            throw new IllegalArgumentException("At least one URI should be provided.");
-        }
-    }
-
-    /**
-     * Get the unique id of this change request (UUID).
-     * @return the unique id of this change request (UUID).
-     */
-    @Override
-    public String getRequestID(){
-        return requestID;
-    }
-
-    @Override
-    public final Collection<URI> getBackendURIs() {
-        return Collections.unmodifiableCollection(uris);
-    }
-
-    @Override
-    public boolean isWritable(String keyExpression) {
-        return true;
-    }
-
-    @Override
-    public boolean isRemovable(String keyExpression) {
-        return true;
-    }
-
-    @Override
-    public abstract boolean exists(String keyExpression);
-
-    @Override
-    public void setRequestId(String requestId) {
-        checkClosed();
-        this.requestID = Objects.requireNonNull(requestId);
-    }
-
-    @Override
-    public ConfigChangeRequest put(String key, String value) {
-        checkClosed();
-        this.properties.put(key, value);
-        return this;
-    }
-
-    @Override
-    public ConfigChangeRequest putAll(Map<String, String> properties) {
-        checkClosed();
-        this.properties.putAll(properties);
-        return this;
-    }
-
-    @Override
-    public ConfigChangeRequest remove(String... keys) {
-        checkClosed();
-        Collections.addAll(this.removed, keys);
-        return this;
-    }
-
-    @Override
-    public ConfigChangeRequest remove(Collection<String> keys) {
-        checkClosed();
-        this.removed.addAll(keys);
-        return this;
-    }
-
-    @Override
-    public final void commit() {
-        checkClosed();
-        commitInternal();
-        closed = true;
-    }
-
-    /**
-     * Commit internal.
-     */
-    protected abstract void commitInternal();
-
-    @Override
-    public final void cancel() {
-        checkClosed();
-        closed = true;
-    }
-
-    @Override
-    public final boolean isClosed() {
-        return closed;
-    }
-
-    /**
-     * Check closed.
-     */
-    protected void checkClosed(){
-        if(closed){
-            throw new ConfigException("Change request already closed.");
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfiguration.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfiguration.java
new file mode 100644
index 0000000..2dd9a20
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfiguration.java
@@ -0,0 +1,167 @@
+/*
+ * 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.mutableconfig.spi;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.mutableconfig.MutableConfiguration;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Base class for implementing a ConfigChangeRequest.
+ */
+public abstract class AbstractMutableConfiguration implements MutableConfiguration {
+
+    private final List<URI> uris = new ArrayList<>();
+    private String requestID = UUID.randomUUID().toString();
+    /**
+     * The Properties.
+     */
+    protected final Map<String,String> properties = new HashMap<>();
+    /**
+     * The Removed.
+     */
+    protected final Set<String> removed = new HashSet<>();
+    private boolean closed = false;
+
+    protected Set<String> getRemoved() {
+        return removed;
+    }
+
+    protected Map<String,String> getProperties() {
+        return properties;
+    }
+
+    /**
+     * Instantiates a new Abstract config change request.
+     *
+     * @param uris the uris
+     */
+    protected AbstractMutableConfiguration(URI... uris){
+        for(URI uri:uris){
+            this.uris.add(Objects.requireNonNull(uri));
+        }
+        if(this.uris.isEmpty()){
+            throw new IllegalArgumentException("At least one URI should be provided.");
+        }
+    }
+
+    /**
+     * Get the unique id of this change request (UUID).
+     * @return the unique id of this change request (UUID).
+     */
+    @Override
+    public String getRequestID(){
+        return requestID;
+    }
+
+    @Override
+    public final Collection<URI> getBackendURIs() {
+        return Collections.unmodifiableCollection(uris);
+    }
+
+    @Override
+    public boolean isWritable(String keyExpression) {
+        return true;
+    }
+
+    @Override
+    public boolean isRemovable(String keyExpression) {
+        return true;
+    }
+
+    @Override
+    public abstract boolean exists(String keyExpression);
+
+    @Override
+    public void setRequestId(String requestId) {
+        checkClosed();
+        this.requestID = Objects.requireNonNull(requestId);
+    }
+
+    @Override
+    public MutableConfiguration put(String key, String value) {
+        checkClosed();
+        this.properties.put(key, value);
+        return this;
+    }
+
+    @Override
+    public MutableConfiguration putAll(Map<String, String> properties) {
+        checkClosed();
+        this.properties.putAll(properties);
+        return this;
+    }
+
+    @Override
+    public MutableConfiguration remove(String... keys) {
+        checkClosed();
+        Collections.addAll(this.removed, keys);
+        return this;
+    }
+
+    @Override
+    public MutableConfiguration remove(Collection<String> keys) {
+        checkClosed();
+        this.removed.addAll(keys);
+        return this;
+    }
+
+    @Override
+    public final void commit() {
+        checkClosed();
+        commitInternal();
+        closed = true;
+    }
+
+    /**
+     * Commit internal.
+     */
+    protected abstract void commitInternal();
+
+    @Override
+    public final void rollback() {
+        checkClosed();
+        closed = true;
+    }
+
+    @Override
+    public final boolean isClosed() {
+        return closed;
+    }
+
+    /**
+     * Check closed.
+     */
+    protected void checkClosed(){
+        if(closed){
+            throw new ConfigException("Change request already closed.");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfigurationBackendSpiSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfigurationBackendSpiSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfigurationBackendSpiSpi.java
new file mode 100644
index 0000000..15cbe87
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfigurationBackendSpiSpi.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.mutableconfig.spi;
+
+import java.net.URI;
+import java.util.*;
+
+/**
+ * Base class for implementing a MutableConfigurationBackend.
+ */
+public abstract class AbstractMutableConfigurationBackendSpiSpi implements MutableConfigurationBackendSpi {
+
+    private final URI backendURI;
+
+    /**
+     * The Properties.
+     */
+    protected final Map<String,String> addedProperties = new HashMap<>();
+    /**
+     * The Removed.
+     */
+    protected final Set<String> removedProperties = new HashSet<>();
+
+    protected Set<String> getRemovedProperties() {
+        return removedProperties;
+    }
+
+    protected Map<String,String> getAddedProperties() {
+        return addedProperties;
+    }
+
+    protected AbstractMutableConfigurationBackendSpiSpi(URI backendURI){
+        this.backendURI = Objects.requireNonNull(backendURI);
+    }
+
+    @Override
+    public URI getBackendURI() {
+        return backendURI;
+    }
+
+    @Override
+    public boolean isWritable(String keyExpression) {
+        return true;
+    }
+
+    @Override
+    public boolean isRemovable(String keyExpression) {
+        return true;
+    }
+
+    @Override
+    public abstract boolean isExisting(String keyExpression);
+
+    @Override
+    public void put(String key, String value) {
+        this.addedProperties.put(key, value);
+    }
+
+    @Override
+    public void putAll(Map<String, String> properties) {
+        this.addedProperties.putAll(properties);
+    }
+
+    @Override
+    public void remove(String... keys) {
+        Collections.addAll(this.removedProperties, keys);
+    }
+
+    @Override
+    public void remove(Collection<String> keys) {
+        this.removedProperties.addAll(keys);
+    }
+
+    @Override
+    public final void commit() {
+        commitInternal();
+        this.removedProperties.clear();
+        this.addedProperties.clear();
+    }
+
+    /**
+     * Commit internal.
+     */
+    protected abstract void commitInternal();
+
+    @Override
+    public final void rollback() {
+        this.removedProperties.clear();
+        this.addedProperties.clear();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/ConfigChangeManagerSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/ConfigChangeManagerSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/ConfigChangeManagerSpi.java
deleted file mode 100644
index fa78708..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/ConfigChangeManagerSpi.java
+++ /dev/null
@@ -1,39 +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.mutableconfig.spi;
-
-import org.apache.tamaya.mutableconfig.ConfigChangeRequest;
-
-import java.net.URI;
-
-/**
- * Provider SPI for the {@link org.apache.tamaya.mutableconfig.ConfigChangeManager}. Providers may override
- * other providers registering with a higher {@link javax.annotation.Priority} value annotated.
- */
-public interface ConfigChangeManagerSpi {
-
-   /**
-    * Creates a new change request for the given Configuration.
-    *
-    * @param backendURI the backend uri
-    * @return a new ChangeRequest, or null if the given backend URI cannot be edited.
-    */
-   ConfigChangeRequest createChangeRequest(URI backendURI);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendProviderSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendProviderSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendProviderSpi.java
new file mode 100644
index 0000000..98d4eb7
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendProviderSpi.java
@@ -0,0 +1,40 @@
+/*
+ * 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.mutableconfig.spi;
+
+import org.apache.tamaya.mutableconfig.MutableConfiguration;
+import org.apache.tamaya.mutableconfig.MutableConfigurationQuery;
+
+import java.net.URI;
+
+/**
+ * Provider SPI used by {@link MutableConfigurationQuery}. Providers may override
+ * other providers registering with a higher {@link javax.annotation.Priority} value annotated.
+ */
+public interface MutableConfigurationBackendProviderSpi {
+
+   /**
+    * Creates a new configuration backend for applying changes to.
+    *
+    * @param backendURI the backend uri
+    * @return the requested backend, or null if the given backend URI is not supported by the given SPI.
+    */
+   MutableConfigurationBackend getBackend(URI backendURI);
+
+}