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
