TAMAYA-318 Fixed failing CDI tests and refactored dynamic value.

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

Branch: refs/heads/master
Commit: 7c071cafd73fe957f92c5cb1ea79fe272e4b4f91
Parents: ee1ca56
Author: Anatole Tresch <[email protected]>
Authored: Sun Nov 19 23:18:40 2017 +0100
Committer: Anatole Tresch <[email protected]>
Committed: Sun Nov 19 23:23:42 2017 +0100

----------------------------------------------------------------------
 .../tamaya/cdi/ConfigurationProducer.java       |   4 +-
 .../apache/tamaya/cdi/DefaultDynamicValue.java  | 380 +++----------------
 .../apache/tamaya/inject/api/DynamicValue.java  |   8 +
 .../tamaya/inject/spi/BaseDynamicValue.java     | 262 +++++++++++--
 .../tamaya/inject/spi/BaseDynamicValueTest.java |   2 +-
 .../ConfigTemplateInvocationHandler.java        |   2 +-
 .../inject/internal/ConfiguredFieldImpl.java    |  10 +-
 .../inject/internal/DefaultDynamicValue.java    | 266 ++-----------
 .../internal/DefaultDynamicValueTest.java       |  27 +-
 .../SpringConfigInjectionPostProcessor.java     |   5 +
 .../integration/spring/TamayaSpringConfig.java  |   5 +
 11 files changed, 346 insertions(+), 625 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/7c071caf/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/ConfigurationProducer.java
----------------------------------------------------------------------
diff --git 
a/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/ConfigurationProducer.java
 
