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/02 17:16:16 UTC

[7/8] incubator-tamaya git commit: TAMAYA-136: Adding PropertyValue for PropertySource SPI. All changes and test fixes in all modules/examples relevant for release.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/functions/src/main/java/org/apache/tamaya/functions/MappedPropertySource.java
----------------------------------------------------------------------
diff --git a/modules/functions/src/main/java/org/apache/tamaya/functions/MappedPropertySource.java b/modules/functions/src/main/java/org/apache/tamaya/functions/MappedPropertySource.java
index 79b0844..3f85f53 100644
--- a/modules/functions/src/main/java/org/apache/tamaya/functions/MappedPropertySource.java
+++ b/modules/functions/src/main/java/org/apache/tamaya/functions/MappedPropertySource.java
@@ -19,6 +19,7 @@
 package org.apache.tamaya.functions;
 
 import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -80,8 +81,8 @@ class MappedPropertySource implements PropertySource {
     }
 
     @Override
-    public String get(String key) {
-        return getProperties().get(key);
+    public PropertyValue get(String key) {
+        return PropertyValue.of(key, getProperties().get(key), getName());
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/functions/src/main/java/org/apache/tamaya/functions/MetaEnrichedPropertySource.java
----------------------------------------------------------------------
diff --git a/modules/functions/src/main/java/org/apache/tamaya/functions/MetaEnrichedPropertySource.java b/modules/functions/src/main/java/org/apache/tamaya/functions/MetaEnrichedPropertySource.java
deleted file mode 100644
index 42b5957..0000000
--- a/modules/functions/src/main/java/org/apache/tamaya/functions/MetaEnrichedPropertySource.java
+++ /dev/null
@@ -1,91 +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.functions;
-
-import org.apache.tamaya.spi.PropertySource;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * Configuration that filters part of the entries defined by a filter predicate.
- */
-class MetaEnrichedPropertySource implements PropertySource {
-
-    private final PropertySource basePropertySource;
-    private final Map<String, String> metaInfo;
-
-    MetaEnrichedPropertySource(PropertySource basePropertySource, Map<String, String> metaInfo) {
-        this.basePropertySource = Objects.requireNonNull(basePropertySource);
-        this.metaInfo = Objects.requireNonNull(metaInfo);
-    }
-
-    // [meta:origin]a.b.c
-    @Override
-    public String get(String key) {
-        if(key.startsWith("[meta:")){
-            key = key.substring(6);
-            int index = key.indexOf(']');
-            String metaKey = key.substring(0,index);
-            String entryKey = key.substring(index+1);
-            String value =  basePropertySource.get(entryKey);
-            if(value!=null) {
-                return metaInfo.get(metaKey);
-            }
-        }
-        return basePropertySource.get(key);
-    }
-
-    @Override
-    public int getOrdinal() {
-        return basePropertySource.getOrdinal();
-    }
-
-    @Override
-    public String getName() {
-        return basePropertySource.getName();
-    }
-
-    @Override
-    public Map<String, String> getProperties() {
-        Map<String, String> baseProperties = basePropertySource.getProperties();
-        Map<String, String> allProperties = new HashMap<>(baseProperties);
-        for(Map.Entry<String,String> en: baseProperties.entrySet()) {
-            for (Map.Entry<String, String> miEn : metaInfo.entrySet()) {
-                allProperties.put("[meta:" + miEn.getKey() + ']' + en.getKey(), miEn.getValue());
-            }
-        }
-        return allProperties;
-    }
-
-    @Override
-    public boolean isScannable() {
-        return basePropertySource.isScannable();
-    }
-
-    @Override
-    public String toString() {
-        return "MetaEnrichedPropertySource{" +
-                "basePropertySource=" + basePropertySource +
-                ", metaInfo=" + metaInfo +
-                '}';
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/functions/src/main/java/org/apache/tamaya/functions/PropertySourceFunctions.java
----------------------------------------------------------------------
diff --git a/modules/functions/src/main/java/org/apache/tamaya/functions/PropertySourceFunctions.java b/modules/functions/src/main/java/org/apache/tamaya/functions/PropertySourceFunctions.java
index 11aa58c..23de455 100644
--- a/modules/functions/src/main/java/org/apache/tamaya/functions/PropertySourceFunctions.java
+++ b/modules/functions/src/main/java/org/apache/tamaya/functions/PropertySourceFunctions.java
@@ -20,6 +20,7 @@ package org.apache.tamaya.functions;
 
 import org.apache.tamaya.ConfigurationProvider;
 import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -50,7 +51,7 @@ public final class PropertySourceFunctions {
         }
 
         @Override
-        public String get(String key) {
+        public PropertyValue get(String key) {
             return null;
         }
 
@@ -77,40 +78,6 @@ public final class PropertySourceFunctions {
     }
 
     /**
-     * Creates a ConfigOperator that creates a Configuration containing only keys
-     * that are contained in the given section (non recursive). Hereby
-     * the section key is stripped away fromMap the resulting key.
-     * <p>
-     * Metadata is added only for keys that are present on the original configuration.
-     * They are added in the following format:
-     * <pre>
-     *     Given are
-     *       1) a configuration with two entries: entry1, entry 2
-     *       2) metadata as metaKey1=metaValue1, metaKey2=metaValue2
-     *
-     * The final configuration will look like:
-     *
-     *     entry1=entry1Value;
-     *     entry2=entry2Value;
-     *     [meta:metaKey1]entry1=metaValue1
-     *     [meta:metaKey2]entry1=metaValue2
-     *     [meta:metaKey1]entry2=metaValue1
-     *     [meta:metaKey2]entry2=metaValue2
-     * </pre>
-     * <p>
-     * This mechanism allows to add meta information such as origin, sensitivity, to all keys of a current
-     * PropertySource or Configuration. If done on multiple PropertySources that are combined the corresponding
-     * values are visible in synch with the values visible.
-     *
-     * @param propertySource the base propertySource, not null.
-     * @param metaData       the metaData to be added, not null
-     * @return the metadata enriched configuration, not null.
-     */
-    public static PropertySource addMetaData(PropertySource propertySource, Map<String, String> metaData) {
-        return new MetaEnrichedPropertySource(propertySource, metaData);
-    }
-
-    /**
      * Calculates the current section key and compares it with the given key.
      *
      * @param key        the fully qualified entry key, not null

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/functions/src/main/java/org/apache/tamaya/functions/ValueMappedPropertySource.java
----------------------------------------------------------------------
diff --git a/modules/functions/src/main/java/org/apache/tamaya/functions/ValueMappedPropertySource.java b/modules/functions/src/main/java/org/apache/tamaya/functions/ValueMappedPropertySource.java
index b0e9db8..a06b8b6 100644
--- a/modules/functions/src/main/java/org/apache/tamaya/functions/ValueMappedPropertySource.java
+++ b/modules/functions/src/main/java/org/apache/tamaya/functions/ValueMappedPropertySource.java
@@ -19,6 +19,7 @@
 package org.apache.tamaya.functions;
 
 import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -51,10 +52,10 @@ class ValueMappedPropertySource implements PropertySource{
     }
 
     @Override
-    public String get(String key) {
-        String value = this.source.get(key);
+    public PropertyValue get(String key) {
+        PropertyValue value = this.source.get(key);
         if(value!=null) {
-            return valueFilter.mapProperty(key, value);
+            return PropertyValue.of(key, valueFilter.mapProperty(key, value.getValue()), getName());
         }
         return null;
     }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/injection/src/test/java/org/apache/tamaya/inject/TestPropertySource.java
----------------------------------------------------------------------
diff --git a/modules/injection/src/test/java/org/apache/tamaya/inject/TestPropertySource.java b/modules/injection/src/test/java/org/apache/tamaya/inject/TestPropertySource.java
index b58d8a4..ff5d0fd 100644
--- a/modules/injection/src/test/java/org/apache/tamaya/inject/TestPropertySource.java
+++ b/modules/injection/src/test/java/org/apache/tamaya/inject/TestPropertySource.java
@@ -19,6 +19,7 @@
 package org.apache.tamaya.inject;
 
 import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -48,8 +49,8 @@ public class TestPropertySource implements PropertySource {
     }
 
     @Override
-    public String get(String key) {
-        return properties.get(key);
+    public PropertyValue get(String key) {
+        return PropertyValue.of(key,properties.get(key),getName());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/injection/src/test/java/org/apache/tamaya/inject/internal/DefaultDynamicValueTest.java
----------------------------------------------------------------------
diff --git a/modules/injection/src/test/java/org/apache/tamaya/inject/internal/DefaultDynamicValueTest.java b/modules/injection/src/test/java/org/apache/tamaya/inject/internal/DefaultDynamicValueTest.java
index 84f1f27..dd16f36 100644
--- a/modules/injection/src/test/java/org/apache/tamaya/inject/internal/DefaultDynamicValueTest.java
+++ b/modules/injection/src/test/java/org/apache/tamaya/inject/internal/DefaultDynamicValueTest.java
@@ -28,6 +28,7 @@ import org.apache.tamaya.inject.api.UpdatePolicy;
 import org.apache.tamaya.spi.ConversionContext;
 import org.apache.tamaya.spi.PropertyConverter;
 import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
 import org.junit.Test;
 
 import org.apache.tamaya.Configuration;
@@ -78,8 +79,8 @@ public class DefaultDynamicValueTest {
                 }
 
                 @Override
-                public String get(String key) {
-                    return properties.get(key);
+                public PropertyValue get(String key) {
+                    return PropertyValue.of(key,properties.get(key),getName());
                 }
 
                 @Override

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/integration/cdi-se/src/test/java/org/apache/tamaya/integration/cdi/cfg/ProvidedPropertySource.java
----------------------------------------------------------------------
diff --git a/modules/integration/cdi-se/src/test/java/org/apache/tamaya/integration/cdi/cfg/ProvidedPropertySource.java b/modules/integration/cdi-se/src/test/java/org/apache/tamaya/integration/cdi/cfg/ProvidedPropertySource.java
index 1c383b4..f7e3c6d 100644
--- a/modules/integration/cdi-se/src/test/java/org/apache/tamaya/integration/cdi/cfg/ProvidedPropertySource.java
+++ b/modules/integration/cdi-se/src/test/java/org/apache/tamaya/integration/cdi/cfg/ProvidedPropertySource.java
@@ -20,6 +20,7 @@
 package org.apache.tamaya.integration.cdi.cfg;
 
 import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
 
 import javax.enterprise.inject.Vetoed;
 import java.util.HashMap;
@@ -50,8 +51,8 @@ class ProvidedPropertySource implements PropertySource{
     }
 
     @Override
-    public String get(String key) {
-        return config.get(key);
+    public PropertyValue get(String key) {
+        return PropertyValue.of(key, config.get(key), getName());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/integration/cdi-se/src/test/java/org/apache/tamaya/integration/cdi/cfg/TestPropertySource.java
----------------------------------------------------------------------
diff --git a/modules/integration/cdi-se/src/test/java/org/apache/tamaya/integration/cdi/cfg/TestPropertySource.java b/modules/integration/cdi-se/src/test/java/org/apache/tamaya/integration/cdi/cfg/TestPropertySource.java
index 1db3d2c..75c55ca 100644
--- a/modules/integration/cdi-se/src/test/java/org/apache/tamaya/integration/cdi/cfg/TestPropertySource.java
+++ b/modules/integration/cdi-se/src/test/java/org/apache/tamaya/integration/cdi/cfg/TestPropertySource.java
@@ -20,6 +20,7 @@
 package org.apache.tamaya.integration.cdi.cfg;
 
 import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
 
 import javax.inject.Singleton;
 import java.util.HashMap;
@@ -62,8 +63,8 @@ public class TestPropertySource implements PropertySource{
     }
 
     @Override
-    public String get(String key) {
-        return config.get(key);
+    public PropertyValue get(String key) {
+        return PropertyValue.of(key, config.get(key), getName());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/EtcdAccessor.java
----------------------------------------------------------------------
diff --git a/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/EtcdAccessor.java b/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/EtcdAccessor.java
index 6923d9e..677d369 100644
--- a/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/EtcdAccessor.java
+++ b/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/EtcdAccessor.java
@@ -55,6 +55,11 @@ public class EtcdAccessor {
 
     /** Timeout in seconds. */
     private int timeout = 2;
+    /** Timeout in seconds. */
+    private int socketTimeout = 1000;
+    /** Timeout in seconds. */
+    private int connectTimeout = 1000;
+
     /** Property that make Johnzon accept commentc. */
     public static final String JOHNZON_SUPPORTS_COMMENTS_PROP = "org.apache.johnzon.supports-comments";
     /** The JSON reader factory used. */
@@ -100,8 +105,8 @@ public class EtcdAccessor {
         try {
             CloseableHttpClient httpclient = HttpClients.createDefault();
             HttpGet httpGet = new HttpGet(serverURL + "/version");
-            httpGet.setConfig(RequestConfig.copy(RequestConfig.DEFAULT).setSocketTimeout(timeout)
-                    .setConnectionRequestTimeout(timeout).setConnectTimeout(timeout).build());
+            httpGet.setConfig(RequestConfig.copy(RequestConfig.DEFAULT)
+            .setSocketTimeout(socketTimeout).setConnectTimeout(timeout).build());
             response = httpclient.execute(httpGet);
             HttpEntity entity;
             if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
@@ -155,16 +160,19 @@ public class EtcdAccessor {
         Map<String,String> result = new HashMap<>();
         try {
             HttpGet httpGet = new HttpGet(serverURL + "/v2/keys/"+key);
-            httpGet.setConfig(RequestConfig.copy(RequestConfig.DEFAULT).setSocketTimeout(timeout)
-                    .setConnectionRequestTimeout(timeout).setConnectTimeout(timeout).build());
+            httpGet.setConfig(RequestConfig.copy(RequestConfig.DEFAULT)
+            .setSocketTimeout(socketTimeout)
+                    .setConnectionRequestTimeout(timeout).setConnectTimeout(connectTimeout).build());
             response = httpclient.execute(httpGet);
             if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                 HttpEntity entity = response.getEntity();
                 JsonReader reader = readerFactory.createReader(new StringReader(EntityUtils.toString(entity)));
                 JsonObject o = reader.readObject();
                 JsonObject node = o.getJsonObject("node");
-                result.put(key, node.getString("value"));
-                result.put("_" + key +".source", "[etcd]"+serverURL);
+                if(node.containsKey("value")) {
+                    result.put(key, node.getString("value"));
+                    result.put("_" + key +".source", "[etcd]"+serverURL);
+                }
                 if(node.containsKey("createdIndex")) {
                     result.put("_" + key +".createdIndex", String.valueOf(node.getInt("createdIndex")));
                 }
@@ -250,8 +258,8 @@ public class EtcdAccessor {
         Map<String,String> result = new HashMap<>();
         try{
             HttpPut put = new HttpPut(serverURL + "/v2/keys/"+key);
-            put.setConfig(RequestConfig.copy(RequestConfig.DEFAULT).setSocketTimeout(timeout)
-                    .setConnectionRequestTimeout(timeout).setConnectTimeout(timeout).build());
+            put.setConfig(RequestConfig.copy(RequestConfig.DEFAULT).setSocketTimeout(socketTimeout)
+                    .setConnectionRequestTimeout(timeout).setConnectTimeout(connectTimeout).build());
             List<NameValuePair> nvps = new ArrayList<>();
             nvps.add(new BasicNameValuePair("value", value));
             if(ttlSeconds!=null){
@@ -336,8 +344,8 @@ public class EtcdAccessor {
         Map<String,String> result = new HashMap<>();
         try{
             HttpDelete delete = new HttpDelete(serverURL + "/v2/keys/"+key);
-            delete.setConfig(RequestConfig.copy(RequestConfig.DEFAULT).setSocketTimeout(timeout)
-                    .setConnectionRequestTimeout(timeout).setConnectTimeout(timeout).build());
+            delete.setConfig(RequestConfig.copy(RequestConfig.DEFAULT).setSocketTimeout(socketTimeout)
+                    .setConnectionRequestTimeout(timeout).setConnectTimeout(connectTimeout).build());
             response = httpclient.execute(delete);
             if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                 HttpEntity entity = response.getEntity();
@@ -449,8 +457,9 @@ public class EtcdAccessor {
         Map<String,String> result = new HashMap<>();
         try{
             HttpGet get = new HttpGet(serverURL + "/v2/keys/"+directory+"?recursive="+recursive);
-            get.setConfig(RequestConfig.copy(RequestConfig.DEFAULT).setSocketTimeout(timeout)
-                    .setConnectionRequestTimeout(timeout).setConnectTimeout(timeout).build());
+            get.setConfig(RequestConfig.copy(RequestConfig.DEFAULT)
+                    .setSocketTimeout(socketTimeout)
+                    .setConnectionRequestTimeout(timeout).setConnectTimeout(connectTimeout).build());
             response = httpclient.execute(get);
             if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                 HttpEntity entity = response.getEntity();

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/EtcdPropertySource.java
----------------------------------------------------------------------
diff --git a/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/EtcdPropertySource.java b/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/EtcdPropertySource.java
index b441141..db3902b 100644
--- a/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/EtcdPropertySource.java
+++ b/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/EtcdPropertySource.java
@@ -19,8 +19,12 @@
 package org.apache.tamaya.etcd;
 
 import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
+import org.apache.tamaya.spi.PropertyValueBuilder;
 
-import java.util.*;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -34,17 +38,13 @@ public class EtcdPropertySource implements PropertySource{
 
     private String prefix = System.getProperty("tamaya.etcd.prefix", "");
 
-    public EtcdPropertySource(){
-
-
-    }
 
     @Override
     public int getOrdinal() {
-        String configuredOrdinal = get(TAMAYA_ORDINAL);
+        PropertyValue configuredOrdinal = get(TAMAYA_ORDINAL);
         if(configuredOrdinal!=null){
             try{
-                return Integer.parseInt(configuredOrdinal);
+                return Integer.parseInt(configuredOrdinal.getValue());
             } catch(Exception e){
                 Logger.getLogger(getClass().getName()).log(Level.WARNING,
                         "Configured Ordinal is not an int number: " + configuredOrdinal, e);
@@ -67,7 +67,7 @@ public class EtcdPropertySource implements PropertySource{
     }
 
     @Override
-    public String get(String key) {
+    public PropertyValue get(String key) {
         // check prefix, if key does not start with it, it is not part of our name space
         // if so, the prefix part must be removed, so etcd can resolve without it
         if(!key.startsWith(prefix)){
@@ -96,7 +96,7 @@ public class EtcdPropertySource implements PropertySource{
                 props = accessor.get(reqKey);
                 if(!props.containsKey("_ERROR")) {
                     // No repfix mapping necessary here, since we only access/return the value...
-                    return props.get(reqKey);
+                    return new PropertyValueBuilder(key, props.get(reqKey), getName()).setContextData(props).build();
                 } else{
                     LOG.log(Level.FINE, "etcd error on " + accessor.getUrl() + ": " + props.get("_ERROR"));
                 }
@@ -109,7 +109,7 @@ public class EtcdPropertySource implements PropertySource{
 
     @Override
     public Map<String, String> getProperties() {
-        if(EtcdBackends.getEtcdBackends().isEmpty()){
+        if(!EtcdBackends.getEtcdBackends().isEmpty()){
             for(EtcdAccessor accessor: EtcdBackends.getEtcdBackends()){
                 try{
                     Map<String, String> props = accessor.getProperties("");

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/internal/EtcdConfigChangeRequest.java
----------------------------------------------------------------------
diff --git a/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/internal/EtcdConfigChangeRequest.java b/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/internal/EtcdConfigChangeRequest.java
index f3c7813..06ef1df 100644
--- a/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/internal/EtcdConfigChangeRequest.java
+++ b/modules/integration/etcd/src/main/java/org/apache/tamaya/etcd/internal/EtcdConfigChangeRequest.java
@@ -28,7 +28,10 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 /**
- * Change Request implementation based on etcd services.
+ * Change Request implementation based on etcd services. Etcd also supports a ttl to set values only for a defined
+ * number of seconds {@code ttl}. This is also supported by this component by adding ttl as a key parameter, e.g.
+ * {@code changeRequest.set("myTimedKey?ttl=30", "myValue");} will set a key {@code myTimedKey} valid only for
+ * 30 seconds.
  */
 class EtcdConfigChangeRequest extends AbstractConfigChangeRequest{
 
@@ -60,18 +63,32 @@ class EtcdConfigChangeRequest extends AbstractConfigChangeRequest{
         checkClosed();
         for(EtcdAccessor accessor: EtcdBackends.getEtcdBackends()){
             try{
-//                for(String k:getRemoved()){
-//                    Map<String,String> res = accessor.delete(k);
-//                    if(res.get("_ERROR")!=null){
-//                        LOG.info("Failed to remove key from etcd: " + k);
-//                    }
-//                }
-//                for(Map.Entry<String,String> en:getProperties().entrySet()){
-//                    Map<String,String> res = accessor.set(en.getKey(), en.getValue());
-//                    if(res.get("_ERROR")!=null){
-//                        LOG.info("Failed key from etcd: " + en.getKey()  + "=" + en.getValue());
-//                    }
-//                }
+                for(String k:getRemoved()){
+                    Map<String,String> res = accessor.delete(k);
+                    if(res.get("_ERROR")!=null){
+                        LOG.info("Failed to remove key from etcd: " + k);
+                    }
+                }
+                for(Map.Entry<String,String> en:getProperties().entrySet()){
+                    String key = en.getKey();
+                    Integer ttl = null;
+                    int index = en.getKey().indexOf('?');
+                    if(index>0){
+                        key = en.getKey().substring(0, index);
+                        String rawQuery = en.getKey().substring(index+1);
+                        String[] queries = rawQuery.split("&");
+                        for(String query:queries){
+                            if(query.contains("ttl")){
+                                int qIdx = query.indexOf('=');
+                                ttl = qIdx>0?Integer.parseInt(query.substring(qIdx+1).trim()):null;
+                            }
+                        }
+                    }
+                    Map<String,String> res = accessor.set(key, en.getValue(), ttl);
+                    if(res.get("_ERROR")!=null){
+                        LOG.info("Failed key from etcd: " + en.getKey()  + "=" + en.getValue());
+                    }
+                }
             } catch(Exception e){
                 LOG.log(Level.FINE, "etcd access failed on " + accessor.getUrl() + ", trying next...", e);
             }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/json/src/main/java/org/apache/tamaya/json/JSONPropertySource.java
----------------------------------------------------------------------
diff --git a/modules/json/src/main/java/org/apache/tamaya/json/JSONPropertySource.java b/modules/json/src/main/java/org/apache/tamaya/json/JSONPropertySource.java
index 48c6521..43cfa73 100644
--- a/modules/json/src/main/java/org/apache/tamaya/json/JSONPropertySource.java
+++ b/modules/json/src/main/java/org/apache/tamaya/json/JSONPropertySource.java
@@ -20,6 +20,7 @@ package org.apache.tamaya.json;
 
 import org.apache.tamaya.ConfigException;
 import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
 
 import java.io.InputStream;
 import java.net.URL;
@@ -89,10 +90,10 @@ public class JSONPropertySource implements PropertySource {
 
     @Override
     public int getOrdinal() {
-        String configuredOrdinal = get(TAMAYA_ORDINAL);
+        PropertyValue configuredOrdinal = get(TAMAYA_ORDINAL);
         if(configuredOrdinal!=null){
             try{
-                return Integer.parseInt(configuredOrdinal);
+                return Integer.parseInt(configuredOrdinal.getValue());
             } catch(Exception e){
                 Logger.getLogger(getClass().getName()).log(Level.WARNING,
                         "Configured Ordinal is not an int number: " + configuredOrdinal, e);
@@ -107,8 +108,8 @@ public class JSONPropertySource implements PropertySource {
     }
 
     @Override
-    public String get(String key) {
-        return getProperties().get(key);
+    public PropertyValue get(String key) {
+        return PropertyValue.of(key, getProperties().get(key), getName());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/json/src/test/java/org/apache/tamaya/json/CommonJSONTestCaseCollection.java
----------------------------------------------------------------------
diff --git a/modules/json/src/test/java/org/apache/tamaya/json/CommonJSONTestCaseCollection.java b/modules/json/src/test/java/org/apache/tamaya/json/CommonJSONTestCaseCollection.java
index 8283e7c..946878c 100644
--- a/modules/json/src/test/java/org/apache/tamaya/json/CommonJSONTestCaseCollection.java
+++ b/modules/json/src/test/java/org/apache/tamaya/json/CommonJSONTestCaseCollection.java
@@ -20,6 +20,7 @@ package org.apache.tamaya.json;
 
 import org.apache.tamaya.ConfigException;
 import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
 import org.hamcrest.CoreMatchers;
 import org.hamcrest.Matchers;
 import org.junit.Test;
@@ -50,9 +51,9 @@ public abstract class CommonJSONTestCaseCollection {
         PropertySource propertySource = getPropertiesFrom(configURL);
 
         assertThat(propertySource.get("name"), Matchers.notNullValue());
-        assertThat(propertySource.get("name"), equalTo("\u041e\u043b\u0438\u0432\u0435\u0440"));
+        assertThat(propertySource.get("name").getValue(), equalTo("\u041e\u043b\u0438\u0432\u0435\u0440"));
         assertThat(propertySource.get("\u0444\u0430\u043c\u0438\u043b\u0438\u044f"), Matchers.notNullValue());
-        assertThat(propertySource.get("\u0444\u0430\u043c\u0438\u043b\u0438\u044f"), Matchers.equalTo("Fischer"));
+        assertThat(propertySource.get("\u0444\u0430\u043c\u0438\u043b\u0438\u044f").getValue(), Matchers.equalTo("Fischer"));
     }
 
     @Test
@@ -66,16 +67,16 @@ public abstract class CommonJSONTestCaseCollection {
 
         assertThat(properties.getProperties().keySet(), hasSize(5));
 
-        String keyB = properties.get("b");
-        String keyDO = properties.get("d.o");
-        String keyDP = properties.get("d.p");
+        PropertyValue keyB = properties.get("b");
+        PropertyValue keyDO = properties.get("d.o");
+        PropertyValue keyDP = properties.get("d.p");
 
         assertThat(keyB, notNullValue());
-        assertThat(keyB, equalTo("B"));
+        assertThat(keyB.getValue(), equalTo("B"));
         assertThat(keyDO, notNullValue());
-        assertThat(keyDO, equalTo("O"));
+        assertThat(keyDO.getValue(), equalTo("O"));
         assertThat(keyDP, Matchers.notNullValue());
-        assertThat(keyDP, is("P"));
+        assertThat(keyDP.getValue(), is("P"));
     }
 
     @Test
@@ -90,19 +91,19 @@ public abstract class CommonJSONTestCaseCollection {
 
         assertThat(properties.getProperties().keySet(), hasSize(4));
 
-        String keyA = properties.get("a");
-        String keyDO = properties.get("b.o");
-        String keyDP = properties.get("b.p");
-        String keyC = properties.get("c");
+        PropertyValue keyA = properties.get("a");
+        PropertyValue keyDO = properties.get("b.o");
+        PropertyValue keyDP = properties.get("b.p");
+        PropertyValue keyC = properties.get("c");
 
         assertThat(keyA, notNullValue());
-        assertThat(keyA, is("A"));
+        assertThat(keyA.getValue(), is("A"));
         assertThat(keyC, notNullValue());
-        assertThat(keyC, equalTo("C"));
+        assertThat(keyC.getValue(), equalTo("C"));
         assertThat(keyDO, notNullValue());
-        assertThat(keyDO, equalTo("O"));
+        assertThat(keyDO.getValue(), equalTo("O"));
         assertThat(keyDP, notNullValue());
-        assertThat(keyDP, is("P"));
+        assertThat(keyDP.getValue(), is("P"));
     }
 
     @Test(expected = ConfigException.class)
@@ -153,16 +154,16 @@ public abstract class CommonJSONTestCaseCollection {
 
         assertThat(properties.getProperties().keySet(), hasSize(3));
 
-        String keyA = properties.get("a");
-        String keyB = properties.get("b");
-        String keyC = properties.get("c");
+        PropertyValue keyA = properties.get("a");
+        PropertyValue keyB = properties.get("b");
+        PropertyValue keyC = properties.get("c");
 
         assertThat(keyA, notNullValue());
-        assertThat(keyA, equalTo("A"));
+        assertThat(keyA.getValue(), equalTo("A"));
         assertThat(keyB, notNullValue());
-        assertThat(keyB, is("B"));
+        assertThat(keyB.getValue(), is("B"));
         assertThat(keyC, notNullValue());
-        assertThat(keyC, is("C"));
+        assertThat(keyC.getValue(), is("C"));
     }
 
     @Test(expected = ConfigException.class)

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/json/src/test/java/org/apache/tamaya/json/JSONPropertySourceTest.java
----------------------------------------------------------------------
diff --git a/modules/json/src/test/java/org/apache/tamaya/json/JSONPropertySourceTest.java b/modules/json/src/test/java/org/apache/tamaya/json/JSONPropertySourceTest.java
index b3a96b3..9892446 100644
--- a/modules/json/src/test/java/org/apache/tamaya/json/JSONPropertySourceTest.java
+++ b/modules/json/src/test/java/org/apache/tamaya/json/JSONPropertySourceTest.java
@@ -37,7 +37,7 @@ public class JSONPropertySourceTest extends CommonJSONTestCaseCollection {
         assertThat(configURL, CoreMatchers.notNullValue());
 
         JSONPropertySource source = new JSONPropertySource(configURL, 4);
-        assertEquals(source.get(PropertySource.TAMAYA_ORDINAL), "16784");
+        assertEquals(source.get(PropertySource.TAMAYA_ORDINAL).getValue(), "16784");
     }
     
     @Test(expected=ConfigException.class)

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/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
index 5188e10..8142fcc 100644
--- 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
@@ -23,6 +23,7 @@ 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;
@@ -44,6 +45,28 @@ public final class 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

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/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
index d06a438..94d3f2e 100644
--- 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
@@ -21,7 +21,11 @@ package org.apache.tamaya.mutableconfig.internal;
 import org.apache.tamaya.ConfigException;
 import org.apache.tamaya.mutableconfig.spi.AbstractConfigChangeRequest;
 
-import java.io.*;
+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;
@@ -84,7 +88,12 @@ class PropertiesFileConfigChangeRequest extends AbstractConfigChangeRequest{
             }
         }
         for(Map.Entry<String,String> en:super.properties.entrySet()){
-            this.properties.put(en.getKey(), en.getValue());
+            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);

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/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
index f98aceb..9211641 100644
--- 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
@@ -88,7 +88,12 @@ class XmlPropertiesFileConfigChangeRequest extends AbstractConfigChangeRequest{
             }
         }
         for(Map.Entry<String,String> en:super.properties.entrySet()){
-            this.properties.put(en.getKey(), en.getValue());
+            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);

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/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
index 28966e7..5e319db 100644
--- 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
@@ -50,6 +50,14 @@ public abstract class AbstractConfigChangeRequest implements ConfigChangeRequest
     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.
      *

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/ConfigChangeManagerTest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/ConfigChangeManagerTest.java b/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/ConfigChangeManagerTest.java
index 2e47383..8f4305c 100644
--- a/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/ConfigChangeManagerTest.java
+++ b/modules/mutable-config/src/test/java/org/apache/tamaya/mutableconfig/ConfigChangeManagerTest.java
@@ -62,7 +62,17 @@ public class ConfigChangeManagerTest {
      * @throws Exception the exception
      */
     @Test(expected=NullPointerException.class)
-    public void testNullCreateChangeRequest() throws Exception {
-        ConfigChangeRequest req = ConfigChangeManager.createChangeRequest(null);
+    public void testNullCreateChangeRequest1() throws Exception {
+        ConfigChangeRequest req = ConfigChangeManager.createChangeRequest((URI[])null);
+    }
+
+    /**
+     * Test null create change request.
+     *
+     * @throws Exception the exception
+     */
+    @Test(expected=NullPointerException.class)
+    public void testNullCreateChangeRequest2() throws Exception {
+        ConfigChangeRequest req = ConfigChangeManager.createChangeRequest((String[])null);
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/pom.xml
----------------------------------------------------------------------
diff --git a/modules/pom.xml b/modules/pom.xml
index 62fdd17..8b265de 100644
--- a/modules/pom.xml
+++ b/modules/pom.xml
@@ -51,6 +51,7 @@ under the License.
         <module>optional</module>
         <module>classloader-support</module>
         <module>integration</module>
+        <module>filter</module>
     </modules>
 
     <build>

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/remote/src/main/java/org/apache/tamaya/remote/BaseRemotePropertySource.java
----------------------------------------------------------------------
diff --git a/modules/remote/src/main/java/org/apache/tamaya/remote/BaseRemotePropertySource.java b/modules/remote/src/main/java/org/apache/tamaya/remote/BaseRemotePropertySource.java
index bf7579d..0fd1c67 100644
--- a/modules/remote/src/main/java/org/apache/tamaya/remote/BaseRemotePropertySource.java
+++ b/modules/remote/src/main/java/org/apache/tamaya/remote/BaseRemotePropertySource.java
@@ -22,6 +22,7 @@ import org.apache.tamaya.format.ConfigurationData;
 import org.apache.tamaya.format.ConfigurationFormat;
 import org.apache.tamaya.json.JSONFormat;
 import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
 
 import java.io.InputStream;
 import java.net.URL;
@@ -119,16 +120,16 @@ public abstract class BaseRemotePropertySource implements PropertySource{
     }
 
     @Override
-    public String get(String key) {
-        return getProperties().get(key);
+    public PropertyValue get(String key) {
+        return PropertyValue.of(key,getProperties().get(key),getName());
     }
 
     @Override
     public int getOrdinal(){
-        String configuredOrdinal = get(TAMAYA_ORDINAL);
+        PropertyValue configuredOrdinal = get(TAMAYA_ORDINAL);
         if(configuredOrdinal!=null){
             try{
-                return Integer.parseInt(configuredOrdinal);
+                return Integer.parseInt(configuredOrdinal.getValue());
             } catch(Exception e){
                 Logger.getLogger(getClass().getName()).log(Level.WARNING,
                         "Configured Ordinal is not an int number: " + configuredOrdinal, e);

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/ExpressionResolutionFilter.java
----------------------------------------------------------------------
diff --git a/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/ExpressionResolutionFilter.java b/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/ExpressionResolutionFilter.java
index 13816c8..e8bad93 100644
--- a/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/ExpressionResolutionFilter.java
+++ b/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/ExpressionResolutionFilter.java
@@ -19,6 +19,7 @@
 package org.apache.tamaya.resolver.internal;
 
 import org.apache.tamaya.resolver.spi.ExpressionEvaluator;
+import org.apache.tamaya.spi.FilterContext;
 import org.apache.tamaya.spi.PropertyFilter;
 import org.apache.tamaya.spi.ServiceContextManager;
 
@@ -71,14 +72,14 @@ public class ExpressionResolutionFilter implements PropertyFilter {
      * <li><code>\${resolverId:expression}foo${resolverId2:expression2}bar</code> (first expression is escaped).</li>
      * </ul>
      *
-     * @param key the key to be filtered
+     * @param context the filter context
      * @param valueToBeFiltered value to be analyzed for expressions
      * @return the resolved value, or the input in case where no expression was detected.
      */
     @Override
-    public String filterProperty(String key, String valueToBeFiltered){
-        LOG.finest("Resolving " + valueToBeFiltered + "(key=" + key + ")");
-        return evaluator.evaluateExpression(key, valueToBeFiltered);
+    public String filterProperty(String valueToBeFiltered, FilterContext context){
+        LOG.finest("Resolving " + valueToBeFiltered + "(key=" + context.getKey() + ")");
+        return evaluator.evaluateExpression(context.getKey(), valueToBeFiltered);
     }
 
 

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/resolver/src/test/java/org/apache/tamaya/resolver/MyTestPropertySource.java
----------------------------------------------------------------------
diff --git a/modules/resolver/src/test/java/org/apache/tamaya/resolver/MyTestPropertySource.java b/modules/resolver/src/test/java/org/apache/tamaya/resolver/MyTestPropertySource.java
index 1a06f22..7d99cbc 100644
--- a/modules/resolver/src/test/java/org/apache/tamaya/resolver/MyTestPropertySource.java
+++ b/modules/resolver/src/test/java/org/apache/tamaya/resolver/MyTestPropertySource.java
@@ -19,6 +19,7 @@
 package org.apache.tamaya.resolver;
 
 import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
 
 import java.io.File;
 import java.net.URISyntaxException;
@@ -85,8 +86,8 @@ public class MyTestPropertySource implements PropertySource{
     }
 
     @Override
-    public String get(String key) {
-        return properties.get(key);
+    public PropertyValue get(String key) {
+        return PropertyValue.of(key, properties.get(key), getName());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathPropertySourceProvider.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathPropertySourceProvider.java b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathPropertySourceProvider.java
index 0df3151..1b62c65 100644
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathPropertySourceProvider.java
+++ b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathPropertySourceProvider.java
@@ -33,6 +33,7 @@ import java.util.logging.Logger;
 
 import org.apache.tamaya.spi.PropertySource;
 import org.apache.tamaya.spi.PropertySourceProvider;
+import org.apache.tamaya.spi.PropertyValue;
 
 /**
  * Abstract base class that uses a descriptive resource path to define the locations of configuration files to be
@@ -142,10 +143,10 @@ public abstract class AbstractPathPropertySourceProvider implements PropertySour
 
         @Override
         public int getOrdinal() {
-            String configuredOrdinal = get(TAMAYA_ORDINAL);
+            PropertyValue configuredOrdinal = get(TAMAYA_ORDINAL);
             if (configuredOrdinal != null) {
                 try {
-                    return Integer.parseInt(configuredOrdinal);
+                    return Integer.parseInt(configuredOrdinal.getValue());
                 } catch (Exception e) {
                     Logger.getLogger(getClass().getName()).log(Level.WARNING,
                             "Configured Ordinal is not an int number: " + configuredOrdinal, e);
@@ -169,8 +170,8 @@ public abstract class AbstractPathPropertySourceProvider implements PropertySour
         }
 
         @Override
-        public String get(String key) {
-            return properties.get(key);
+        public PropertyValue get(String key) {
+            return PropertyValue.of(key, getProperties().get(key), getName());
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/resources/src/test/java/org/apache/tamaya/resource/AbstractPathPropertySourceProviderTest.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/test/java/org/apache/tamaya/resource/AbstractPathPropertySourceProviderTest.java b/modules/resources/src/test/java/org/apache/tamaya/resource/AbstractPathPropertySourceProviderTest.java
index fa5560a..8fe1b2b 100644
--- a/modules/resources/src/test/java/org/apache/tamaya/resource/AbstractPathPropertySourceProviderTest.java
+++ b/modules/resources/src/test/java/org/apache/tamaya/resource/AbstractPathPropertySourceProviderTest.java
@@ -19,6 +19,8 @@
 package org.apache.tamaya.resource;
 
 import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
+import org.apache.tamaya.spi.PropertyValueBuilder;
 import org.junit.Test;
 
 import java.net.URL;
@@ -87,10 +89,10 @@ public class AbstractPathPropertySourceProviderTest {
          * @return the 'importance' aka ordinal of the configured values. The higher, the more important.
          */
         public int getOrdinal() {
-            String configuredOrdinal = get(TAMAYA_ORDINAL);
+            PropertyValue configuredOrdinal = get(TAMAYA_ORDINAL);
             if (configuredOrdinal != null) {
                 try {
-                    return Integer.parseInt(configuredOrdinal);
+                    return Integer.parseInt(configuredOrdinal.getValue());
                 } catch (Exception e) {
                     Logger.getLogger(getClass().getName()).log(Level.WARNING,
                             "Configured Ordinal is not an int number: " + configuredOrdinal, e);
@@ -114,7 +116,7 @@ public class AbstractPathPropertySourceProviderTest {
         }
 
         @Override
-        public String get(String key) {
+        public PropertyValue get(String key) {
             return null;
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/resources/src/test/java/org/apache/tamaya/resource/internal/PathBasedPropertySourceProvider.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/test/java/org/apache/tamaya/resource/internal/PathBasedPropertySourceProvider.java b/modules/resources/src/test/java/org/apache/tamaya/resource/internal/PathBasedPropertySourceProvider.java
index 39885b8..7ea9b4c 100644
--- a/modules/resources/src/test/java/org/apache/tamaya/resource/internal/PathBasedPropertySourceProvider.java
+++ b/modules/resources/src/test/java/org/apache/tamaya/resource/internal/PathBasedPropertySourceProvider.java
@@ -20,6 +20,8 @@ package org.apache.tamaya.resource.internal;
 
 import org.apache.tamaya.resource.AbstractPathPropertySourceProvider;
 import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
+import org.apache.tamaya.spi.PropertyValueBuilder;
 
 import java.io.InputStream;
 import java.net.URL;
@@ -78,8 +80,8 @@ public class PathBasedPropertySourceProvider extends AbstractPathPropertySourceP
         }
 
         @Override
-        public String get(String key) {
-            return properties.get(key);
+        public PropertyValue get(String key) {
+            return PropertyValue.of(key,properties.get(key), getName());
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/server/pom.xml
----------------------------------------------------------------------
diff --git a/modules/server/pom.xml b/modules/server/pom.xml
index ff74e01..62fb139 100644
--- a/modules/server/pom.xml
+++ b/modules/server/pom.xml
@@ -33,20 +33,27 @@ under the License.
 
     <properties>
         <jdkVersion>1.7</jdkVersion>
+        <dropwizard.version>0.9.2</dropwizard.version>
     </properties>
 
+    <!-- Add typical dependencies for a web application -->
     <dependencies>
         <dependency>
+            <groupId>io.dropwizard</groupId>
+            <artifactId>dropwizard-core</artifactId>
+            <version>${dropwizard.version}</version>
+        </dependency>
+        <dependency>
             <groupId>org.apache.tamaya</groupId>
             <artifactId>tamaya-api</artifactId>
             <version>${project.version}</version>
-            <scope>provided</scope>
+            <scope>compile</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.tamaya</groupId>
             <artifactId>tamaya-core</artifactId>
             <version>${project.version}</version>
-            <scope>provided</scope>
+            <scope>compile</scope>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
@@ -62,17 +69,85 @@ under the License.
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.apache.cxf</groupId>
-            <artifactId>apache-cxf</artifactId>
-            <type>pom</type>
-            <version>3.1.2</version>
-        </dependency>
     </dependencies>
 
     <build>
         <plugins>
             <plugin>
+                <groupId>com.spotify</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+                <version>0.3.258</version>
+                <configuration>
+                    <imageName>apache/tamaya/config-server</imageName>
+                    <imageTags>
+                        <imageTag>${project.version}</imageTag>
+                    </imageTags>
+                    <baseImage>java:8-jre</baseImage>
+                    <entryPoint>["java", "-jar", "/${project.build.finalName}.jar", "server", "/config-server.yml"]</entryPoint>
+                    <exposes>
+                        <expose>8080</expose>
+                    </exposes>
+                    <resources>
+                        <resource>
+                            <targetPath>/</targetPath>
+                            <directory>${project.build.directory}</directory>
+                            <include>${project.build.finalName}.jar</include>
+                        </resource>
+                        <resource>
+                            <targetPath>/</targetPath>
+                            <directory>${project.build.directory}/classes</directory>
+                            <include>config-server.yml</include>
+                        </resource>
+                    </resources>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.4</version>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-shade-plugin</artifactId>
+                <version>2.3</version>
+                <configuration>
+                    <createDependencyReducedPom>true</createDependencyReducedPom>
+                    <filters>
+                        <filter>
+                            <artifact>*:*</artifact>
+                            <excludes>
+                                <exclude>META-INF/*.SF</exclude>
+                                <exclude>META-INF/*.DSA</exclude>
+                                <exclude>META-INF/*.RSA</exclude>
+                            </excludes>
+                        </filter>
+                    </filters>
+                </configuration>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                        <configuration>
+                            <transformers>
+                                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
+                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                                    <mainClass>org.apache.tamaya.server.ConfigServiceApp</mainClass>
+                                </transformer>
+                            </transformers>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
                 <extensions>true</extensions>

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/server/src/main/java/org/apache/tamaya/server/ConfigServer.java
----------------------------------------------------------------------
diff --git a/modules/server/src/main/java/org/apache/tamaya/server/ConfigServer.java b/modules/server/src/main/java/org/apache/tamaya/server/ConfigServer.java
deleted file mode 100644
index 3d0c070..0000000
--- a/modules/server/src/main/java/org/apache/tamaya/server/ConfigServer.java
+++ /dev/null
@@ -1,50 +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.server;
-
-import org.apache.tamaya.spi.ServiceContextManager;
-
-/**
- * Simple Server singleton for starting the built-in simple configuration server.
- */
-public final class ConfigServer {
-    /**
-     * Utility class constructor.
-     */
-    private ConfigServer(){}
-
-    /**
-     * Creates a new server instance.
-     * @return a new server instance.
-     */
-    public static Server createServer(){
-        return ServiceContextManager.getServiceContext().getService(Server.class);
-    }
-
-    /**
-     * Main method to start the simple config server as a main method.
-     * @param args the args provided.
-     */
-    public static void main(String... args){
-        String portVal = System.getProperty("port");
-        int port = portVal==null?8888:Integer.parseInt(portVal);
-        createServer().start(port);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/server/src/main/java/org/apache/tamaya/server/ConfigServiceApp.java
----------------------------------------------------------------------
diff --git a/modules/server/src/main/java/org/apache/tamaya/server/ConfigServiceApp.java b/modules/server/src/main/java/org/apache/tamaya/server/ConfigServiceApp.java
new file mode 100644
index 0000000..2e98998
--- /dev/null
+++ b/modules/server/src/main/java/org/apache/tamaya/server/ConfigServiceApp.java
@@ -0,0 +1,57 @@
+/*
+ * 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.server;
+
+import io.dropwizard.Application;
+import io.dropwizard.setup.Bootstrap;
+import io.dropwizard.setup.Environment;
+
+/**
+ * Main Application for the Tamaya Configuration Server.
+ */
+public class ConfigServiceApp extends Application<ConfigServiceConfiguration> {
+
+    public static void main(String... args) throws Exception {
+        new ConfigServiceApp().run(args);
+    }
+
+    @Override
+    public String getName() {
+        return "Tamaya Config-Server";
+    }
+
+    @Override
+    public void initialize(Bootstrap<ConfigServiceConfiguration> bootstrap) {
+        // nothing to do yet
+    }
+
+    @Override
+    public void run(ConfigServiceConfiguration configuration,
+                    Environment environment) {
+        final ConfigurationResource resource = new ConfigurationResource(
+                configuration.getScope()
+        );
+    //    final TemplateHealthCheck healthCheck =
+    //            new TemplateHealthCheck(configuration.getTemplate());
+    //    environment.healthChecks().register("template", healthCheck);
+        environment.jersey().register(resource);
+    }
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/server/src/main/java/org/apache/tamaya/server/ConfigServiceConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/server/src/main/java/org/apache/tamaya/server/ConfigServiceConfiguration.java b/modules/server/src/main/java/org/apache/tamaya/server/ConfigServiceConfiguration.java
new file mode 100644
index 0000000..6248e82
--- /dev/null
+++ b/modules/server/src/main/java/org/apache/tamaya/server/ConfigServiceConfiguration.java
@@ -0,0 +1,41 @@
+/*
+ * 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.server;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.dropwizard.Configuration;
+
+/**
+ *Configuration Server DropWizard Configuration.
+ */
+public class ConfigServiceConfiguration extends Configuration {
+
+    private String scope;
+
+    @JsonProperty
+    public String getScope() {
+        return scope;
+    }
+
+    @JsonProperty
+    public void setScope(String scope) {
+        this.scope = scope;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/server/src/main/java/org/apache/tamaya/server/ConfigurationResource.java
----------------------------------------------------------------------
diff --git a/modules/server/src/main/java/org/apache/tamaya/server/ConfigurationResource.java b/modules/server/src/main/java/org/apache/tamaya/server/ConfigurationResource.java
new file mode 100644
index 0000000..ec01097
--- /dev/null
+++ b/modules/server/src/main/java/org/apache/tamaya/server/ConfigurationResource.java
@@ -0,0 +1,321 @@
+/*
+ * 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.server;
+
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.ConfigurationProvider;
+import org.apache.tamaya.functions.ConfigurationFunctions;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonWriter;
+import javax.json.stream.JsonGenerator;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import java.io.StringWriter;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Spring boot based configuration service that behavious compatible with etcd REST API (excluded the blocking API
+ * calls).
+ */
+@Path("/")
+@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
+public class ConfigurationResource {
+    private final String scope;
+    private final AtomicLong readCounter  = new AtomicLong();
+    private final AtomicLong writeCounter  = new AtomicLong();
+    private final AtomicLong deleteCounter  = new AtomicLong();
+
+    public ConfigurationResource(String scope) {
+        this.scope = scope;
+    }
+
+    @GET
+    @Path("/version")
+    @Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
+    public String version() {
+        return "{ \"version\" : \"Apache Tamaya: 0.2-incubating\" }";
+    }
+
+    @GET
+    @Path("/v2/keys")
+    public String readEtcdConfig(@QueryParam("recursive") Boolean recursive) {
+        return readConfig(recursive);
+    }
+
+    /**
+     *
+     * This models a etcd2 compliant access point for getting a property value.
+     * @return
+     */
+    @GET
+    @Path("/keys")
+    public String readConfig(@QueryParam("recursive") Boolean recursive) {
+        readCounter.incrementAndGet();
+        Configuration config = ConfigurationProvider.getConfiguration();
+        Map<String,String> children = config.getProperties();
+        JsonArrayBuilder ab = Json.createArrayBuilder();
+        for(Map.Entry<String,String> en: children.entrySet()){
+            Node node = new Node(config, en.getKey(), "node");
+            ab.add(node.createJsonObject());
+        }
+        Node node = new Node(config, null, "node", ab.build());
+        JsonObjectBuilder root = Json.createObjectBuilder().add("action", "get")
+                .add("node", node.createJsonObject());
+        StringWriter writer = new StringWriter();
+        JsonWriter jwriter = Json.createWriter(writer);
+        jwriter.writeObject(root.build());
+        return writer.toString();
+    }
+
+    /**
+     * This models a etcd2 compliant access point for getting a property value.
+     * @param key
+     * @return
+     */
+    @GET
+    @Path("/v2/keys/{key}")
+    public String readEtcdConfig(@PathParam("key") String key, @QueryParam("recursive") Boolean recursive) {
+        return readConfig(key, recursive);
+    }
+
+    /**
+     * This models a etcd2 compliant access point for getting a property value.
+     * @param key
+     * @return
+     */
+    @GET
+    @Path("/keys/{key}")
+    public String readConfig(@PathParam("key") String key, @QueryParam("recursive") Boolean recursive) {
+        readCounter.incrementAndGet();
+        Configuration config = ConfigurationProvider.getConfiguration();
+        if(key!=null) {
+            if (key.startsWith("/")) {
+                key = key.substring(1);
+            }
+            if (config.get(key) != null && !recursive) {
+                Node node = new Node(config, key, "node");
+                JsonObjectBuilder root = Json.createObjectBuilder().add("action", "get")
+                        .add("node", node.createJsonObject());
+                StringWriter writer = new StringWriter();
+                JsonGenerator gen = Json.createGenerator(writer);
+                gen.write(root.build());
+                return writer.toString();
+            }
+        }
+        Map<String,String> children = null;
+        if(key==null){
+            children = config.getProperties();
+        } else{
+            children = config.with(ConfigurationFunctions.section(key)).getProperties();
+        }
+        JsonArrayBuilder ab = Json.createArrayBuilder();
+        for(Map.Entry<String,String> en: children.entrySet()){
+            Node node = new Node(config, en.getKey(), "node");
+            ab.add(node.createJsonObject());
+        }
+        Node node = new Node(config, key, "node", ab.build());
+        JsonObjectBuilder root = Json.createObjectBuilder().add("action", "get")
+                .add("node", node.createJsonObject());
+        StringWriter writer = new StringWriter();
+        JsonWriter jwriter = Json.createWriter(writer);
+        jwriter.writeObject(root.build());
+        return writer.toString();
+    }
+
+    @PUT
+    @Path("/v2/keys/{key}")
+    public String writeEtcdConfig(@PathParam("key") String key, @javax.ws.rs.FormParam("value") String value,
+                              @FormParam("ttl") Integer ttl) {
+        return writeConfig(key, value, ttl);
+    }
+    /**
+     * This models a etcd2 compliant access point for getting a property value:
+     * <pre>
+     *     {
+     "action": "set",
+     "node": {
+     "createdIndex": 3,
+     "key": "/message",
+     "modifiedIndex": 3,
+     "value": "Hello etcd"
+     },
+     "prevNode": {
+     "createdIndex": 2,
+     "key": "/message",
+     "value": "Hello world",
+     "modifiedIndex": 2
+     }
+     }
+     * </pre>
+     * @param key
+     * @return
+     */
+    @PUT
+    @Path("/keys/{key}")
+    public String writeConfig(@PathParam("key") String key, @javax.ws.rs.FormParam("value") String value,
+                              @FormParam("ttl") Integer ttl) {
+        writeCounter.incrementAndGet();
+        Configuration config = ConfigurationProvider.getConfiguration();
+        if(key.startsWith("/")){
+            key = key.substring(1);
+        }
+        Node prevNode = new Node(config, key, "prevNode");
+        // TODO implement write! value and ttl as input
+        Node node = new Node(config, key, "node");
+        JsonObjectBuilder root = Json.createObjectBuilder().add("action", "set")
+                .add("node", node.createJsonObject())
+                .add("prevNode", prevNode.createJsonObject());
+        StringWriter writer = new StringWriter();
+        JsonWriter jwriter = Json.createWriter(writer);
+        jwriter.writeObject(root.build());
+        return writer.toString();
+    }
+
+    @DELETE
+    @Path("/v2/keys/{key}")
+    public String deleteEtcdConfig(@PathParam("key") String key) {
+        return deleteConfig(key);
+    }
+    /**
+     * This models a etcd2 compliant access point for getting a property value:
+     * <pre>
+     *     {
+     "action": "set",
+     "node": {
+     "createdIndex": 3,
+     "key": "/message",
+     "modifiedIndex": 3,
+     "value": "Hello etcd"
+     },
+     "prevNode": {
+     "createdIndex": 2,
+     "key": "/message",
+     "value": "Hello world",
+     "modifiedIndex": 2
+     }
+     }
+     * </pre>
+     * @param key
+     * @return
+     */
+    @DELETE
+    @Path("/keys/{key}")
+    public String deleteConfig(@PathParam("key") String key) {
+        deleteCounter.incrementAndGet();
+        Configuration config = ConfigurationProvider.getConfiguration();
+        if(key.startsWith("/")){
+            key = key.substring(1);
+        }
+        Node prevNode = new Node(config, key, "prevNode");
+        // TODO implement write! value and ttl as input
+        Node node = new Node(config, key, "node");
+        JsonObjectBuilder root = Json.createObjectBuilder().add("action", "delete")
+                .add("node", node.createJsonObject())
+                .add("prevNode", prevNode.createJsonObject());
+        StringWriter writer = new StringWriter();
+        JsonWriter jwriter = Json.createWriter(writer);
+        jwriter.writeObject(root.build());
+        return writer.toString();
+    }
+
+    public long getDeleteCounter(){
+        return deleteCounter.get();
+    }
+
+    public long getReadCounter(){
+        return readCounter.get();
+    }
+
+    public long getWriteCounter(){
+        return writeCounter.get();
+    }
+
+    /**
+     * Internal representation of a configuration node as modelled by etc.
+     */
+    private static final class Node{
+        private Integer createdIndex;
+        private Integer modifiedIndex;
+        private String key;
+        private String value;
+        private String nodeId;
+        private Integer ttl;
+        private String expiration;
+        private JsonArray nodes;
+
+        Node(Configuration config, String key, String nodeId){
+            this(config, key, nodeId, null);
+        }
+        Node(Configuration config, String key, String nodeId, JsonArray nodes){
+            this.key = key;
+            this.nodeId = Objects.requireNonNull(nodeId);
+            if(key!=null) {
+                value = config.get(key);
+                createdIndex = config.getOrDefault("_" + key + ".createdIndex", Integer.class, null);
+                modifiedIndex = config.getOrDefault("_" + key + ".modifiedIndex", Integer.class, null);
+                ttl = config.getOrDefault("_" + key + ".ttl", Integer.class, null);
+                expiration = config.getOrDefault("_" + key + ".expiration", null);
+            }
+            this.nodes = nodes;
+        }
+
+        JsonObject createJsonObject(){
+            JsonObjectBuilder nodeBuilder = Json.createObjectBuilder();
+            if(key!=null) {
+                nodeBuilder.add("key", '/' + key);
+            }else{
+                nodeBuilder.add("dir", true);
+            }
+            if(value!=null){
+                nodeBuilder.add("value", value);
+            }
+            if(createdIndex!=null){
+                nodeBuilder.add("createdIndex", createdIndex.intValue());
+            }
+            if(modifiedIndex!=null){
+                nodeBuilder.add("modifiedIndex", modifiedIndex.intValue());
+            }
+            if(ttl!=null){
+                nodeBuilder.add("ttl", ttl.intValue());
+            }
+            if(expiration!=null){
+                nodeBuilder.add("expiration", value);
+            }
+            if(nodes!=null){
+                nodeBuilder.add("nodes", nodes);
+            }
+            return nodeBuilder.build();
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/server/src/main/java/org/apache/tamaya/server/FilteredConfigServlet.java
----------------------------------------------------------------------
diff --git a/modules/server/src/main/java/org/apache/tamaya/server/FilteredConfigServlet.java b/modules/server/src/main/java/org/apache/tamaya/server/FilteredConfigServlet.java
deleted file mode 100644
index 8fe0f49..0000000
--- a/modules/server/src/main/java/org/apache/tamaya/server/FilteredConfigServlet.java
+++ /dev/null
@@ -1,86 +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.server;
-
-import org.apache.http.HttpStatus;
-import org.apache.tamaya.server.internal.MediaTypeUtil;
-import org.apache.tamaya.server.spi.ConfigService;
-import org.apache.tamaya.spi.ServiceContextManager;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Servlet to be registered for answering requests for filterted configuration. You can register this servlet e.g.
- * under {@code /config/filtered}. Then it allows to perform requests in the form of {@code /config/filtered/$PATH},
- * e.g. {@code /config/filtered/java,sun?scope=CLIENT&scopeId=1.2.3.4&format=text/json}.
- */
-public class FilteredConfigServlet extends HttpServlet{
-
-    private static final Logger LOG = Logger.getLogger(FilteredConfigServlet.class.getName());
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * Gets the Service delegate to provide the configuration representation in different formats and scopes.
-     */
-    private ConfigService getConfService(){
-        return ServiceContextManager.getServiceContext()
-                    .getService(ConfigService.class);
-    }
-
-    @Override
-    protected void doGet(HttpServletRequest request, HttpServletResponse res) throws ServletException, IOException {
-        MediaType mediaType = MediaTypeUtil.getMediaType(request.getParameter("format"),request.getHeader(HttpHeaders.ACCEPT));
-        String scope = request.getParameter("scope");
-        String scopeId = request.getParameter("scopeId");
-        String path = request.getPathInfo();
-        if(path==null || path.isEmpty()){
-            res.setStatus(HttpStatus.SC_BAD_REQUEST);
-            return;
-        }
-        if(path.startsWith("/")){
-            path = path.substring(1);
-        }
-        try {
-            String response = getConfService().getConfigurationWithPath(path, mediaType, scope, scopeId, request);
-            if(response!=null){
-                res.setStatus(HttpStatus.SC_OK);
-                res.setHeader(HttpHeaders.CONTENT_ENCODING, "utf-8");
-                res.setContentType(mediaType.toString());
-                res.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_TYPE.toString());
-                res.getOutputStream().print(response);
-                return;
-            }
-            res.setStatus(HttpStatus.SC_BAD_REQUEST);
-        } catch(Exception e){
-            LOG.log(Level.SEVERE, "Error printing config.", e);
-            Response.status(Response.Status.INTERNAL_SERVER_ERROR);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/server/src/main/java/org/apache/tamaya/server/FullConfigServlet.java
----------------------------------------------------------------------
diff --git a/modules/server/src/main/java/org/apache/tamaya/server/FullConfigServlet.java b/modules/server/src/main/java/org/apache/tamaya/server/FullConfigServlet.java
deleted file mode 100644
index daddead..0000000
--- a/modules/server/src/main/java/org/apache/tamaya/server/FullConfigServlet.java
+++ /dev/null
@@ -1,86 +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.server;
-
-import org.apache.http.HttpStatus;
-import org.apache.tamaya.server.internal.MediaTypeUtil;
-import org.apache.tamaya.server.spi.ConfigService;
-import org.apache.tamaya.spi.ServiceContextManager;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-
-/**
- * Servlet to be registered for answering requests for accessing unscoped configuration. You can register this
- * servlet e.g. under {@code /config}. Then it allows to perform requests in the form of
- * {@code /config/java,sun?scope=CLIENT&scopeId=1.2.3.4&format=text/json}.
- */
-public class FullConfigServlet extends HttpServlet{
-
-    private static final Logger LOG = Logger.getLogger(FilteredConfigServlet.class.getName());
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * Gets the Service delegate to provide the configuration representation in different formats and scopes.
-     */
-    private ConfigService getConfService(){
-        return ServiceContextManager.getServiceContext()
-                .getService(ConfigService.class);
-    }
-
-    /**
-     * Servlet to be registered for answering requests for accessing unscoped configuration. You can register this
-     * servlet e.g. under {@code /config}. Then it allows to perform requests in the form of
-     * {@code /config/java,sun?scope=CLIENT&scopeId=1.2.3.4&format=text/json}.
-     */
-    @Override
-    protected void doGet(HttpServletRequest request, HttpServletResponse res) throws ServletException, IOException {
-        MediaType mediaType = MediaTypeUtil.getMediaType(request.getParameter("format"),
-                request.getHeader(HttpHeaders.ACCEPT));
-        String scope = request.getParameter("scope");
-        String scopeId = request.getParameter("scopeId");
-        try {
-            String response = getConfService().getConfiguration(mediaType, scope, scopeId, request);
-            if(response!=null) {
-                res.setStatus(HttpStatus.SC_OK);
-                res.setHeader(HttpHeaders.CONTENT_ENCODING, "utf-8");
-                if (mediaType.equals(MediaType.APPLICATION_JSON_TYPE)) {
-                    res.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_TYPE.toString());
-                    res.getOutputStream().print(response);
-                    return;
-                }
-            }
-            res.setStatus(HttpStatus.SC_BAD_REQUEST);
-        } catch(Exception e){
-            LOG.log(Level.SEVERE, "Error printing config.", e);
-            Response.status(Response.Status.INTERNAL_SERVER_ERROR);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d778cb81/modules/server/src/main/java/org/apache/tamaya/server/Server.java
----------------------------------------------------------------------
diff --git a/modules/server/src/main/java/org/apache/tamaya/server/Server.java b/modules/server/src/main/java/org/apache/tamaya/server/Server.java
deleted file mode 100644
index 5e2cb52..0000000
--- a/modules/server/src/main/java/org/apache/tamaya/server/Server.java
+++ /dev/null
@@ -1,46 +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.server;
-
-/**
- * Simple abstraction of the Server interface.
- */
-public interface Server {
-    /**
-     * Starts the server on the given port-
-     * @param port the target port.
-     */
-    void start(int port);
-
-    /**
-     * Checks if the server us started.
-     * @return true if the server us started.
-     */
-    boolean isStarted();
-
-    /**
-     * Stops the server, but does not destroy it, so it might be restarted.
-     */
-    void stop();
-
-    /**
-     * Destroy the server instance.
-     */
-    void destroy();
-}