b/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/ConfigurationProducer.java
index 279f04b..2dfef7c 100644
--- 
a/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/ConfigurationProducer.java
+++ 
b/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/ConfigurationProducer.java
@@ -45,9 +45,9 @@ public class ConfigurationProducer {
     private DynamicValue createDynamicValue(final InjectionPoint 
injectionPoint) {
         Member member = injectionPoint.getMember();
         if (member instanceof Field) {
-            return DefaultDynamicValue.of((Field) member, 
ConfigurationProvider.getConfiguration());
+            return DefaultDynamicValue.of(injectionPoint.getBean(), (Field) 
member, ConfigurationProvider.getConfiguration());
         } else if (member instanceof Method) {
-            return DefaultDynamicValue.of((Method) member, 
ConfigurationProvider.getConfiguration());
+            return DefaultDynamicValue.of(injectionPoint.getBean(), (Method) 
member, ConfigurationProvider.getConfiguration());
         }
         return null;
     }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/7c071caf/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/DefaultDynamicValue.java
----------------------------------------------------------------------
diff --git 
a/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/DefaultDynamicValue.java
 
b/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/DefaultDynamicValue.java
index 5a3c807..8c6dfee 100644
--- 
a/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/DefaultDynamicValue.java
+++ 
b/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/DefaultDynamicValue.java
@@ -27,21 +27,13 @@ import org.apache.tamaya.inject.api.UpdatePolicy;
 import org.apache.tamaya.inject.api.WithPropertyConverter;
 import org.apache.tamaya.inject.spi.BaseDynamicValue;
 import org.apache.tamaya.inject.spi.InjectionUtils;
-import org.apache.tamaya.spi.ConversionContext;
 import org.apache.tamaya.spi.PropertyConverter;
 
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.lang.ref.WeakReference;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.util.*;
-import java.util.logging.Logger;
 
 /**
  * A accessor for a single configured value. This can be used to support 
values that may change during runtime,
@@ -59,90 +51,56 @@ import java.util.logging.Logger;
  */
 final class DefaultDynamicValue<T> extends BaseDynamicValue<T> {
 
-    private static final long serialVersionUID = -2071172847144537443L;
-
-    /**
-     * The property name of the entry.
-     */
-    private final String propertyName;
-    /**
-     * The keys to be resolved.
-     */
-    private final String[] keys;
     /**
      * Back reference to the base configuration instance. This reference is 
used reevalaute the given property and
      * compare the result with the previous value after a configuration change 
was triggered.
      */
     private final Configuration configuration;
-    /**
-     * The target type of the property used to lookup a matching {@link 
PropertyConverter}.
-     * If null, {@code propertyConverter} is set and used instead.
-     */
-    private final TypeLiteral<T> targetType;
+
     /**
      * The property converter to be applied, may be null. In the ladder case 
targetType is not null.
      */
-    private final PropertyConverter<T> propertyConverter;
-    /**
-     * Policy that defines how new values are applied, be default it is 
applied initially once, but never updated
-     * anymore.
-     */
-    private UpdatePolicy updatePolicy;
+    private final PropertyConverter<T> customConverter;
     /**
      * Load policy.
      */
     private final LoadPolicy loadPolicy;
 
     /**
-     * The current value, never null.
-     */
-    private transient T value;
-    /**
-     * The new value, or null.
-     */
-    private transient Object[] newValue;
-    /**
-     * List of listeners that listen for changes.
-     */
-    private transient WeakList<PropertyChangeListener> listeners;
-
-    /**
      * Constructor.
      *
      * @param propertyName      the name of the fields' property/method.
      * @param keys              the keys of the property, not null.
      * @param configuration     the configuration, not null.
      * @param targetType        the target type, not null.
-     * @param propertyConverter the optional converter to be used.
+     * @param customConverter the optional converter to be used.
      */
-    private DefaultDynamicValue(String propertyName, Configuration 
configuration, TypeLiteral<T> targetType,
-                                PropertyConverter<T> propertyConverter, 
List<String> keys, LoadPolicy loadPolicy,
+    private DefaultDynamicValue(Object owner, String propertyName, 
Configuration configuration, TypeLiteral<T> targetType,
+                                PropertyConverter<T> customConverter, 
List<String> keys, LoadPolicy loadPolicy,
                                 UpdatePolicy updatePolicy) {
-        this.propertyName = Objects.requireNonNull(propertyName);
-        this.keys = keys.toArray(new String[keys.size()]);
+        super(owner, propertyName, targetType, keys);
         this.configuration = Objects.requireNonNull(configuration);
-        this.propertyConverter = propertyConverter;
-        this.targetType = targetType;
+        this.customConverter = customConverter;
         this.loadPolicy = Objects.requireNonNull(loadPolicy);
-        this.updatePolicy = Objects.requireNonNull(updatePolicy);
+        setUpdatePolicy(updatePolicy);
         if(loadPolicy == LoadPolicy.INITIAL){
-            this.value = evaluateValue();
+            updateValue();
         }
     }
 
-    public static DynamicValue of(Field annotatedField, Configuration 
configuration) {
-        return of(annotatedField, configuration, LoadPolicy.ALWAYS, 
UpdatePolicy.IMMEDIATE);
+    public static DynamicValue of(Object owner, Field annotatedField, 
Configuration configuration) {
+        return of(owner, annotatedField, configuration, LoadPolicy.ALWAYS, 
UpdatePolicy.IMMEDIATE);
     }
 
-    public static DynamicValue of(Field annotatedField, Configuration 
configuration, LoadPolicy loadPolicy) {
-        return of(annotatedField, configuration, loadPolicy, 
UpdatePolicy.IMMEDIATE);
+    public static DynamicValue of(Object owner, Field annotatedField, 
Configuration configuration, LoadPolicy loadPolicy) {
+        return of(owner, annotatedField, configuration, loadPolicy, 
UpdatePolicy.IMMEDIATE);
     }
 
-    public static DynamicValue of(Field annotatedField, Configuration 
configuration, UpdatePolicy updatePolicy) {
-        return of(annotatedField, configuration, LoadPolicy.ALWAYS, 
updatePolicy);
+    public static DynamicValue of(Object owner, Field annotatedField, 
Configuration configuration, UpdatePolicy updatePolicy) {
+        return of(owner, annotatedField, configuration, LoadPolicy.ALWAYS, 
updatePolicy);
     }
 
-    public static DynamicValue of(Field annotatedField, Configuration 
configuration, LoadPolicy loadPolicy, UpdatePolicy updatePolicy) {
+    public static DynamicValue of(Object owner, Field annotatedField, 
Configuration configuration, LoadPolicy loadPolicy, UpdatePolicy updatePolicy) {
         // Check for adapter/filter
         Type targetType = annotatedField.getGenericType();
         if (targetType == null) {
@@ -170,23 +128,23 @@ final class DefaultDynamicValue<T> extends 
BaseDynamicValue<T> {
             }
         }
         List<String> keys = InjectionUtils.getKeys(annotatedField);
-        return new DefaultDynamicValue(annotatedField.getName(), configuration,
+        return new DefaultDynamicValue(owner, annotatedField.getName(), 
configuration,
                 TypeLiteral.of(targetType), propertyConverter, keys, 
loadPolicy, updatePolicy);
     }
 
-    public static DynamicValue of(Method method, Configuration configuration) {
-        return of(method, configuration, LoadPolicy.ALWAYS, 
UpdatePolicy.IMMEDIATE);
+    public static DynamicValue of(Object owner, Method method, Configuration 
configuration) {
+        return of(owner, method, configuration, LoadPolicy.ALWAYS, 
UpdatePolicy.IMMEDIATE);
     }
 
-    public static DynamicValue of(Method method, Configuration configuration, 
UpdatePolicy updatePolicy) {
-        return of(method, configuration, LoadPolicy.ALWAYS, updatePolicy);
+    public static DynamicValue of(Object owner, Method method, Configuration 
configuration, UpdatePolicy updatePolicy) {
+        return of(owner, method, configuration, LoadPolicy.ALWAYS, 
updatePolicy);
     }
 
-    public static DynamicValue of(Method method, Configuration configuration, 
LoadPolicy loadPolicy) {
-        return of(method, configuration, loadPolicy, UpdatePolicy.IMMEDIATE);
+    public static DynamicValue of(Object owner, Method method, Configuration 
configuration, LoadPolicy loadPolicy) {
+        return of(owner, method, configuration, loadPolicy, 
UpdatePolicy.IMMEDIATE);
     }
 
-    public static DynamicValue of(Method method, Configuration configuration, 
LoadPolicy loadPolicy, UpdatePolicy updatePolicy) {
+    public static DynamicValue of(Object owner, Method method, Configuration 
configuration, LoadPolicy loadPolicy, UpdatePolicy updatePolicy) {
         // Check for adapter/filter
         Type targetType = method.getGenericReturnType();
         if (targetType == null) {
@@ -213,285 +171,35 @@ final class DefaultDynamicValue<T> extends 
BaseDynamicValue<T> {
                         + '.' + method.getName(), e);
             }
         }
-        return new DefaultDynamicValue<>(method.getName(),
+        return new DefaultDynamicValue<>(owner, method.getName(),
                 configuration, TypeLiteral.of(targetType), propertyConverter, 
InjectionUtils.getKeys(method),
                 loadPolicy, updatePolicy);
     }
 
 
-    /**
-     * Commits a new value that has not been committed yet, make it the new 
value of the instance. On change any
-     * registered listeners will be triggered.
-     */
-    public void commit() {
-        T oldValue = value;
-        value = newValue==null?null:(T)newValue[0];
-        newValue = null;
-        informListeners(oldValue, value);
-    }
-
-    private void informListeners(T value, T newValue) {
-        synchronized (this) {
-            PropertyChangeEvent evt = new PropertyChangeEvent(this, 
propertyName, value,
-                    newValue);
-            if (listeners != null) {
-                for (PropertyChangeListener consumer : listeners.get()) {
-                    consumer.propertyChange(evt);
-                }
-            }
-        }
-    }
-
-    /**
-     * Discards a new value that was published. No listeners will be informed.
-     */
-    public void discard() {
-        newValue = null;
-    }
-
-
-    /**
-     * Access the {@link UpdatePolicy} used for updating this value.
-     *
-     * @return the update policy, never null.
-     */
-    public UpdatePolicy getUpdatePolicy() {
-        return updatePolicy;
+    @Override
+    protected Configuration getConfiguration() {
+        return configuration;
     }
 
-    /**
-     * Sets a new {@link UpdatePolicy}.
-     *
-     * @param updatePolicy the new policy, not null.
-     */
-    public void setUpdatePolicy(UpdatePolicy updatePolicy) {
-        this.updatePolicy = Objects.requireNonNull(updatePolicy);
-    }
 
-    /**
-     * Add a listener to be called as weak reference, when this value has been 
changed.
-     *
-     * @param l the listener, not null
-     */
-    public void addListener(PropertyChangeListener l) {
-        if (listeners == null) {
-            listeners = new WeakList<>();
-        }
-        listeners.add(l);
+    @Override
+    protected PropertyConverter<T> getCustomConverter() {
+        return customConverter;
     }
 
-    /**
-     * Removes a listener to be called, when this value has been changed.
-     *
-     * @param l the listner to be removed, not null
-     */
-    public void removeListener(PropertyChangeListener l) {
-        if (listeners != null) {
-            listeners.remove(l);
-        }
+    @Override
+    public String toString() {
+        return "DefaultDynamicValue{" +
+                "configuration=" + configuration +
+                ", customConverter=" + customConverter +
+                ", loadPolicy=" + loadPolicy +
+                ", value=" + value +
+                ", newValue=" + newValue +
+                ", defaultValue=" + getDefaultValue() +
+                ", discarded=" + discarded +
+                ", keys=" + getKeys() +
+                ", updatePolicy=" + getUpdatePolicy() +
+                '}';
     }
-
-    /**
-     * If a value is present in this {@code DynamicValue}, returns the value,
-     * otherwise throws {@code ConfigException}.
-     *
-     * @return the non-null value held by this {@code Optional}
-     * @throws ConfigException if there is no value present
-     * @see DefaultDynamicValue#isPresent()
-     */
-    public T get() {
-        T newLocalValue;
-        if(loadPolicy!=LoadPolicy.INITIAL) {
-            newLocalValue = evaluateValue();
-            if (this.value == null) {
-                this.value = newLocalValue;
-            }
-            if(!Objects.equals(this.value, newLocalValue)){
-                switch (updatePolicy){
-                    case IMMEDEATE:
-                    case IMMEDIATE:
-                        commit();
-                        break;
-                    case EXPLCIT:
-                    case EXPLICIT:
-                        this.newValue = new Object[]{newLocalValue};
-                        break;
-                    case LOG_ONLY:
-                        informListeners(this.value, newLocalValue);
-                        this.newValue = null;
-                        break;
-                    case NEVER:
-                        this.newValue = null;
-                        break;
-                    default:
-                        this.newValue = null;
-                        break;
-                }
-            }
-        }
-        return value;
-    }
-
-    /**
-     * Method to check for and apply a new value. Depending on the {@link  
UpdatePolicy}
-     * the value is immediately or deferred visible (or it may even be ignored 
completely).
-     *
-     * @return true, if a new value has been detected. The value may not be 
visible depending on the current
-     * {@link UpdatePolicy} in place.
-     */
-    public boolean updateValue() {
-        if(this.value==null && this.newValue==null){
-            this.value = evaluateValue();
-            return false;
-        }
-        T newValue = evaluateValue();
-        if (Objects.equals(newValue, this.value)) {
-            return false;
-        }
-        switch (this.updatePolicy) {
-            case LOG_ONLY:
-                Logger.getLogger(getClass().getName()).info("Discard change on 
" + this + ", newValue=" + newValue);
-                informListeners(value, newValue);
-                this.newValue = null;
-                break;
-            case NEVER:
-                this.newValue = null;
-                break;
-            case EXPLCIT:
-            case IMMEDEATE:
-            default:
-                this.newValue = new Object[]{newValue};
-                commit();
-                break;
-        }
-        return true;
-    }
-
-    /**
-     * Evaluates the current value dynamically from the underlying 
configuration.
-     *
-     * @return the current actual value, or null.
-     */
-    public T evaluateValue() {
-        T value = null;
-
-        for (String key : keys) {
-            if (propertyConverter == null) {
-                value = configuration.get(key, targetType);
-            } else {
-                String source = configuration.get(key);
-                ConversionContext ctx = new 
ConversionContext.Builder(configuration,
-                        configuration.getContext(), key, targetType).build();
-                value = propertyConverter.convert(source, ctx);
-            }
-
-            if (value != null) {
-                break;
-            }
-        }
-
-        return value;
-    }
-
-    /**
-     * Access a new value that has not yet been committed.
-     *
-     * @return the uncommitted new value, or null.
-     */
-    public T getNewValue() {
-        T nv = newValue==null?null:(T)newValue[0];
-        if (nv != null) {
-            return nv;
-        }
-        return null;
-    }
-
-
-    /**
-     * Serialization implementation that strips away the non serializable 
Optional part.
-     *
-     * @param oos the output stream
-     * @throws IOException if serialization fails.
-     */
-    private void writeObject(ObjectOutputStream oos) throws IOException {
-        oos.writeObject(getUpdatePolicy());
-        oos.writeObject(get());
-    }
-
-    /**
-     * Reads an instance from the input stream.
-     *
-     * @param ois the object input stream
-     * @throws IOException            if deserialization fails.
-     * @throws ClassNotFoundException
-     */
-    private void readObject(ObjectInputStream ois) throws IOException, 
ClassNotFoundException {
-        this.updatePolicy = (UpdatePolicy) ois.readObject();
-        if (isPresent()) {
-            this.value = (T) ois.readObject();
-        }
-        newValue = null;
-    }
-
-
-    /**
-     * Simple helper that allows keeping the listeners registered as weak 
references, hereby avoiding any
-     * memory leaks.
-     *
-     * @param <I> the type
-     */
-    private class WeakList<I> {
-        final List<WeakReference<I>> refs = new LinkedList<>();
-
-        /**
-         * Adds a new instance.
-         *
-         * @param t the new instance, not null.
-         */
-        void add(I t) {
-            refs.add(new WeakReference<>(t));
-        }
-
-        /**
-         * Removes a instance.
-         *
-         * @param t the instance to be removed.
-         */
-        void remove(I t) {
-            synchronized (refs) {
-                for (Iterator<WeakReference<I>> iterator = refs.iterator(); 
iterator.hasNext(); ) {
-                    WeakReference<I> ref = iterator.next();
-                    I instance = ref.get();
-                    if (instance == null || instance == t) {
-                        iterator.remove();
-                        break;
-                    }
-                }
-            }
-        }
-
-
-        /**
-         * Access a list (copy) of the current instances that were not 
discarded by the GC.
-         *
-         * @return the list of accessible items.
-         */
-        public List<I> get() {
-            synchronized (refs) {
-                List<I> res = new ArrayList<>();
-                for (Iterator<WeakReference<I>> iterator = refs.iterator(); 
iterator.hasNext(); ) {
-                    WeakReference<I> ref = iterator.next();
-                    I instance = ref.get();
-                    if (instance == null) {
-                        iterator.remove();
-                    } else {
-                        res.add(instance);
-                    }
-                }
-                return res;
-            }
-        }
-    }
-
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/7c071caf/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/api/DynamicValue.java
----------------------------------------------------------------------
diff --git 
a/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/api/DynamicValue.java
 
b/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/api/DynamicValue.java
index 54ab10a..ef249ac 100644
--- 
a/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/api/DynamicValue.java
+++ 
b/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/api/DynamicValue.java
@@ -59,6 +59,14 @@ public interface DynamicValue<T> {
     void commit();
 
     /**
+     * Discards a new value that has been published and ignore all future 
evaluations to the last discarded
+     * value. If a different new value than the discarded value will be 
evaluated a value change
+     * will be flagged and handled as defined by the {@link UpdatePolicy}.
+     * No listeners will be triggered.
+     */
+    void discard();
+
+    /**
      * Access the {@link UpdatePolicy} used for updating this value.
      * @return the update policy, never null.
      */

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/7c071caf/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/spi/BaseDynamicValue.java
----------------------------------------------------------------------
diff --git 
a/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/spi/BaseDynamicValue.java
 
b/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/spi/BaseDynamicValue.java
index 59e7683..d886d45 100644
--- 
a/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/spi/BaseDynamicValue.java
+++ 
b/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/spi/BaseDynamicValue.java
@@ -23,15 +23,15 @@ import org.apache.tamaya.Configuration;
 import org.apache.tamaya.TypeLiteral;
 import org.apache.tamaya.inject.api.DynamicValue;
 import org.apache.tamaya.inject.api.UpdatePolicy;
+import org.apache.tamaya.spi.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
 
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.io.Serializable;
-import java.lang.reflect.Member;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
+import java.lang.ref.WeakReference;
+import java.util.*;
+import java.util.function.Consumer;
 import java.util.function.Supplier;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -53,27 +53,72 @@ import java.util.logging.Logger;
  *
  * @param <T> The type of the value.
  */
-public abstract class BaseDynamicValue<T> implements DynamicValue<T>, 
Serializable {
+public abstract class BaseDynamicValue<T> implements DynamicValue<T> {
 
     private static final long serialVersionUID = 1L;
 
     private static final Logger LOG = 
Logger.getLogger(DynamicValue.class.getName());
 
+    /** The value owner used for PropertyChangeEvents. */
+    private Object owner;
+    /**
+     * The property name of the entry.
+     */
+    private String propertyName;
+
+    /**
+     * Policy that defines how new values are applied, be default it is 
applied initially once, but never updated
+     * anymore.
+     */
     private UpdatePolicy updatePolicy = UpdatePolicy.NEVER;
+    /** The targe type. */
     private TypeLiteral<T> targetType;
-    private T currentValue;
-    private T newValue;
+    /**
+     * The current value, never null.
+     */
+    protected transient T value;
+    /** The last discarded value. */
+    protected transient T discarded;
+    /** Any new value, not yet applied. */
+    protected transient T newValue;
+    /** The configured default value, before type conversion. */
+    private String defaultValue;
+    /** The list of candidate keys to be used. */
     private List<String> keys = new ArrayList<>();
-    private List<PropertyChangeListener> listeners = 
Collections.synchronizedList(new ArrayList<>());
-
+    /** The registered listeners. */
+    private WeakList<PropertyChangeListener> listeners = new WeakList<>();
 
-    public BaseDynamicValue(TypeLiteral targetType, List<String> keys){
+    /**
+     * Creates a new instance.
+     * @param owner the owner, not null.
+     * @param propertyName the property name, not null.
+     * @param targetType the target type.
+     * @param keys the candidate keys.
+     */
+    public BaseDynamicValue(Object owner, String propertyName, TypeLiteral 
targetType, List<String> keys){
         if(keys == null || keys.isEmpty()){
             throw new ConfigException("At least one key is required.");
         }
+        this.owner = owner;
+        this.propertyName = Objects.requireNonNull(propertyName);
         this.targetType = Objects.requireNonNull(targetType);
         this.keys.addAll(keys);
-        this.currentValue = evaluateValue();
+    }
+
+    /**
+     * Get the default value, used if no value could be evaluated.
+     * @return the default value, or null.
+     */
+    public String getDefaultValue() {
+        return defaultValue;
+    }
+
+    /**
+     * Set the default value to be used.
+     * @param defaultValue the default value.
+     */
+    public void setDefaultValue(String defaultValue) {
+        this.defaultValue = defaultValue;
     }
 
     /**
@@ -83,16 +128,20 @@ public abstract class BaseDynamicValue<T> implements 
DynamicValue<T>, Serializab
     protected abstract Configuration getConfiguration();
 
     /**
-     * Get the owner of this dynamic value instance.
-     * @return the owner, never null.
+     * Get the corresponding property name.
+     * @return
      */
-    protected abstract Object getOwner();
+    protected String getPropertyName(){
+        return propertyName;
+    }
 
     /**
-     * Get the corresponding property name.
-     * @return
+     * Get the owner of this dynamic value instance.
+     * @return the owner, never null.
      */
-    protected abstract String getPropertyName();
+    protected Object getOwner(){
+        return owner;
+    }
 
     /**
      * Get the targeted keys, in evaluation order.
@@ -112,11 +161,21 @@ public abstract class BaseDynamicValue<T> implements 
DynamicValue<T>, Serializab
 
     @Override
     public void commit() {
-        if(!Objects.equals(newValue, currentValue)) {
-            T oldValue = this.currentValue;
-            currentValue = newValue;
-            publishChangeEvent(this.currentValue, newValue);
+        if(!Objects.equals(newValue, value)) {
+            T oldValue = this.value;
+            value = newValue;
+            discarded = null;
+            publishChangeEvent(this.value, newValue);
+            newValue = null;
+        }
+    }
+
+    @Override
+    public void discard() {
+        if(newValue!=null){
+            discarded = newValue;
         }
+        newValue = null;
     }
 
     @Override
@@ -142,21 +201,32 @@ public abstract class BaseDynamicValue<T> implements 
DynamicValue<T>, Serializab
 
     @Override
     public T get() {
-        return currentValue;
+        updateValue();
+        return value;
     }
 
     @Override
     public boolean updateValue() {
         Configuration config = getConfiguration();
         T val = evaluateValue();
-        if(!Objects.equals(val, currentValue)){
+        if(value == null){
+            value = val;
+            return true;
+        }else if(discarded!=null && discarded.equals(val)){
+            // the evaluated value has been discarded and will be flagged out.
+            return false;
+        }else{
+            // Reset discarded state for a new value.
+            discarded = null;
+        }
+        if(!Objects.equals(val, value)){
             switch (updatePolicy){
                 case EXPLICIT:
                     newValue = val;
                     break;
                 case IMMEDIATE:
-                    this.currentValue = val;
-                    publishChangeEvent(this.currentValue, val);
+                    this.value = val;
+                    publishChangeEvent(this.value, val);
                     break;
                 case LOG_ONLY:
                     LOG.info("New config value for keys " + keys + " detected, 
but not yet applied.");
@@ -178,7 +248,7 @@ public abstract class BaseDynamicValue<T> implements 
DynamicValue<T>, Serializab
     protected void publishChangeEvent(T oldValue, T newValue) {
         PropertyChangeEvent evt = new PropertyChangeEvent(getOwner(), 
getPropertyName(),oldValue, newValue);
         synchronized (listeners){
-            listeners.parallelStream().forEach(l -> {
+            listeners.forEach(l -> {
                 try{
                     l.propertyChange(evt);
                 }catch(Exception e){
@@ -188,16 +258,56 @@ public abstract class BaseDynamicValue<T> implements 
DynamicValue<T>, Serializab
         }
     }
 
+    /**
+     * Allows to customize type conversion if needed, e.g. based on some 
annotations defined.
+     * @return the custom converter, which replaces the default converters, ot 
null.
+     */
+    protected PropertyConverter<T> getCustomConverter(){
+        return null;
+    }
+
     @Override
     public T evaluateValue() {
-        Configuration config = getConfiguration();
-        for(String key:getKeys()){
-            T val = config.getOrDefault(key, targetType, null);
-           if(val!=null){
-               return val;
-           }
+        T value = null;
+        List<PropertyConverter<T>> converters = new ArrayList<>();
+        if (this.getCustomConverter() != null) {
+            converters.add(this.getCustomConverter());
         }
-        return null;
+        
converters.addAll(getConfiguration().getContext().getPropertyConverters(targetType));
+
+        for (String key : keys) {
+            ConversionContext ctx = new ConversionContext.Builder(key, 
targetType).build();
+            String stringVal = getConfiguration().getOrDefault(key, 
String.class, null);
+            if(stringVal!=null) {
+                if(String.class.equals(targetType.getType())){
+                    value = (T)stringVal;
+                }
+                for(PropertyConverter<T> conv:converters){
+                    try{
+                        value = conv.convert(stringVal, ctx);
+                        if(value!=null){
+                            break;
+                        }
+                    }catch(Exception e){
+                        LOG.warning("failed to convert: " + ctx);
+                    }
+                }
+            }
+        }
+        if(value == null && defaultValue!=null){
+            ConversionContext ctx = new 
ConversionContext.Builder("<defaultValue>", targetType).build();
+            for(PropertyConverter<T> conv:converters){
+                try{
+                    value = conv.convert(defaultValue, ctx);
+                    if(value!=null){
+                        break;
+                    }
+                }catch(Exception e){
+                    LOG.warning("failed to convert: " + ctx);
+                }
+            }
+        }
+        return value;
     }
 
     @Override
@@ -217,6 +327,7 @@ public abstract class BaseDynamicValue<T> implements 
DynamicValue<T>, Serializab
      * @throws org.apache.tamaya.ConfigException if there is no value present
      * @see DynamicValue#isPresent()
      */
+    @Override
     public T commitAndGet() {
         commit();
         return get();
@@ -227,6 +338,7 @@ public abstract class BaseDynamicValue<T> implements 
DynamicValue<T>, Serializab
      *
      * @return {@code true} if there is a value present, otherwise {@code 
false}
      */
+    @Override
     public boolean isPresent() {
         return get() != null;
     }
@@ -239,6 +351,7 @@ public abstract class BaseDynamicValue<T> implements 
DynamicValue<T>, Serializab
      *              be null
      * @return the value, if present, otherwise {@code other}
      */
+    @Override
     public T orElse(T other) {
         T value = get();
         if (value == null) {
@@ -257,6 +370,7 @@ public abstract class BaseDynamicValue<T> implements 
DynamicValue<T>, Serializab
      * @throws NullPointerException if value is not present and {@code other} 
is
      *                              null
      */
+    @Override
     public T orElseGet(Supplier<? extends T> other) {
         T value = get();
         if (value == null) {
@@ -281,6 +395,7 @@ public abstract class BaseDynamicValue<T> implements 
DynamicValue<T>, Serializab
      * @throws NullPointerException if no value is present and
      *                              {@code exceptionSupplier} is null
      */
+    @Override
     public <X extends Throwable> T orElseThrow(Supplier<? extends X> 
exceptionSupplier) throws X {
         T value = get();
         if (value == null) {
@@ -289,4 +404,83 @@ public abstract class BaseDynamicValue<T> implements 
DynamicValue<T>, Serializab
         return value;
     }
 
+
+
+    /**
+     * Simple helper that allows keeping the listeners registered as weak 
references, hereby avoiding any
+     * memory leaks.
+     *
+     * @param <I> the type
+     */
+    private class WeakList<I> {
+        final List<WeakReference<I>> refs = new LinkedList<>();
+
+        boolean contains(I item){
+            for(WeakReference<I> t:refs){
+                if(item.equals(t.get())){
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        void forEach(Consumer<I> consumer){
+            refs.parallelStream().forEach(ref -> {
+                I t = ref.get();
+                if(t!=null){
+                    consumer.accept(t);
+                }
+            });
+        }
+
+        /**
+         * Adds a new instance.
+         *
+         * @param t the new instance, not null.
+         */
+        void add(I t) {
+            refs.add(new WeakReference<>(t));
+        }
+
+        /**
+         * Removes a instance.
+         *
+         * @param t the instance to be removed.
+         */
+        void remove(I t) {
+            synchronized (refs) {
+                for (Iterator<WeakReference<I>> iterator = refs.iterator(); 
iterator.hasNext(); ) {
+                    WeakReference<I> ref = iterator.next();
+                    I instance = ref.get();
+                    if (instance == null || instance == t) {
+                        iterator.remove();
+                        break;
+                    }
+                }
+            }
+        }
+
+
+        /**
+         * Access a list (copy) of the current instances that were not 
discarded by the GC.
+         *
+         * @return the list of accessible items.
+         */
+        public List<I> get() {
+            synchronized (refs) {
+                List<I> res = new ArrayList<>();
+                for (Iterator<WeakReference<I>> iterator = refs.iterator(); 
iterator.hasNext(); ) {
+                    WeakReference<I> ref = iterator.next();
+                    I instance = ref.get();
+                    if (instance == null) {
+                        iterator.remove();
+                    } else {
+                        res.add(instance);
+                    }
+                }
+                return res;
+            }
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/7c071caf/modules/injection/injection-api/src/test/java/org/apache/tamaya/inject/spi/BaseDynamicValueTest.java
----------------------------------------------------------------------
diff --git 
a/modules/injection/injection-api/src/test/java/org/apache/tamaya/inject/spi/BaseDynamicValueTest.java
 
b/modules/injection/injection-api/src/test/java/org/apache/tamaya/inject/spi/BaseDynamicValueTest.java
index 3f8720e..bb568a5 100644
--- 
a/modules/injection/injection-api/src/test/java/org/apache/tamaya/inject/spi/BaseDynamicValueTest.java
+++ 
b/modules/injection/injection-api/src/test/java/org/apache/tamaya/inject/spi/BaseDynamicValueTest.java
@@ -79,7 +79,7 @@ public class BaseDynamicValueTest {
     private static final class MyDynamicValue extends BaseDynamicValue{
 
         public MyDynamicValue(String... keys){
-            super(TypeLiteral.of(String.class), Arrays.asList(keys));
+            super(null, "test", TypeLiteral.of(String.class), 
Arrays.asList(keys));
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/7c071caf/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/ConfigTemplateInvocationHandler.java
----------------------------------------------------------------------
diff --git 
a/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/ConfigTemplateInvocationHandler.java
 
b/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/ConfigTemplateInvocationHandler.java
index 5d634e1..fd9f7be 100644
--- 
a/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/ConfigTemplateInvocationHandler.java
+++ 
b/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/ConfigTemplateInvocationHandler.java
@@ -64,7 +64,7 @@ public final class ConfigTemplateInvocationHandler implements 
InvocationHandler
             return config;
         }
         if (method.getReturnType() == DynamicValue.class) {
-            return DefaultDynamicValue.of(method, config);
+            return DefaultDynamicValue.of(proxy, method, config);
         }
         String[] retKey = new String[1];
         String configValue = InjectionHelper.getConfigValue(method, retKey, 
config);

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/7c071caf/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/ConfiguredFieldImpl.java
----------------------------------------------------------------------
diff --git 
a/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/ConfiguredFieldImpl.java
 
b/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/ConfiguredFieldImpl.java
index 7ccaecc..e39b070 100644
--- 
a/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/ConfiguredFieldImpl.java
+++ 
b/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/ConfiguredFieldImpl.java
@@ -82,11 +82,11 @@ public class ConfiguredFieldImpl implements ConfiguredField{
                 @Override
                 public Object run() throws Exception {
                     annotatedField.setAccessible(true);
+                    annotatedField.set(target,
+                            DefaultDynamicValue.of(target, annotatedField, 
ConfigurationProvider.getConfiguration()));
                     return annotatedField;
                 }
             });
-            annotatedField.set(target,
-                    DefaultDynamicValue.of(annotatedField, 
ConfigurationProvider.getConfiguration()));
         } catch (Exception e) {
             throw new ConfigException("Failed to annotation configured field: 
" + this.annotatedField.getDeclaringClass()
                     .getName() + '.' + annotatedField.getName(), e);
@@ -118,12 +118,12 @@ public class ConfiguredFieldImpl implements 
ConfiguredField{
                 @Override
                 public Object run() throws Exception {
                     annotatedField.setAccessible(true);
+                    if(value!=null) {
+                        annotatedField.set(target, value);
+                    }
                     return annotatedField;
                 }
             });
-            if(value!=null) {
-                annotatedField.set(target, value);
-            }
         } catch (Exception e) {
             throw new ConfigException("Failed to evaluate annotated field: " + 
this.annotatedField.getDeclaringClass()
                     .getName() + '.' + annotatedField.getName(), e);

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/7c071caf/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/DefaultDynamicValue.java
----------------------------------------------------------------------
diff --git 
a/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/DefaultDynamicValue.java
 
b/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/DefaultDynamicValue.java
index 621399d..ac7e977 100644
--- 
a/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/DefaultDynamicValue.java
+++ 
b/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/DefaultDynamicValue.java
@@ -67,51 +67,21 @@ final class DefaultDynamicValue<T> extends 
BaseDynamicValue<T> {
     private static final long serialVersionUID = -2071172847144537443L;
 
     /**
-     * The property name of the entry.
-     */
-    private final String propertyName;
-    /**
-     * The keys to be resolved.
-     */
-    private final String[] keys;
-    /**
      * Back reference to the base configuration instance. This reference is 
used reevaluate the given property and
      * compare the result with the previous value after a configuration change 
was triggered.
      */
     private final Configuration configuration;
     /**
-     * The target type of the property used to lookup a matching {@link 
PropertyConverter}.
-     * If null, {@code propertyConverter} is set and used instead.
-     */
-    private final TypeLiteral<T> targetType;
-    /**
      * The property converter to be applied, may be null. In the ladder case 
targetType is not null.
      */
     private final PropertyConverter<T> propertyConverter;
-    /**
-     * Policy that defines how new values are applied, be default it is 
applied initially once, but never updated
-     * anymore.
-     */
-    private UpdatePolicy updatePolicy;
+
     /**
      * Load policy.
      */
     private final LoadPolicy loadPolicy;
 
     /**
-     * The current value, never null.
-     */
-    private transient T value;
-    /**
-     * The new value, or null.
-     */
-    private transient Object[] newValue;
-    /**
-     * List of listeners that listen for changes.
-     */
-    private transient WeakList<PropertyChangeListener> listeners;
-
-    /**
      * Constructor.
      *
      * @param propertyName      the name of the fields' property/method.
@@ -120,35 +90,33 @@ final class DefaultDynamicValue<T> extends 
BaseDynamicValue<T> {
      * @param targetType        the target type, not null.
      * @param propertyConverter the optional converter to be used.
      */
-    private DefaultDynamicValue(String propertyName, Configuration 
configuration, TypeLiteral<T> targetType,
+    private DefaultDynamicValue(Object owner, String propertyName, 
Configuration configuration, TypeLiteral<T> targetType,
                                 PropertyConverter<T> propertyConverter, 
List<String> keys, LoadPolicy loadPolicy,
                                 UpdatePolicy updatePolicy) {
-        this.propertyName = Objects.requireNonNull(propertyName);
-        this.keys = keys.toArray(new String[keys.size()]);
+        super(owner, propertyName, targetType, keys);
         this.configuration = Objects.requireNonNull(configuration);
         this.propertyConverter = propertyConverter;
-        this.targetType = targetType;
         this.loadPolicy = Objects.requireNonNull(loadPolicy);
-        this.updatePolicy = Objects.requireNonNull(updatePolicy);
+        setUpdatePolicy(updatePolicy);
         if(loadPolicy == LoadPolicy.INITIAL){
             this.value = evaluateValue();
         }
     }
 
-    public static DynamicValue<?> of(Field annotatedField, Configuration 
configuration) {
-        return of(annotatedField, configuration, LoadPolicy.ALWAYS, 
UpdatePolicy.IMMEDIATE);
+    public static DynamicValue<?> of(Object owner, Field annotatedField, 
Configuration configuration) {
+        return of(owner, annotatedField, configuration, LoadPolicy.ALWAYS, 
UpdatePolicy.IMMEDIATE);
     }
 
-    public static DynamicValue<?> of(Field annotatedField, Configuration 
configuration, LoadPolicy loadPolicy) {
-        return of(annotatedField, configuration, loadPolicy, 
UpdatePolicy.IMMEDIATE);
+    public static DynamicValue<?> of(Object owner, Field annotatedField, 
Configuration configuration, LoadPolicy loadPolicy) {
+        return of(owner, annotatedField, configuration, loadPolicy, 
UpdatePolicy.IMMEDIATE);
     }
 
-    public static DynamicValue<?> of(Field annotatedField, Configuration 
configuration, UpdatePolicy updatePolicy) {
-        return of(annotatedField, configuration, LoadPolicy.ALWAYS, 
updatePolicy);
+    public static DynamicValue<?> of(Object owner, Field annotatedField, 
Configuration configuration, UpdatePolicy updatePolicy) {
+        return of(owner, annotatedField, configuration, LoadPolicy.ALWAYS, 
updatePolicy);
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
-       public static DynamicValue<?> of(Field annotatedField, Configuration 
configuration, LoadPolicy loadPolicy, UpdatePolicy updatePolicy) {
+       public static DynamicValue<?> of(Object owner, Field annotatedField, 
Configuration configuration, LoadPolicy loadPolicy, UpdatePolicy updatePolicy) {
         // Check for adapter/filter
         Type targetType = annotatedField.getGenericType();
         if (targetType == null) {
@@ -176,24 +144,24 @@ final class DefaultDynamicValue<T> extends 
BaseDynamicValue<T> {
             }
         }
         List<String> keys = InjectionUtils.getKeys(annotatedField);
-        return new DefaultDynamicValue(annotatedField.getName(), configuration,
+        return new DefaultDynamicValue(owner, annotatedField.getName(), 
configuration,
                 TypeLiteral.of(targetType), propertyConverter, keys, 
loadPolicy, updatePolicy);
     }
 
-    public static DynamicValue<?> of(Method method, Configuration 
configuration) {
-        return of(method, configuration, LoadPolicy.ALWAYS, 
UpdatePolicy.IMMEDIATE);
+    public static DynamicValue<?> of(Object owner, Method method, 
Configuration configuration) {
+        return of(owner, method, configuration, LoadPolicy.ALWAYS, 
UpdatePolicy.IMMEDIATE);
     }
 
-    public static DynamicValue<?> of(Method method, Configuration 
configuration, UpdatePolicy updatePolicy) {
-        return of(method, configuration, LoadPolicy.ALWAYS, updatePolicy);
+    public static DynamicValue<?> of(Object owner, Method method, 
Configuration configuration, UpdatePolicy updatePolicy) {
+        return of(owner, method, configuration, LoadPolicy.ALWAYS, 
updatePolicy);
     }
 
-    public static DynamicValue<?> of(Method method, Configuration 
configuration, LoadPolicy loadPolicy) {
-        return of(method, configuration, loadPolicy, UpdatePolicy.IMMEDIATE);
+    public static DynamicValue<?> of(Object owner, Method method, 
Configuration configuration, LoadPolicy loadPolicy) {
+        return of(owner, method, configuration, loadPolicy, 
UpdatePolicy.IMMEDIATE);
     }
 
     @SuppressWarnings("unchecked")
-       public static DynamicValue<?> of(Method method, Configuration 
configuration, LoadPolicy loadPolicy, UpdatePolicy updatePolicy) {
+       public static DynamicValue<?> of(Object owner, Method method, 
Configuration configuration, LoadPolicy loadPolicy, UpdatePolicy updatePolicy) {
         // Check for adapter/filter
         Type targetType = method.getGenericReturnType();
         if (targetType == null) {
@@ -220,82 +188,18 @@ final class DefaultDynamicValue<T> extends 
BaseDynamicValue<T> {
                         + '.' + method.getName(), e);
             }
         }
-        return new DefaultDynamicValue<>(method.getName(),
+        return new DefaultDynamicValue<>(owner, method.getName(),
                 configuration, TypeLiteral.of(targetType), propertyConverter, 
InjectionUtils.getKeys(method),
                 loadPolicy, updatePolicy);
     }
 
-
-    /**
-     * Commits a new value that has not been committed yet, make it the new 
value of the instance. On change any
-     * registered listeners will be triggered.
-     */
-    @SuppressWarnings("unchecked")
-       public void commit() {
-        T oldValue = value;
-        value = newValue==null?null:(T)newValue[0];
-        newValue = null;
-        informListeners(oldValue, value);
-    }
-
-    private void informListeners(T value, T newValue) {
-        synchronized (this) {
-            PropertyChangeEvent evt = new PropertyChangeEvent(this, 
propertyName, value,
-                    newValue);
-            if (listeners != null) {
-                for (PropertyChangeListener consumer : listeners.get()) {
-                    consumer.propertyChange(evt);
-                }
-            }
-        }
-    }
-
-    /**
-     * Discards a new value that was published. No listeners will be informed.
-     */
-    public void discard() {
-        newValue = null;
-    }
-
-    /**
-     * Access the {@link UpdatePolicy} used for updating this value.
-     *
-     * @return the update policy, never null.
-     */
-    public UpdatePolicy getUpdatePolicy() {
-        return updatePolicy;
-    }
-
-    /**
-     * Sets a new {@link UpdatePolicy}.
-     *
-     * @param updatePolicy the new policy, not null.
-     */
-    public void setUpdatePolicy(UpdatePolicy updatePolicy) {
-        this.updatePolicy = Objects.requireNonNull(updatePolicy);
-    }
-
-    /**
-     * Add a listener to be called as weak reference, when this value has been 
changed.
-     *
-     * @param l the listener, not null
-     */
-    public void addListener(PropertyChangeListener l) {
-        if (listeners == null) {
-            listeners = new WeakList<>();
-        }
-        listeners.add(l);
+    protected PropertyConverter getCustomConverter(){
+        return this.propertyConverter;
     }
 
-    /**
-     * Removes a listener to be called, when this value has been changed.
-     *
-     * @param l the listener to be removed, not null
-     */
-    public void removeListener(PropertyChangeListener l) {
-        if (listeners != null) {
-            listeners.remove(l);
-        }
+    @Override
+    protected Configuration getConfiguration() {
+        return configuration;
     }
 
     /**
@@ -314,17 +218,17 @@ final class DefaultDynamicValue<T> extends 
BaseDynamicValue<T> {
                 this.value = newLocalValue;
             }
             if(!Objects.equals(this.value, newLocalValue)){
-                switch (updatePolicy){
+                switch (getUpdatePolicy()){
                     case IMMEDEATE:
                     case IMMEDIATE:
                         commit();
                         break;
                     case EXPLCIT:
                     case EXPLICIT:
-                        this.newValue = new Object[]{newLocalValue};
+                        this.newValue = newLocalValue;
                         break;
                     case LOG_ONLY:
-                        informListeners(this.value, newLocalValue);
+                        publishChangeEvent(this.value, newLocalValue);
                         this.newValue = null;
                         break;
                     case NEVER:
@@ -355,10 +259,10 @@ final class DefaultDynamicValue<T> extends 
BaseDynamicValue<T> {
         if (Objects.equals(newValue, this.value)) {
             return false;
         }
-        switch (this.updatePolicy) {
+        switch (getUpdatePolicy()) {
             case LOG_ONLY:
                 Logger.getLogger(getClass().getName()).info("Discard change on 
" + this + ", newValue=" + newValue);
-                informListeners(value, newValue);
+                publishChangeEvent(value, newValue);
                 this.newValue = null;
                 break;
             case NEVER:
@@ -367,7 +271,7 @@ final class DefaultDynamicValue<T> extends 
BaseDynamicValue<T> {
             case EXPLCIT:
             case IMMEDEATE:
             default:
-                this.newValue = new Object[]{newValue};
+                this.newValue = newValue;
                 commit();
                 break;
         }
@@ -375,60 +279,16 @@ final class DefaultDynamicValue<T> extends 
BaseDynamicValue<T> {
     }
 
     /**
-     * Evaluates the current value dynamically from the underlying 
configuration.
-     *
-     * @return the current actual value, or null.
-     */
-    public T evaluateValue() {
-        T value = null;
-
-        for (String key : keys) {
-            ConversionContext ctx = new ConversionContext.Builder(key, 
targetType).build();
-            if (propertyConverter == null) {
-                value = configuration.get(key, targetType);
-            } else {
-                String source = configuration.get(key);
-                value = propertyConverter.convert(source, ctx);
-            }
-
-            if (value != null) {
-                break;
-            }
-        }
-
-        return value;
-    }
-
-    /**
      * Access a new value that has not yet been committed.
      *
      * @return the uncommitted new value, or null.
      */
     public T getNewValue() {
         @SuppressWarnings("unchecked")
-               T nv = newValue==null?null:(T)newValue[0];
+               T nv = newValue==null?null:(T)newValue;
         return nv;
     }
 
-    @Override
-    public T orElseGet(Supplier<? extends T> other) {
-        T t = evaluateValue();
-        if(t==null){
-            return other.get();
-        }
-        return t;
-    }
-
-    @Override
-    public <X extends Throwable> T orElseThrow(Supplier<? extends X> 
exceptionSupplier) throws X {
-        T t = evaluateValue();
-        if(t==null){
-            throw exceptionSupplier.get();
-        }
-        return t;
-    }
-
-
     /**
      * Serialization implementation that strips away the non serializable 
Optional part.
      *
@@ -449,71 +309,11 @@ final class DefaultDynamicValue<T> extends 
BaseDynamicValue<T> {
      */
     @SuppressWarnings("unchecked")
        private void readObject(ObjectInputStream ois) throws IOException, 
ClassNotFoundException {
-        this.updatePolicy = (UpdatePolicy) ois.readObject();
+        setUpdatePolicy((UpdatePolicy)ois.readObject());
         if (isPresent()) {
             this.value = (T) ois.readObject();
         }
         newValue = null;
     }
 
-
-    /**
-     * Simple helper that allows keeping the listeners registered as weak 
references, hereby avoiding any
-     * memory leaks.
-     *
-     * @param <I> the type
-     */
-    private class WeakList<I> {
-        final List<WeakReference<I>> refs = new LinkedList<>();
-
-        /**
-         * Adds a new instance.
-         *
-         * @param t the new instance, not null.
-         */
-        void add(I t) {
-            refs.add(new WeakReference<>(t));
-        }
-
-        /**
-         * Removes a instance.
-         *
-         * @param t the instance to be removed.
-         */
-        void remove(I t) {
-            synchronized (refs) {
-                for (Iterator<WeakReference<I>> iterator = refs.iterator(); 
iterator.hasNext(); ) {
-                    WeakReference<I> ref = iterator.next();
-                    I instance = ref.get();
-                    if (instance == null || instance == t) {
-                        iterator.remove();
-                        break;
-                    }
-                }
-            }
-        }
-
-
-        /**
-         * Access a list (copy) of the current instances that were not 
discarded by the GC.
-         *
-         * @return the list of accessible items.
-         */
-        public List<I> get() {
-            synchronized (refs) {
-                List<I> res = new ArrayList<>();
-                for (Iterator<WeakReference<I>> iterator = refs.iterator(); 
iterator.hasNext(); ) {
-                    WeakReference<I> ref = iterator.next();
-                    I instance = ref.get();
-                    if (instance == null) {
-                        iterator.remove();
-                    } else {
-                        res.add(instance);
-                    }
-                }
-                return res;
-            }
-        }
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/7c071caf/modules/injection/standalone/src/test/java/org/apache/tamaya/inject/internal/DefaultDynamicValueTest.java
----------------------------------------------------------------------
diff --git 
a/modules/injection/standalone/src/test/java/org/apache/tamaya/inject/internal/DefaultDynamicValueTest.java
 
b/modules/injection/standalone/src/test/java/org/apache/tamaya/inject/internal/DefaultDynamicValueTest.java
index 3ee690d..a071584 100644
--- 
a/modules/injection/standalone/src/test/java/org/apache/tamaya/inject/internal/DefaultDynamicValueTest.java
+++ 
b/modules/injection/standalone/src/test/java/org/apache/tamaya/inject/internal/DefaultDynamicValueTest.java
@@ -95,14 +95,14 @@ public class DefaultDynamicValueTest {
 
     @Test
     public void testOf_Field() throws Exception {
-        DynamicValue val = 
DefaultDynamicValue.of(getClass().getDeclaredField("myValue"),
+        DynamicValue val = DefaultDynamicValue.of(this, 
getClass().getDeclaredField("myValue"),
                 ConfigurationProvider.getConfiguration());
         assertNotNull(val);
     }
 
     @Test
     public void testOf_Method() throws Exception {
-        DynamicValue val = 
DefaultDynamicValue.of(getClass().getDeclaredMethod("setterMethod", 
String.class),
+        DynamicValue val = DefaultDynamicValue.of(this, 
getClass().getDeclaredMethod("setterMethod", String.class),
                 config);
         assertNotNull(val);
     }
@@ -110,7 +110,7 @@ public class DefaultDynamicValueTest {
     @Test
     public void testCommitAndGet() throws Exception {
         properties.put("a",PropertyValue.of("a","aValue","test"));
-        DynamicValue val = 
DefaultDynamicValue.of(getClass().getDeclaredField("myValue"),
+        DynamicValue val = DefaultDynamicValue.of(this, 
getClass().getDeclaredField("myValue"),
                 config);
         assertNotNull(val);
         assertEquals("aValue",val.evaluateValue());
@@ -119,7 +119,7 @@ public class DefaultDynamicValueTest {
     @Test
     public void testCommitAndGets() throws Exception {
         properties.put("a",PropertyValue.of("a","aValue","test"));
-        DynamicValue val = 
DefaultDynamicValue.of(getClass().getDeclaredField("myValue"),
+        DynamicValue val = DefaultDynamicValue.of(this, 
getClass().getDeclaredField("myValue"),
                 config);
         val.setUpdatePolicy(UpdatePolicy.EXPLICIT);
         assertNotNull(val);
@@ -134,7 +134,7 @@ public class DefaultDynamicValueTest {
     @Test
     public void testCommit() throws Exception {
         properties.put("a",PropertyValue.of("a","aValue","test"));
-        DynamicValue val = 
DefaultDynamicValue.of(getClass().getDeclaredField("myValue"),
+        DynamicValue val = DefaultDynamicValue.of(this, 
getClass().getDeclaredField("myValue"),
                 config);
         val.setUpdatePolicy(UpdatePolicy.EXPLICIT);
         assertNotNull(val);
@@ -150,7 +150,7 @@ public class DefaultDynamicValueTest {
 
     @Test
     public void testGetSetUpdatePolicy() throws Exception {
-        DynamicValue val = 
DefaultDynamicValue.of(getClass().getDeclaredField("myValue"),
+        DynamicValue val = DefaultDynamicValue.of(this, 
getClass().getDeclaredField("myValue"),
                 config);
         for(UpdatePolicy pol: UpdatePolicy.values()) {
             val.setUpdatePolicy(pol);
@@ -161,7 +161,7 @@ public class DefaultDynamicValueTest {
     @Test
     public void testAddRemoveListener() throws Exception {
         properties.put("a",PropertyValue.of("a","aValue","test"));
-        DynamicValue val = 
DefaultDynamicValue.of(getClass().getDeclaredField("myValue"),
+        DynamicValue val = DefaultDynamicValue.of(this, 
getClass().getDeclaredField("myValue"),
                 config);
         val.setUpdatePolicy(UpdatePolicy.IMMEDIATE);
         val.addListener(consumer);
@@ -180,7 +180,7 @@ public class DefaultDynamicValueTest {
     @Test
     public void testGet() throws Exception {
         properties.put("a",PropertyValue.of("a","aValue","test"));
-        DynamicValue val = 
DefaultDynamicValue.of(getClass().getDeclaredField("myValue"),
+        DynamicValue val = DefaultDynamicValue.of(this, 
getClass().getDeclaredField("myValue"),
                 config);
         val.setUpdatePolicy(UpdatePolicy.IMMEDIATE);
         properties.put("a",PropertyValue.of("a","aValue2","test"));
@@ -191,7 +191,7 @@ public class DefaultDynamicValueTest {
     @Test
     public void testUpdateValue() throws Exception {
         properties.put("a",PropertyValue.of("a","aValue","test"));
-        DynamicValue val = 
DefaultDynamicValue.of(getClass().getDeclaredField("myValue"),
+        DynamicValue val = DefaultDynamicValue.of(this, 
getClass().getDeclaredField("myValue"),
                 config);
         val.setUpdatePolicy(UpdatePolicy.EXPLICIT);
         assertNotNull(val.get());
@@ -206,7 +206,7 @@ public class DefaultDynamicValueTest {
     @Test
     public void testEvaluateValue() throws Exception {
         properties.put("a",PropertyValue.of("a","aValue","test"));
-        DynamicValue val = 
DefaultDynamicValue.of(getClass().getDeclaredField("myValue"),
+        DynamicValue val = DefaultDynamicValue.of(this, 
getClass().getDeclaredField("myValue"),
                 config);
         val.setUpdatePolicy(UpdatePolicy.EXPLICIT);
         assertNotNull(val.get());
@@ -218,7 +218,7 @@ public class DefaultDynamicValueTest {
     @Test
     public void testGetNewValue() throws Exception {
         properties.put("a",PropertyValue.of("a","aValue","test"));
-        DynamicValue val = 
DefaultDynamicValue.of(getClass().getDeclaredField("myValue"),
+        DynamicValue val = DefaultDynamicValue.of(this, 
getClass().getDeclaredField("myValue"),
                 config);
         val.setUpdatePolicy(UpdatePolicy.EXPLICIT);
         val.get();
@@ -228,6 +228,7 @@ public class DefaultDynamicValueTest {
         assertNotNull(val.getNewValue());
         assertEquals("aValue2", val.getNewValue());
         val.commit();
+        assertEquals("aValue2", val.get());
         assertNull(val.getNewValue());
     }
 
@@ -239,7 +240,7 @@ public class DefaultDynamicValueTest {
     @Test
     public void testIfPresent() throws Exception {
         properties.put("a",PropertyValue.of("a","aValue","test"));
-        DynamicValue val = 
DefaultDynamicValue.of(getClass().getDeclaredField("myValue"),
+        DynamicValue val = DefaultDynamicValue.of(this, 
getClass().getDeclaredField("myValue"),
                 config);
         val.setUpdatePolicy(UpdatePolicy.IMMEDIATE);
         assertTrue(val.isPresent());
@@ -250,7 +251,7 @@ public class DefaultDynamicValueTest {
 
     @Test
     public void testOrElse() throws Exception {
-        DynamicValue val = 
DefaultDynamicValue.of(getClass().getDeclaredField("myValue"),
+        DynamicValue val = DefaultDynamicValue.of(this, 
getClass().getDeclaredField("myValue"),
                 config);
         val.setUpdatePolicy(UpdatePolicy.IMMEDIATE);
         assertEquals("bla", val.orElse("bla"));

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/7c071caf/modules/spring/src/main/java/org/apache/tamaya/integration/spring/SpringConfigInjectionPostProcessor.java
----------------------------------------------------------------------
diff --git 
a/modules/spring/src/main/java/org/apache/tamaya/integration/spring/SpringConfigInjectionPostProcessor.java
 
b/modules/spring/src/main/java/org/apache/tamaya/integration/spring/SpringConfigInjectionPostProcessor.java
index e25b230..0bcc5c3 100644
--- 
a/modules/spring/src/main/java/org/apache/tamaya/integration/spring/SpringConfigInjectionPostProcessor.java
+++ 
b/modules/spring/src/main/java/org/apache/tamaya/integration/spring/SpringConfigInjectionPostProcessor.java
@@ -21,8 +21,13 @@ package org.apache.tamaya.integration.spring;
 import org.apache.tamaya.inject.ConfigurationInjection;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.cglib.core.ReflectUtils;
+import org.springframework.cglib.proxy.Enhancer;
 import org.springframework.stereotype.Component;
 
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+
 /**
  * PostProcessor that performs injection of configured values using Tamaya 
{@link ConfigurationInjection}.
  */

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/7c071caf/modules/spring/src/main/java/org/apache/tamaya/integration/spring/TamayaSpringConfig.java
----------------------------------------------------------------------
diff --git 
a/modules/spring/src/main/java/org/apache/tamaya/integration/spring/TamayaSpringConfig.java
 
b/modules/spring/src/main/java/org/apache/tamaya/integration/spring/TamayaSpringConfig.java
index cacab20..7c9966b 100644
--- 
a/modules/spring/src/main/java/org/apache/tamaya/integration/spring/TamayaSpringConfig.java
+++ 
b/modules/spring/src/main/java/org/apache/tamaya/integration/spring/TamayaSpringConfig.java
@@ -53,4 +53,9 @@ public class TamayaSpringConfig {
         cfgBean.setPropertySources(sources);
         return cfgBean;
     }
+
+    @Bean
+    public static SpringConfigInjectionPostProcessor 
tamayaConfigPostProcessor(){
+        return new SpringConfigInjectionPostProcessor();
+    }
  }
\ No newline at end of file

Reply via email to