You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by st...@apache.org on 2017/08/08 10:55:56 UTC

svn commit: r1804397 - in /geronimo/components/config/trunk: ./ impl/ impl/src/main/java/org/apache/geronimo/config/cdi/ impl/src/test/java/org/apache/geronimo/config/test/internal/

Author: struberg
Date: Tue Aug  8 10:55:56 2017
New Revision: 1804397

URL: http://svn.apache.org/viewvc?rev=1804397&view=rev
Log:
GERONIMO-6577 move back to a more dynamic version

The goal of r1800748 to calculate all information upfront could not be achieved
so we move back to the old version

Modified:
    geronimo/components/config/trunk/impl/debug-suite.xml
    geronimo/components/config/trunk/impl/pom.xml
    geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
    geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
    geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
    geronimo/components/config/trunk/pom.xml

Modified: geronimo/components/config/trunk/impl/debug-suite.xml
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/debug-suite.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
==============================================================================
--- geronimo/components/config/trunk/impl/debug-suite.xml (original)
+++ geronimo/components/config/trunk/impl/debug-suite.xml Tue Aug  8 10:55:56 2017
@@ -24,7 +24,7 @@
     <classes>
         <!-- Issues in the spec -->
         <!-- CDI-437 -->
-        <class name="org.eclipse.microprofile.config.tck.CdiOptionalInjectionTest">
+        <class name="org.eclipse.microprofile.config.tck.CDIPlainInjectionTest">
             <methods>
                 <include name=".*"/>
             </methods>

Modified: geronimo/components/config/trunk/impl/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/pom.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
==============================================================================
--- geronimo/components/config/trunk/impl/pom.xml (original)
+++ geronimo/components/config/trunk/impl/pom.xml Tue Aug  8 10:55:56 2017
@@ -27,7 +27,6 @@
     </parent>
 
     <artifactId>geronimo-config-impl</artifactId>
-    <name>Geronimo Microprofile Configuration :: Implementation</name>
 
     <dependencyManagement>
         <dependencies>

Modified: geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java?rev=1804397&r1=1804396&r2=1804397&view=diff
==============================================================================
--- geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java (original)
+++ geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java Tue Aug  8 10:55:56 2017
@@ -16,54 +16,38 @@
  */
 package org.apache.geronimo.config.cdi;
 
-import org.apache.geronimo.config.ConfigImpl;
-import org.eclipse.microprofile.config.Config;
-import org.eclipse.microprofile.config.inject.ConfigProperty;
-import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
 
-import javax.enterprise.context.spi.CreationalContext;
 import javax.enterprise.event.Observes;
 import javax.enterprise.inject.spi.AfterBeanDiscovery;
 import javax.enterprise.inject.spi.AfterDeploymentValidation;
-import javax.enterprise.inject.spi.AnnotatedMember;
-import javax.enterprise.inject.spi.AnnotatedType;
 import javax.enterprise.inject.spi.BeanManager;
-import javax.enterprise.inject.spi.BeforeBeanDiscovery;
 import javax.enterprise.inject.spi.BeforeShutdown;
+import javax.enterprise.inject.spi.DeploymentException;
 import javax.enterprise.inject.spi.Extension;
 import javax.enterprise.inject.spi.InjectionPoint;
 import javax.enterprise.inject.spi.ProcessInjectionPoint;
 import javax.inject.Provider;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.BiFunction;
-import java.util.stream.Stream;
 
-import static java.util.function.Function.identity;
-import static java.util.stream.Collectors.toMap;
-import static org.eclipse.microprofile.config.ConfigProvider.getConfig;
+import org.apache.geronimo.config.DefaultConfigProvider;
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
 
 /**
  * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
  */
 public class ConfigExtension implements Extension {
-    private static final Object NULL = new Object();
-
     private Config config;
-    private ConfigProviderResolver resolver;
 
-    private Set<Injection> injections = new HashSet<>();
-    private List<Throwable> deploymentProblems = new ArrayList<>();
     private static final Map<Type, Type> REPLACED_TYPES = new HashMap<>();
 
     static {
@@ -74,336 +58,65 @@ public class ConfigExtension implements
         REPLACED_TYPES.put(boolean.class, Boolean.class);
     }
 
-    void init(@Observes final BeforeBeanDiscovery beforeBeanDiscovery, final BeanManager bm) {
-        resolver = ConfigProviderResolver.instance();
-        config = getConfig();
-    }
+    private Set<InjectionPoint> injectionPoints = new HashSet<>();
+
 
     public void collectConfigProducer(@Observes ProcessInjectionPoint<?, ?> pip) {
-        final InjectionPoint injectionPoint = pip.getInjectionPoint();
-        final ConfigProperty configProperty = injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class);
+        ConfigProperty configProperty = pip.getInjectionPoint().getAnnotated().getAnnotation(ConfigProperty.class);
         if (configProperty != null) {
-            Type replacedType = REPLACED_TYPES.getOrDefault(injectionPoint.getType(), injectionPoint.getType());
-            Injection injection = new Injection(replacedType);
-            final String key = getConfigKey(injectionPoint, configProperty);
-            final boolean defaultUnset = isDefaultUnset(configProperty.defaultValue());
-            if (!injections.add(injection)) {
-                final Injection ref = injection;
-                injection = injections.stream().filter(i -> i.equals(ref)).findFirst().get();
-            }
-            injection.keys.add(key);
-            injection.defaultValues.add(configProperty.defaultValue());
-
-            final ConfigImpl configImpl = unwrapConfig();
-
-            // what about lazy runtime lookup, not consistent with tck and system prop usage, for now assume optional=optional ;)
-            boolean hasValue = true;
-            if (defaultUnset) { // value validation
-                if (ParameterizedType.class.isInstance(injection.type)) {
-                    final ParameterizedType pt = ParameterizedType.class.cast(injection.type);
-                    if (pt.getRawType() != Optional.class && !configImpl.getOptionalValue(key, String.class).isPresent()) {
-                        hasValue = false;
-                    }
-                } else if (!configImpl.getOptionalValue(key, String.class).isPresent()) {
-                    hasValue = false;
-                }
-                if (!hasValue) {
-                    deploymentProblems.add(new IllegalArgumentException("No configured value for '" + key + "' from " + injectionPoint));
-                }
-            }
-
-            Class<?> instanceType = null;
-            if (ParameterizedType.class.isInstance(injection.type)) { // converters validation
-                final ParameterizedType pt = ParameterizedType.class.cast(injection.type);
-                if (pt.getRawType() == Provider.class && pt.getActualTypeArguments().length == 1 && Class.class.isInstance(pt.getActualTypeArguments()[0])
-                        && !configImpl.getConverters().containsKey(Class.class.cast(pt.getActualTypeArguments()[0]))) {
-                    instanceType = Class.class.cast(pt.getActualTypeArguments()[0]);
-                } // else if Optional it is fine, else we don't know how to process
-            } else if (Class.class.isInstance(injection.type)) {
-                instanceType = Class.class.cast(injection.type);
-            }
-            if (instanceType != null) { // validate we have a converter + we can convert the existing value
-                if (!configImpl.getConverters().containsKey(instanceType)) {
-                    deploymentProblems.add(new IllegalArgumentException("Missing converter for '" + key + "' from " + injectionPoint));
-                } else if (hasValue) {
-                    try {
-                        configImpl.getConverters().get(injection.type).convert(configImpl.getValue(key));
-                    } catch (final RuntimeException re) {
-                        deploymentProblems.add(re);
-                    }
-                }
-            }
+            injectionPoints.add(pip.getInjectionPoint());
         }
     }
 
     public void registerConfigProducer(@Observes AfterBeanDiscovery abd, BeanManager bm) {
-        injections.stream()
-                .flatMap(injection -> {
-                    final BiFunction<CreationalContext<?>, ConfigInjectionBean<?>, String> keyProvider;
-                    if (injection.keys.size() == 1) {
-                        final String key = injection.keys.iterator().next();
-                        keyProvider = (ctx, bean) -> key;
-                    } else {
-                        keyProvider = (ctx, bean) -> getName(findInjectionPoint(bm, ctx, bean));
-                    }
-
-                    if (ParameterizedType.class.isInstance(injection.type)) {
-                        final ParameterizedType paramType = ParameterizedType.class.cast(injection.type);
-                        final Type rawType = paramType.getRawType();
-
-                        // todo: do we care of Instance injection? doesnt make much sense right?
-                        if (Provider.class == rawType && paramType.getActualTypeArguments().length == 1) {
-                            if (!Class.class.isInstance(paramType.getActualTypeArguments()[0])) {
-                                deploymentProblems.add(new IllegalArgumentException("@ConfigProperty can only be used with Provider<T> where T is a Class"));
-                                return Stream.empty();
-                            }
-                            final Class<?> providerType = Class.class.cast(paramType.getActualTypeArguments()[0]);
-                            return Stream.of(new ConfigInjectionBean<Provider<?>>(injection.type, true) {
-                                @Override
-                                public Provider<?> create(final CreationalContext<Provider<?>> context) {
-                                    return () -> config.getValue(keyProvider.apply(context, this), providerType);
-                                }
-                            });
-                        } else if (Optional.class == rawType && paramType.getActualTypeArguments().length == 1) {
-                            if (!Class.class.isInstance(paramType.getActualTypeArguments()[0])) {
-                                deploymentProblems.add(new IllegalArgumentException("@ConfigProperty can only be used with Optional<T> where T is a Class"));
-                                return null;
-                            }
-                            final Class<?> optionalType = Class.class.cast(paramType.getActualTypeArguments()[0]);
-                            return Stream.of(new ConfigInjectionBean<Optional<?>>(injection.type) {
-                                @Override
-                                public Optional<?> create(final CreationalContext<Optional<?>> context) {
-                                    return config.getOptionalValue(keyProvider.apply(context, this), optionalType);
-                                }
-                            });
-                        } else {
-                            deploymentProblems.add(new IllegalArgumentException("Unsupported parameterized type " + paramType));
-                            return Stream.empty();
-                        }
-                    } else if (Class.class.isInstance(injection.type)) {
-                        final Class clazz = Class.class.cast(injection.type);
-                        final ConfigInjectionBean bean;
-                        if (injection.defaultValues.isEmpty()) {
-                            bean = new ConfigInjectionBean<Object>(injection.type) {
-                                @Override
-                                public Object create(final CreationalContext<Object> context) {
-                                    return config.getOptionalValue(keyProvider.apply(context, this), clazz);
-                                }
-                            };
-                        } else if (injection.defaultValues.size() == 1) { // common enough to be optimized
-                            final String defVal = injection.defaultValues.iterator().next();
-                            final Object alternativeVal = isDefaultUnset(defVal) ? null : unwrapConfig().convert(defVal, clazz);
-                            bean = new ConfigInjectionBean<Object>(injection.type) {
-                                @Override
-                                public Object create(final CreationalContext<Object> context) {
-                                    final Optional optionalValue = config.getOptionalValue(keyProvider.apply(context, this), clazz);
-                                    return optionalValue.orElse(alternativeVal);
-                                }
-                            };
-                        } else { // sadly we need to get back to the injection point to know which one we need to use
-                            final Map<String, Object> prepared = injection.defaultValues.stream()
-                                    .collect(toMap(identity(), k -> isDefaultUnset(k) ? NULL : unwrapConfig().convert(k, clazz), (a, b) -> b));
-                            bean = new ConfigInjectionBean<Object>(injection.type) {
-                                @Override
-                                public Object create(final CreationalContext<Object> context) {
-                                    final InjectionPoint ip = findInjectionPoint(bm, context, this);
-                                    if (ip == null) {
-                                        throw new IllegalStateException("Could not retrieve InjectionPoint");
-                                    }
-                                    return config.getOptionalValue(ConfigExtension.this.getName(ip), clazz)
-                                            .orElseGet(() -> {
-                                                final Object val = prepared.get(ip.getAnnotated().getAnnotation(ConfigProperty.class).defaultValue());
-                                                return val == NULL ? null : val;
-                                            });
-                                }
-                            };
-                        }
-
-                        final Collection<ConfigInjectionBean<?>> beans = new ArrayList<>();
-                        beans.add(bean);
-
-                        // is adding these beans is that useful? we captured them all so only a programmatic lookup would justify it
-                        // and not sure it would be done this way anyway
-                        final ParameterizedTypeImpl providerType = new ParameterizedTypeImpl(Provider.class, injection.type);
-                        if (injections.stream().noneMatch(i -> i.type.equals(providerType))) {
-                            beans.add(new ConfigInjectionBean<Provider<?>>(providerType, true) {
-                                @Override
-                                public Provider<?> create(final CreationalContext<Provider<?>> context) {
-                                    return () -> bean.create(context);
-                                }
-                            });
-                        }
-
-                        final ParameterizedTypeImpl optionalType = new ParameterizedTypeImpl(Optional.class, injection.type);
-                        if (injections.stream().noneMatch(i -> i.type.equals(optionalType))) {
-                            beans.add(new ConfigInjectionBean<Optional<?>>(optionalType) {
-                                @Override
-                                public Optional<?> create(final CreationalContext<Optional<?>> context) {
-                                    return Optional.ofNullable(bean.create(context));
-                                }
-                            });
-                        }
-
-                        return beans.stream();
-                    } else {
-                        deploymentProblems.add(new IllegalArgumentException("Unknown type " + injection.type));
-                        return Stream.empty();
-                    }
-                })
-                .forEach(abd::addBean);
-    }
+        Set<Class> types = injectionPoints.stream()
+                .filter(ip -> ip.getType() instanceof Class)
+                .map(ip -> (Class) REPLACED_TYPES.getOrDefault(ip.getType(), ip.getType()))
+                .collect(Collectors.toSet());
+
+        // Provider and Optional are ParameterizedTypes and not a Class, so we need to add them manually
+        types.add(Provider.class);
+        types.add(Optional.class);
 
-    public void validate(@Observes AfterDeploymentValidation add) {
-        deploymentProblems.forEach(add::addDeploymentProblem);
-        injections.clear();
-        deploymentProblems.clear();
+        types.forEach(type -> abd.addBean(new ConfigInjectionBean(bm, type)));
     }
 
-    public void shutdown(@Observes BeforeShutdown bsd) {
-        resolver.releaseConfig(config);
-    }
+    public void validate(@Observes AfterDeploymentValidation add) {
+        List<String> deploymentProblems = new ArrayList<>();
 
-    private ConfigImpl unwrapConfig() {
-        return ConfigImpl.class.cast(config);
-    }
+        config = ConfigProvider.getConfig();
 
-    private static String getName(final InjectionPoint ip) {
-        final ConfigProperty annotation = ip.getAnnotated().getAnnotation(ConfigProperty.class);
-        final String name = annotation.name();
-        return isDefaultUnset(name) ? getConfigKey(ip, annotation) : name;
-    }
+        for (InjectionPoint injectionPoint : injectionPoints) {
+            Type type = injectionPoint.getType();
 
-    /**
-     * Get the property key to use.
-     * In case the {@link ConfigProperty#name()} is empty we will try to determine the key name from the InjectionPoint.
-     */
-    private static String getConfigKey(InjectionPoint ip, ConfigProperty configProperty) {
-        String key = configProperty.name();
-        if (!key.isEmpty()) {
-            return key;
-        }
-        if (ip.getAnnotated() instanceof AnnotatedMember) {
-            AnnotatedMember member = (AnnotatedMember) ip.getAnnotated();
-            AnnotatedType declaringType = member.getDeclaringType();
-            if (declaringType != null) {
-                String[] parts = declaringType.getJavaClass().getCanonicalName().split("\\.");
-                String cn = parts[parts.length - 1];
-                parts[parts.length - 1] = Character.toLowerCase(cn.charAt(0)) + (cn.length() > 1 ? cn.substring(1) : "");
-                StringBuilder sb = new StringBuilder(parts[0]);
-                for (int i = 1; i < parts.length; i++) {
-                    sb.append(".").append(parts[i]);
+            // replace native types with their Wrapper types
+            type = REPLACED_TYPES.getOrDefault(type, type);
+
+            ConfigProperty configProperty = injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class);
+            if (type instanceof Class) {
+                // a direct injection of a ConfigProperty
+                // that means a Converter must exist.
+                String key = ConfigInjectionBean.getConfigKey(injectionPoint, configProperty);
+                if ((isDefaultUnset(configProperty.defaultValue()))
+                        && !config.getOptionalValue(key, (Class) type).isPresent()) {
+                    deploymentProblems.add("No Config Value exists for " + key);
                 }
-
-                // now add the field name
-                sb.append(".").append(member.getJavaMember().getName());
-                return sb.toString();
             }
         }
 
-        throw new IllegalStateException("Could not find default name for @ConfigProperty InjectionPoint " + ip);
-    }
-
-    private static boolean isDefaultUnset(String defaultValue) {
-        return defaultValue == null || defaultValue.length() == 0 || defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);
-    }
-
-    private static InjectionPoint findInjectionPoint(final BeanManager bm, final CreationalContext<?> ctx,
-                                                     ConfigInjectionBean bean) {
-        return InjectionPoint.class.cast(bm.getInjectableReference(bean.getSimpleInjectionPoint(), ctx));
-    }
-
-    private static final class Injection {
-        private final Type type;
-        private final Collection<String> keys = new ArrayList<>();
-        private final Collection<String> defaultValues = new ArrayList<>();
-
-        private Injection(final Type type) {
-            this.type = type;
-        }
-
-        @Override
-        public boolean equals(final Object o) {
-            if (this == o) {
-                return true;
-            }
-            if (o == null || Injection.class != o.getClass()) {
-                return false;
-            }
-            final Injection injection = Injection.class.cast(o);
-            return Objects.equals(type, injection.type);
+        if (!deploymentProblems.isEmpty()) {
+            add.addDeploymentProblem(new DeploymentException("Error while validating Configuration\n"
+                                                             + String.join("\n", deploymentProblems)));
         }
 
-        @Override
-        public int hashCode() {
-            return type.hashCode();
-        }
     }
 
-    private class ParameterizedTypeImpl implements ParameterizedType {
-        private final Type rawType;
-        private final Type[] types;
-
-        private ParameterizedTypeImpl(final Type raw, final Type... types) {
-            this.rawType = raw;
-            this.types = types;
-        }
-
-        @Override
-        public Type[] getActualTypeArguments() {
-            return types.clone();
-        }
-
-        @Override
-        public Type getOwnerType() {
-            return null;
-        }
-
-        @Override
-        public Type getRawType() {
-            return rawType;
-        }
-
-        @Override
-        public int hashCode() {
-            return Arrays.hashCode(types) ^ rawType.hashCode();
-        }
-
-        @Override
-        public boolean equals(final Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (ParameterizedType.class.isInstance(obj)) {
-                final ParameterizedType that = ParameterizedType.class.cast(obj);
-                final Type thatRawType = that.getRawType();
-                return (rawType == null ? thatRawType == null : rawType.equals(thatRawType))
-                        && Arrays.equals(types, that.getActualTypeArguments());
-            }
-            return false;
-        }
+    public void shutdown(@Observes BeforeShutdown bsd) {
+        DefaultConfigProvider.instance().releaseConfig(config);
+    }
 
-        @Override
-        public String toString() {
-            final StringBuilder buffer = new StringBuilder();
-            buffer.append(Class.class.cast(rawType).getName());
-            final Type[] actualTypes = getActualTypeArguments();
-            if (actualTypes.length > 0) {
-                buffer.append("<");
-                final int length = actualTypes.length;
-                for (int i = 0; i < length; i++) {
-                    if (actualTypes[i] instanceof Class) {
-                        buffer.append(((Class<?>) actualTypes[i]).getSimpleName());
-                    } else {
-                        buffer.append(actualTypes[i].toString());
-                    }
-                    if (i != actualTypes.length - 1) {
-                        buffer.append(",");
-                    }
-                }
 
-                buffer.append(">");
-            }
-            return buffer.toString();
-        }
+    static boolean isDefaultUnset(String defaultValue) {
+        return defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);
     }
 }

Modified: geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java?rev=1804397&r1=1804396&r2=1804397&view=diff
==============================================================================
--- geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java (original)
+++ geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java Tue Aug  8 10:55:56 2017
@@ -16,49 +16,59 @@
  */
 package org.apache.geronimo.config.cdi;
 
-import org.eclipse.microprofile.config.inject.ConfigProperty;
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
 
 import javax.enterprise.context.Dependent;
 import javax.enterprise.context.spi.CreationalContext;
-import javax.enterprise.inject.Default;
 import javax.enterprise.inject.spi.Annotated;
+import javax.enterprise.inject.spi.AnnotatedMember;
+import javax.enterprise.inject.spi.AnnotatedType;
 import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
 import javax.enterprise.inject.spi.InjectionPoint;
 import javax.enterprise.inject.spi.PassivationCapable;
 import javax.enterprise.util.AnnotationLiteral;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Member;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
+import javax.inject.Provider;
+
+import org.apache.geronimo.config.ConfigImpl;
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
 
 /**
  * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
  */
-public abstract class ConfigInjectionBean<T> implements Bean<T>, PassivationCapable {
+public class ConfigInjectionBean<T> implements Bean<T>, PassivationCapable {
 
     private final static Set<Annotation> QUALIFIERS = new HashSet<>();
     static {
         QUALIFIERS.add(new ConfigPropertyLiteral());
     }
 
+    private final BeanManager bm;
     private final Class rawType;
     private final Set<Type> types;
-    private final String id;
-    private final boolean alternative;
-
-    ConfigInjectionBean(Type type) {
-        this(type,false);
-    }
 
-    ConfigInjectionBean(Type type, boolean alternative) {
-        this.types = new HashSet<>();
-        this.types.add(type);
-        this.rawType = getRawType(type);
-        this.id = "ConfigInjectionBean_" + type.toString();
-        this.alternative = alternative;
+    /**
+     * only access via {@link #getConfig(}
+     */
+    private Config _config;
+
+    public ConfigInjectionBean(BeanManager bm, Type type) {
+        this.bm = bm;
+
+        types = new HashSet<>();
+        types.add(type);
+        rawType = getRawType(type);
     }
 
     private Class getRawType(Type type) {
@@ -76,7 +86,7 @@ public abstract class ConfigInjectionBea
 
     @Override
     public Set<InjectionPoint> getInjectionPoints() {
-        return Collections.emptySet();
+        return Collections.EMPTY_SET;
     }
 
     @Override
@@ -90,8 +100,90 @@ public abstract class ConfigInjectionBea
     }
 
     @Override
+    public T create(CreationalContext<T> context) {
+        Set<Bean<?>> beans = bm.getBeans(InjectionPoint.class);
+        Bean<?> bean = bm.resolve(beans);
+        InjectionPoint ip = (InjectionPoint) bm.getReference(bean, InjectionPoint.class,  context);
+        if (ip == null) {
+            throw new IllegalStateException("Could not retrieve InjectionPoint");
+        }
+        Annotated annotated = ip.getAnnotated();
+        ConfigProperty configProperty = annotated.getAnnotation(ConfigProperty.class);
+        String key = getConfigKey(ip, configProperty);
+        String defaultValue = configProperty.defaultValue();
+
+        if (annotated.getBaseType() instanceof ParameterizedType) {
+            ParameterizedType paramType = (ParameterizedType) annotated.getBaseType();
+            Type rawType = paramType.getRawType();
+
+            // handle Provider<T>
+            if (rawType instanceof Class && ((Class) rawType).isAssignableFrom(Provider.class) && paramType.getActualTypeArguments().length == 1) {
+                Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
+                return (T) new ConfigValueProvider(getConfig(), key, clazz);
+            }
+
+            // handle Optional<T>
+            if (rawType instanceof Class && ((Class) rawType).isAssignableFrom(Optional.class) && paramType.getActualTypeArguments().length == 1) {
+                Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
+                return (T) getConfig().getOptionalValue(key, clazz);
+            }
+        }
+        else {
+            Class clazz = (Class) annotated.getBaseType();
+            if (ConfigExtension.isDefaultUnset(defaultValue)) {
+                return (T) getConfig().getValue(key, clazz);
+            }
+            else {
+                Config config = getConfig();
+                return (T) config.getOptionalValue(key, clazz)
+                        .orElse(((ConfigImpl) config).convert(defaultValue, clazz));
+            }
+        }
+
+        throw new IllegalStateException("unhandled ConfigProperty");
+    }
+
+
+    /**
+     * Get the property key to use.
+     * In case the {@link ConfigProperty#name()} is empty we will try to determine the key name from the InjectionPoint.
+     */
+    public static String getConfigKey(InjectionPoint ip, ConfigProperty configProperty) {
+        String key = configProperty.name();
+        if (key.length() > 0) {
+            return key;
+        }
+        if (ip.getAnnotated() instanceof AnnotatedMember) {
+            AnnotatedMember member = (AnnotatedMember) ip.getAnnotated();
+            AnnotatedType declaringType = member.getDeclaringType();
+            if (declaringType != null) {
+                String[] parts = declaringType.getJavaClass().getCanonicalName().split("\\.");
+                String cn = parts[parts.length-1];
+                parts[parts.length-1] = Character.toLowerCase(cn.charAt(0)) + (cn.length() > 1 ? cn.substring(1) : "");
+                StringBuilder sb = new StringBuilder(parts[0]);
+                for (int i = 1; i < parts.length; i++) {
+                    sb.append(".").append(parts[i]);
+                }
+
+                // now add the field name
+                sb.append(".").append(member.getJavaMember().getName());
+                return sb.toString();
+            }
+        }
+
+        throw new IllegalStateException("Could not find default name for @ConfigProperty InjectionPoint " + ip);
+    }
+
+    public Config getConfig() {
+        if (_config == null) {
+            _config = ConfigProvider.getConfig();
+        }
+        return _config;
+    }
+
+    @Override
     public void destroy(T instance, CreationalContext<T> context) {
-        // no-op
+
     }
 
     @Override
@@ -116,21 +208,17 @@ public abstract class ConfigInjectionBea
 
     @Override
     public Set<Class<? extends Annotation>> getStereotypes() {
-        return Collections.emptySet();
+        return Collections.EMPTY_SET;
     }
 
     @Override
     public boolean isAlternative() {
-        return alternative;
+        return true;
     }
 
     @Override
     public String getId() {
-        return id;
-    }
-
-    InjectionPoint getSimpleInjectionPoint() {
-        return simpleInjectionPoint;
+        return "ConfigInjectionBean_" + rawType.getName();
     }
 
     private static class ConfigPropertyLiteral extends AnnotationLiteral<ConfigProperty> implements ConfigProperty {
@@ -145,41 +233,31 @@ public abstract class ConfigInjectionBea
         }
     }
 
-    private final InjectionPoint simpleInjectionPoint = new InjectionPoint() {
-
-        @Override
-        public boolean isTransient() {
-            return false;
-        }
-
-        @Override
-        public boolean isDelegate() {
-            return false;
-        }
-
-        @Override
-        public Type getType() {
-            return InjectionPoint.class;
-        }
-
-        @Override
-        public Set<Annotation> getQualifiers() {
-            return Collections.singleton(new AnnotationLiteral<Default>() {});
-        }
-
-        @Override
-        public Member getMember() {
-            return null;
+    /**
+     * A special Provider&lt;T&gt;
+     * This concrete class is needed because we need the injected Provider for the ConfigProperty
+     * to be Serializable. A Lambda would not work in this case
+     */
+    public static class ConfigValueProvider<T> implements Provider<T>, Serializable {
+        private transient Config config;
+        private final String key;
+        private final Class<T> type;
+
+        ConfigValueProvider(Config config, String key, Class<T> type) {
+            this.config = config;
+            this.key = key;
+            this.type = type;
         }
 
         @Override
-        public Bean<?> getBean() {
-            return ConfigInjectionBean.this;
+        public T get() {
+            return (T) config.getValue(key, type);
+        }
+
+        private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
+            in.defaultReadObject();
+            config = ConfigProviderResolver.instance().getConfig();
         }
 
-        @Override
-        public Annotated getAnnotated() {
-            return null;
-        }
-    };
+    }
 }

Modified: geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java?rev=1804397&r1=1804396&r2=1804397&view=diff
==============================================================================
--- geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java (original)
+++ geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java Tue Aug  8 10:55:56 2017
@@ -33,9 +33,12 @@ import org.testng.annotations.Test;
 
 public class ProviderTest extends Arquillian {
     private static final String SOME_KEY = "org.apache.geronimo.config.test.internal.somekey";
+    private static final String ANOTHER_KEY = "org.apache.geronimo.config.test.internal.anotherkey";
 
     @Deployment
     public static WebArchive deploy() {
+        System.setProperty(SOME_KEY, "someval");
+        System.setProperty(ANOTHER_KEY, "someval");
         JavaArchive testJar = ShrinkWrap
                 .create(JavaArchive.class, "configProviderTest.jar")
                 .addClasses(ProviderTest.class, SomeBean.class)
@@ -70,8 +73,16 @@ public class ProviderTest extends Arquil
         @ConfigProperty(name=SOME_KEY)
         private Provider<String> myconfig;
 
+        @Inject
+        @ConfigProperty(name=ANOTHER_KEY)
+        private Provider<String> anotherconfig;
+
         public String getMyconfig() {
             return myconfig.get();
         }
+
+        public Provider<String> getAnotherconfig() {
+            return anotherconfig;
+        }
     }
 }

Modified: geronimo/components/config/trunk/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/pom.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
==============================================================================
--- geronimo/components/config/trunk/pom.xml (original)
+++ geronimo/components/config/trunk/pom.xml Tue Aug  8 10:55:56 2017
@@ -27,7 +27,7 @@
     </parent>
 
     <groupId>org.apache.geronimo.config</groupId>
-    <artifactId>config-parent</artifactId>
+    <artifactId>geronimo-config</artifactId>
     <version>1.1-SNAPSHOT</version>
     <packaging>pom</packaging>
     <name>Geronimo Microprofile Configuration</name>
@@ -50,7 +50,7 @@
     <properties>
         <maven.compiler.source>1.8</maven.compiler.source>
         <maven.compiler.target>1.8</maven.compiler.target>
-        <microprofile-config.version>1.1-SNAPSHOT</microprofile-config.version>
+        <microprofile-config.version>1.0</microprofile-config.version>
         <owb.version>1.7.3</owb.version>
         <owb2.version>2.0.1-SNAPSHOT</owb2.version>
         <arquillian.version>1.1.13.Final</arquillian.version>



Re: svn commit: r1804397 - in /geronimo/components/config/trunk: ./ impl/ impl/src/main/java/org/apache/geronimo/config/cdi/ impl/src/test/java/org/apache/geronimo/config/test/internal/

Posted by Mark Struberg <st...@yahoo.de>.
I'll take a look in the evening.

LieGrue,
Strub

> Am 09.08.2017 um 14:00 schrieb John D. Ament <jo...@apache.org>:
> 
> Ok, I got tests passing on all three.  It actually looks like its simpler (and more correct) to not use a custom provider.  The provider approach wasn't supporting default values.  I've committed changes, please take a look and hopefully we can plan to reroll 1.0.
> 
> John
> 
>> On Tue, Aug 8, 2017 at 10:02 PM John D. Ament <jo...@apache.org> wrote:
>> Ok, I've readded some of the Weld3 support, 3 tests are failing.
>> 
>> Some interesting notes:
>> 
>> - If I remove Provider support, it generally works.  However, I suddenly get duplicate beans of type Provider, which is confusing (but probably because of the alternative flag).
>> - I can get everything to pass in Weld, and 1 test failure in in OWB with the following:
>> 
>> - Set alternative = false
>> - Remove Provider from the types
>> - Remove the filter on types to check if class.
>> - Change getId to use all of the types (makes a better toString)
>> 
>> 
>> If we can figure out the alternative issue with OWB, we'll be good to go again.
>> 
>> John
>> 
>>> On Tue, Aug 8, 2017 at 8:44 AM John D. Ament <jo...@apache.org> wrote:
>>> I can get to some of it.
>>> 
>>> We have a couple of issues now though:
>>> 
>>> https://issues.jboss.org/browse/WELD-2411
>>> https://issues.jboss.org/browse/CDI-712
>>> 
>>> Martin doesn't feel the spec allows you to override Provider impl's.  Please feel free to weigh in :-)
>>> 
>>> John
>>> 
>>> 
>>>> On Tue, Aug 8, 2017 at 7:33 AM Mark Struberg <st...@yahoo.de> wrote:
>>>> Oh I see what you mean.
>>>> Do you mind to re-apply your fix or should I?
>>>> 
>>>> Btw, I also tested with the -PWeld3 but I was not able to resolve arquillian-weld-embedded:jar:2.0.0-SNAPSHOT
>>>> We might need to add a <repository> for it in the Weld3 profile.
>>>> 
>>>> I also would love to add a Weld profile. I thought we have this already but seems we missed it?
>>>> 
>>>> txs and LieGrue,
>>>> strub
>>>> 
>>>> > Am 08.08.2017 um 12:58 schrieb John D. Ament <jo...@apache.org>:
>>>> >
>>>> > One note - hardcoding "isAlternative" to true breaks in Weld.  Unless there is a base bean of same type, the alternative is ignored.  Hence why I only did isAlternative on the provider type, all others are just regular beans.
>>>> >
>>>> > John
>>>> >
>>>> > On Tue, Aug 8, 2017 at 6:55 AM <st...@apache.org> wrote:
>>>> > Author: struberg
>>>> > Date: Tue Aug  8 10:55:56 2017
>>>> > New Revision: 1804397
>>>> >
>>>> > URL: http://svn.apache.org/viewvc?rev=1804397&view=rev
>>>> > Log:
>>>> > GERONIMO-6577 move back to a more dynamic version
>>>> >
>>>> > The goal of r1800748 to calculate all information upfront could not be achieved
>>>> > so we move back to the old version
>>>> >
>>>> > Modified:
>>>> >     geronimo/components/config/trunk/impl/debug-suite.xml
>>>> >     geronimo/components/config/trunk/impl/pom.xml
>>>> >     geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
>>>> >     geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
>>>> >     geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
>>>> >     geronimo/components/config/trunk/pom.xml
>>>> >
>>>> > Modified: geronimo/components/config/trunk/impl/debug-suite.xml
>>>> > URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/debug-suite.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
>>>> > ==============================================================================
>>>> > --- geronimo/components/config/trunk/impl/debug-suite.xml (original)
>>>> > +++ geronimo/components/config/trunk/impl/debug-suite.xml Tue Aug  8 10:55:56 2017
>>>> > @@ -24,7 +24,7 @@
>>>> >      <classes>
>>>> >          <!-- Issues in the spec -->
>>>> >          <!-- CDI-437 -->
>>>> > -        <class name="org.eclipse.microprofile.config.tck.CdiOptionalInjectionTest">
>>>> > +        <class name="org.eclipse.microprofile.config.tck.CDIPlainInjectionTest">
>>>> >              <methods>
>>>> >                  <include name=".*"/>
>>>> >              </methods>
>>>> >
>>>> > Modified: geronimo/components/config/trunk/impl/pom.xml
>>>> > URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/pom.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
>>>> > ==============================================================================
>>>> > --- geronimo/components/config/trunk/impl/pom.xml (original)
>>>> > +++ geronimo/components/config/trunk/impl/pom.xml Tue Aug  8 10:55:56 2017
>>>> > @@ -27,7 +27,6 @@
>>>> >      </parent>
>>>> >
>>>> >      <artifactId>geronimo-config-impl</artifactId>
>>>> > -    <name>Geronimo Microprofile Configuration :: Implementation</name>
>>>> >
>>>> >      <dependencyManagement>
>>>> >          <dependencies>
>>>> >
>>>> > Modified: geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
>>>> > URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java?rev=1804397&r1=1804396&r2=1804397&view=diff
>>>> > ==============================================================================
>>>> > --- geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java (original)
>>>> > +++ geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java Tue Aug  8 10:55:56 2017
>>>> > @@ -16,54 +16,38 @@
>>>> >   */
>>>> >  package org.apache.geronimo.config.cdi;
>>>> >
>>>> > -import org.apache.geronimo.config.ConfigImpl;
>>>> > -import org.eclipse.microprofile.config.Config;
>>>> > -import org.eclipse.microprofile.config.inject.ConfigProperty;
>>>> > -import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
>>>> > +import java.lang.reflect.Type;
>>>> > +import java.util.ArrayList;
>>>> > +import java.util.HashMap;
>>>> > +import java.util.HashSet;
>>>> > +import java.util.List;
>>>> > +import java.util.Map;
>>>> > +import java.util.Optional;
>>>> > +import java.util.Set;
>>>> > +import java.util.stream.Collectors;
>>>> >
>>>> > -import javax.enterprise.context.spi.CreationalContext;
>>>> >  import javax.enterprise.event.Observes;
>>>> >  import javax.enterprise.inject.spi.AfterBeanDiscovery;
>>>> >  import javax.enterprise.inject.spi.AfterDeploymentValidation;
>>>> > -import javax.enterprise.inject.spi.AnnotatedMember;
>>>> > -import javax.enterprise.inject.spi.AnnotatedType;
>>>> >  import javax.enterprise.inject.spi.BeanManager;
>>>> > -import javax.enterprise.inject.spi.BeforeBeanDiscovery;
>>>> >  import javax.enterprise.inject.spi.BeforeShutdown;
>>>> > +import javax.enterprise.inject.spi.DeploymentException;
>>>> >  import javax.enterprise.inject.spi.Extension;
>>>> >  import javax.enterprise.inject.spi.InjectionPoint;
>>>> >  import javax.enterprise.inject.spi.ProcessInjectionPoint;
>>>> >  import javax.inject.Provider;
>>>> > -import java.lang.reflect.ParameterizedType;
>>>> > -import java.lang.reflect.Type;
>>>> > -import java.util.ArrayList;
>>>> > -import java.util.Arrays;
>>>> > -import java.util.Collection;
>>>> > -import java.util.HashMap;
>>>> > -import java.util.HashSet;
>>>> > -import java.util.List;
>>>> > -import java.util.Map;
>>>> > -import java.util.Objects;
>>>> > -import java.util.Optional;
>>>> > -import java.util.Set;
>>>> > -import java.util.function.BiFunction;
>>>> > -import java.util.stream.Stream;
>>>> >
>>>> > -import static java.util.function.Function.identity;
>>>> > -import static java.util.stream.Collectors.toMap;
>>>> > -import static org.eclipse.microprofile.config.ConfigProvider.getConfig;
>>>> > +import org.apache.geronimo.config.DefaultConfigProvider;
>>>> > +import org.eclipse.microprofile.config.Config;
>>>> > +import org.eclipse.microprofile.config.ConfigProvider;
>>>> > +import org.eclipse.microprofile.config.inject.ConfigProperty;
>>>> >
>>>> >  /**
>>>> >   * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
>>>> >   */
>>>> >  public class ConfigExtension implements Extension {
>>>> > -    private static final Object NULL = new Object();
>>>> > -
>>>> >      private Config config;
>>>> > -    private ConfigProviderResolver resolver;
>>>> >
>>>> > -    private Set<Injection> injections = new HashSet<>();
>>>> > -    private List<Throwable> deploymentProblems = new ArrayList<>();
>>>> >      private static final Map<Type, Type> REPLACED_TYPES = new HashMap<>();
>>>> >
>>>> >      static {
>>>> > @@ -74,336 +58,65 @@ public class ConfigExtension implements
>>>> >          REPLACED_TYPES.put(boolean.class, Boolean.class);
>>>> >      }
>>>> >
>>>> > -    void init(@Observes final BeforeBeanDiscovery beforeBeanDiscovery, final BeanManager bm) {
>>>> > -        resolver = ConfigProviderResolver.instance();
>>>> > -        config = getConfig();
>>>> > -    }
>>>> > +    private Set<InjectionPoint> injectionPoints = new HashSet<>();
>>>> > +
>>>> >
>>>> >      public void collectConfigProducer(@Observes ProcessInjectionPoint<?, ?> pip) {
>>>> > -        final InjectionPoint injectionPoint = pip.getInjectionPoint();
>>>> > -        final ConfigProperty configProperty = injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class);
>>>> > +        ConfigProperty configProperty = pip.getInjectionPoint().getAnnotated().getAnnotation(ConfigProperty.class);
>>>> >          if (configProperty != null) {
>>>> > -            Type replacedType = REPLACED_TYPES.getOrDefault(injectionPoint.getType(), injectionPoint.getType());
>>>> > -            Injection injection = new Injection(replacedType);
>>>> > -            final String key = getConfigKey(injectionPoint, configProperty);
>>>> > -            final boolean defaultUnset = isDefaultUnset(configProperty.defaultValue());
>>>> > -            if (!injections.add(injection)) {
>>>> > -                final Injection ref = injection;
>>>> > -                injection = injections.stream().filter(i -> i.equals(ref)).findFirst().get();
>>>> > -            }
>>>> > -            injection.keys.add(key);
>>>> > -            injection.defaultValues.add(configProperty.defaultValue());
>>>> > -
>>>> > -            final ConfigImpl configImpl = unwrapConfig();
>>>> > -
>>>> > -            // what about lazy runtime lookup, not consistent with tck and system prop usage, for now assume optional=optional ;)
>>>> > -            boolean hasValue = true;
>>>> > -            if (defaultUnset) { // value validation
>>>> > -                if (ParameterizedType.class.isInstance(injection.type)) {
>>>> > -                    final ParameterizedType pt = ParameterizedType.class.cast(injection.type);
>>>> > -                    if (pt.getRawType() != Optional.class && !configImpl.getOptionalValue(key, String.class).isPresent()) {
>>>> > -                        hasValue = false;
>>>> > -                    }
>>>> > -                } else if (!configImpl.getOptionalValue(key, String.class).isPresent()) {
>>>> > -                    hasValue = false;
>>>> > -                }
>>>> > -                if (!hasValue) {
>>>> > -                    deploymentProblems.add(new IllegalArgumentException("No configured value for '" + key + "' from " + injectionPoint));
>>>> > -                }
>>>> > -            }
>>>> > -
>>>> > -            Class<?> instanceType = null;
>>>> > -            if (ParameterizedType.class.isInstance(injection.type)) { // converters validation
>>>> > -                final ParameterizedType pt = ParameterizedType.class.cast(injection.type);
>>>> > -                if (pt.getRawType() == Provider.class && pt.getActualTypeArguments().length == 1 && Class.class.isInstance(pt.getActualTypeArguments()[0])
>>>> > -                        && !configImpl.getConverters().containsKey(Class.class.cast(pt.getActualTypeArguments()[0]))) {
>>>> > -                    instanceType = Class.class.cast(pt.getActualTypeArguments()[0]);
>>>> > -                } // else if Optional it is fine, else we don't know how to process
>>>> > -            } else if (Class.class.isInstance(injection.type)) {
>>>> > -                instanceType = Class.class.cast(injection.type);
>>>> > -            }
>>>> > -            if (instanceType != null) { // validate we have a converter + we can convert the existing value
>>>> > -                if (!configImpl.getConverters().containsKey(instanceType)) {
>>>> > -                    deploymentProblems.add(new IllegalArgumentException("Missing converter for '" + key + "' from " + injectionPoint));
>>>> > -                } else if (hasValue) {
>>>> > -                    try {
>>>> > -                        configImpl.getConverters().get(injection.type).convert(configImpl.getValue(key));
>>>> > -                    } catch (final RuntimeException re) {
>>>> > -                        deploymentProblems.add(re);
>>>> > -                    }
>>>> > -                }
>>>> > -            }
>>>> > +            injectionPoints.add(pip.getInjectionPoint());
>>>> >          }
>>>> >      }
>>>> >
>>>> >      public void registerConfigProducer(@Observes AfterBeanDiscovery abd, BeanManager bm) {
>>>> > -        injections.stream()
>>>> > -                .flatMap(injection -> {
>>>> > -                    final BiFunction<CreationalContext<?>, ConfigInjectionBean<?>, String> keyProvider;
>>>> > -                    if (injection.keys.size() == 1) {
>>>> > -                        final String key = injection.keys.iterator().next();
>>>> > -                        keyProvider = (ctx, bean) -> key;
>>>> > -                    } else {
>>>> > -                        keyProvider = (ctx, bean) -> getName(findInjectionPoint(bm, ctx, bean));
>>>> > -                    }
>>>> > -
>>>> > -                    if (ParameterizedType.class.isInstance(injection.type)) {
>>>> > -                        final ParameterizedType paramType = ParameterizedType.class.cast(injection.type);
>>>> > -                        final Type rawType = paramType.getRawType();
>>>> > -
>>>> > -                        // todo: do we care of Instance injection? doesnt make much sense right?
>>>> > -                        if (Provider.class == rawType && paramType.getActualTypeArguments().length == 1) {
>>>> > -                            if (!Class.class.isInstance(paramType.getActualTypeArguments()[0])) {
>>>> > -                                deploymentProblems.add(new IllegalArgumentException("@ConfigProperty can only be used with Provider<T> where T is a Class"));
>>>> > -                                return Stream.empty();
>>>> > -                            }
>>>> > -                            final Class<?> providerType = Class.class.cast(paramType.getActualTypeArguments()[0]);
>>>> > -                            return Stream.of(new ConfigInjectionBean<Provider<?>>(injection.type, true) {
>>>> > -                                @Override
>>>> > -                                public Provider<?> create(final CreationalContext<Provider<?>> context) {
>>>> > -                                    return () -> config.getValue(keyProvider.apply(context, this), providerType);
>>>> > -                                }
>>>> > -                            });
>>>> > -                        } else if (Optional.class == rawType && paramType.getActualTypeArguments().length == 1) {
>>>> > -                            if (!Class.class.isInstance(paramType.getActualTypeArguments()[0])) {
>>>> > -                                deploymentProblems.add(new IllegalArgumentException("@ConfigProperty can only be used with Optional<T> where T is a Class"));
>>>> > -                                return null;
>>>> > -                            }
>>>> > -                            final Class<?> optionalType = Class.class.cast(paramType.getActualTypeArguments()[0]);
>>>> > -                            return Stream.of(new ConfigInjectionBean<Optional<?>>(injection.type) {
>>>> > -                                @Override
>>>> > -                                public Optional<?> create(final CreationalContext<Optional<?>> context) {
>>>> > -                                    return config.getOptionalValue(keyProvider.apply(context, this), optionalType);
>>>> > -                                }
>>>> > -                            });
>>>> > -                        } else {
>>>> > -                            deploymentProblems.add(new IllegalArgumentException("Unsupported parameterized type " + paramType));
>>>> > -                            return Stream.empty();
>>>> > -                        }
>>>> > -                    } else if (Class.class.isInstance(injection.type)) {
>>>> > -                        final Class clazz = Class.class.cast(injection.type);
>>>> > -                        final ConfigInjectionBean bean;
>>>> > -                        if (injection.defaultValues.isEmpty()) {
>>>> > -                            bean = new ConfigInjectionBean<Object>(injection.type) {
>>>> > -                                @Override
>>>> > -                                public Object create(final CreationalContext<Object> context) {
>>>> > -                                    return config.getOptionalValue(keyProvider.apply(context, this), clazz);
>>>> > -                                }
>>>> > -                            };
>>>> > -                        } else if (injection.defaultValues.size() == 1) { // common enough to be optimized
>>>> > -                            final String defVal = injection.defaultValues.iterator().next();
>>>> > -                            final Object alternativeVal = isDefaultUnset(defVal) ? null : unwrapConfig().convert(defVal, clazz);
>>>> > -                            bean = new ConfigInjectionBean<Object>(injection.type) {
>>>> > -                                @Override
>>>> > -                                public Object create(final CreationalContext<Object> context) {
>>>> > -                                    final Optional optionalValue = config.getOptionalValue(keyProvider.apply(context, this), clazz);
>>>> > -                                    return optionalValue.orElse(alternativeVal);
>>>> > -                                }
>>>> > -                            };
>>>> > -                        } else { // sadly we need to get back to the injection point to know which one we need to use
>>>> > -                            final Map<String, Object> prepared = injection.defaultValues.stream()
>>>> > -                                    .collect(toMap(identity(), k -> isDefaultUnset(k) ? NULL : unwrapConfig().convert(k, clazz), (a, b) -> b));
>>>> > -                            bean = new ConfigInjectionBean<Object>(injection.type) {
>>>> > -                                @Override
>>>> > -                                public Object create(final CreationalContext<Object> context) {
>>>> > -                                    final InjectionPoint ip = findInjectionPoint(bm, context, this);
>>>> > -                                    if (ip == null) {
>>>> > -                                        throw new IllegalStateException("Could not retrieve InjectionPoint");
>>>> > -                                    }
>>>> > -                                    return config.getOptionalValue(ConfigExtension.this.getName(ip), clazz)
>>>> > -                                            .orElseGet(() -> {
>>>> > -                                                final Object val = prepared.get(ip.getAnnotated().getAnnotation(ConfigProperty.class).defaultValue());
>>>> > -                                                return val == NULL ? null : val;
>>>> > -                                            });
>>>> > -                                }
>>>> > -                            };
>>>> > -                        }
>>>> > -
>>>> > -                        final Collection<ConfigInjectionBean<?>> beans = new ArrayList<>();
>>>> > -                        beans.add(bean);
>>>> > -
>>>> > -                        // is adding these beans is that useful? we captured them all so only a programmatic lookup would justify it
>>>> > -                        // and not sure it would be done this way anyway
>>>> > -                        final ParameterizedTypeImpl providerType = new ParameterizedTypeImpl(Provider.class, injection.type);
>>>> > -                        if (injections.stream().noneMatch(i -> i.type.equals(providerType))) {
>>>> > -                            beans.add(new ConfigInjectionBean<Provider<?>>(providerType, true) {
>>>> > -                                @Override
>>>> > -                                public Provider<?> create(final CreationalContext<Provider<?>> context) {
>>>> > -                                    return () -> bean.create(context);
>>>> > -                                }
>>>> > -                            });
>>>> > -                        }
>>>> > -
>>>> > -                        final ParameterizedTypeImpl optionalType = new ParameterizedTypeImpl(Optional.class, injection.type);
>>>> > -                        if (injections.stream().noneMatch(i -> i.type.equals(optionalType))) {
>>>> > -                            beans.add(new ConfigInjectionBean<Optional<?>>(optionalType) {
>>>> > -                                @Override
>>>> > -                                public Optional<?> create(final CreationalContext<Optional<?>> context) {
>>>> > -                                    return Optional.ofNullable(bean.create(context));
>>>> > -                                }
>>>> > -                            });
>>>> > -                        }
>>>> > -
>>>> > -                        return beans.stream();
>>>> > -                    } else {
>>>> > -                        deploymentProblems.add(new IllegalArgumentException("Unknown type " + injection.type));
>>>> > -                        return Stream.empty();
>>>> > -                    }
>>>> > -                })
>>>> > -                .forEach(abd::addBean);
>>>> > -    }
>>>> > +        Set<Class> types = injectionPoints.stream()
>>>> > +                .filter(ip -> ip.getType() instanceof Class)
>>>> > +                .map(ip -> (Class) REPLACED_TYPES.getOrDefault(ip.getType(), ip.getType()))
>>>> > +                .collect(Collectors.toSet());
>>>> > +
>>>> > +        // Provider and Optional are ParameterizedTypes and not a Class, so we need to add them manually
>>>> > +        types.add(Provider.class);
>>>> > +        types.add(Optional.class);
>>>> >
>>>> > -    public void validate(@Observes AfterDeploymentValidation add) {
>>>> > -        deploymentProblems.forEach(add::addDeploymentProblem);
>>>> > -        injections.clear();
>>>> > -        deploymentProblems.clear();
>>>> > +        types.forEach(type -> abd.addBean(new ConfigInjectionBean(bm, type)));
>>>> >      }
>>>> >
>>>> > -    public void shutdown(@Observes BeforeShutdown bsd) {
>>>> > -        resolver.releaseConfig(config);
>>>> > -    }
>>>> > +    public void validate(@Observes AfterDeploymentValidation add) {
>>>> > +        List<String> deploymentProblems = new ArrayList<>();
>>>> >
>>>> > -    private ConfigImpl unwrapConfig() {
>>>> > -        return ConfigImpl.class.cast(config);
>>>> > -    }
>>>> > +        config = ConfigProvider.getConfig();
>>>> >
>>>> > -    private static String getName(final InjectionPoint ip) {
>>>> > -        final ConfigProperty annotation = ip.getAnnotated().getAnnotation(ConfigProperty.class);
>>>> > -        final String name = annotation.name();
>>>> > -        return isDefaultUnset(name) ? getConfigKey(ip, annotation) : name;
>>>> > -    }
>>>> > +        for (InjectionPoint injectionPoint : injectionPoints) {
>>>> > +            Type type = injectionPoint.getType();
>>>> >
>>>> > -    /**
>>>> > -     * Get the property key to use.
>>>> > -     * In case the {@link ConfigProperty#name()} is empty we will try to determine the key name from the InjectionPoint.
>>>> > -     */
>>>> > -    private static String getConfigKey(InjectionPoint ip, ConfigProperty configProperty) {
>>>> > -        String key = configProperty.name();
>>>> > -        if (!key.isEmpty()) {
>>>> > -            return key;
>>>> > -        }
>>>> > -        if (ip.getAnnotated() instanceof AnnotatedMember) {
>>>> > -            AnnotatedMember member = (AnnotatedMember) ip.getAnnotated();
>>>> > -            AnnotatedType declaringType = member.getDeclaringType();
>>>> > -            if (declaringType != null) {
>>>> > -                String[] parts = declaringType.getJavaClass().getCanonicalName().split("\\.");
>>>> > -                String cn = parts[parts.length - 1];
>>>> > -                parts[parts.length - 1] = Character.toLowerCase(cn.charAt(0)) + (cn.length() > 1 ? cn.substring(1) : "");
>>>> > -                StringBuilder sb = new StringBuilder(parts[0]);
>>>> > -                for (int i = 1; i < parts.length; i++) {
>>>> > -                    sb.append(".").append(parts[i]);
>>>> > +            // replace native types with their Wrapper types
>>>> > +            type = REPLACED_TYPES.getOrDefault(type, type);
>>>> > +
>>>> > +            ConfigProperty configProperty = injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class);
>>>> > +            if (type instanceof Class) {
>>>> > +                // a direct injection of a ConfigProperty
>>>> > +                // that means a Converter must exist.
>>>> > +                String key = ConfigInjectionBean.getConfigKey(injectionPoint, configProperty);
>>>> > +                if ((isDefaultUnset(configProperty.defaultValue()))
>>>> > +                        && !config.getOptionalValue(key, (Class) type).isPresent()) {
>>>> > +                    deploymentProblems.add("No Config Value exists for " + key);
>>>> >                  }
>>>> > -
>>>> > -                // now add the field name
>>>> > -                sb.append(".").append(member.getJavaMember().getName());
>>>> > -                return sb.toString();
>>>> >              }
>>>> >          }
>>>> >
>>>> > -        throw new IllegalStateException("Could not find default name for @ConfigProperty InjectionPoint " + ip);
>>>> > -    }
>>>> > -
>>>> > -    private static boolean isDefaultUnset(String defaultValue) {
>>>> > -        return defaultValue == null || defaultValue.length() == 0 || defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);
>>>> > -    }
>>>> > -
>>>> > -    private static InjectionPoint findInjectionPoint(final BeanManager bm, final CreationalContext<?> ctx,
>>>> > -                                                     ConfigInjectionBean bean) {
>>>> > -        return InjectionPoint.class.cast(bm.getInjectableReference(bean.getSimpleInjectionPoint(), ctx));
>>>> > -    }
>>>> > -
>>>> > -    private static final class Injection {
>>>> > -        private final Type type;
>>>> > -        private final Collection<String> keys = new ArrayList<>();
>>>> > -        private final Collection<String> defaultValues = new ArrayList<>();
>>>> > -
>>>> > -        private Injection(final Type type) {
>>>> > -            this.type = type;
>>>> > -        }
>>>> > -
>>>> > -        @Override
>>>> > -        public boolean equals(final Object o) {
>>>> > -            if (this == o) {
>>>> > -                return true;
>>>> > -            }
>>>> > -            if (o == null || Injection.class != o.getClass()) {
>>>> > -                return false;
>>>> > -            }
>>>> > -            final Injection injection = Injection.class.cast(o);
>>>> > -            return Objects.equals(type, injection.type);
>>>> > +        if (!deploymentProblems.isEmpty()) {
>>>> > +            add.addDeploymentProblem(new DeploymentException("Error while validating Configuration\n"
>>>> > +                                                             + String.join("\n", deploymentProblems)));
>>>> >          }
>>>> >
>>>> > -        @Override
>>>> > -        public int hashCode() {
>>>> > -            return type.hashCode();
>>>> > -        }
>>>> >      }
>>>> >
>>>> > -    private class ParameterizedTypeImpl implements ParameterizedType {
>>>> > -        private final Type rawType;
>>>> > -        private final Type[] types;
>>>> > -
>>>> > -        private ParameterizedTypeImpl(final Type raw, final Type... types) {
>>>> > -            this.rawType = raw;
>>>> > -            this.types = types;
>>>> > -        }
>>>> > -
>>>> > -        @Override
>>>> > -        public Type[] getActualTypeArguments() {
>>>> > -            return types.clone();
>>>> > -        }
>>>> > -
>>>> > -        @Override
>>>> > -        public Type getOwnerType() {
>>>> > -            return null;
>>>> > -        }
>>>> > -
>>>> > -        @Override
>>>> > -        public Type getRawType() {
>>>> > -            return rawType;
>>>> > -        }
>>>> > -
>>>> > -        @Override
>>>> > -        public int hashCode() {
>>>> > -            return Arrays.hashCode(types) ^ rawType.hashCode();
>>>> > -        }
>>>> > -
>>>> > -        @Override
>>>> > -        public boolean equals(final Object obj) {
>>>> > -            if (this == obj) {
>>>> > -                return true;
>>>> > -            }
>>>> > -            if (ParameterizedType.class.isInstance(obj)) {
>>>> > -                final ParameterizedType that = ParameterizedType.class.cast(obj);
>>>> > -                final Type thatRawType = that.getRawType();
>>>> > -                return (rawType == null ? thatRawType == null : rawType.equals(thatRawType))
>>>> > -                        && Arrays.equals(types, that.getActualTypeArguments());
>>>> > -            }
>>>> > -            return false;
>>>> > -        }
>>>> > +    public void shutdown(@Observes BeforeShutdown bsd) {
>>>> > +        DefaultConfigProvider.instance().releaseConfig(config);
>>>> > +    }
>>>> >
>>>> > -        @Override
>>>> > -        public String toString() {
>>>> > -            final StringBuilder buffer = new StringBuilder();
>>>> > -            buffer.append(Class.class.cast(rawType).getName());
>>>> > -            final Type[] actualTypes = getActualTypeArguments();
>>>> > -            if (actualTypes.length > 0) {
>>>> > -                buffer.append("<");
>>>> > -                final int length = actualTypes.length;
>>>> > -                for (int i = 0; i < length; i++) {
>>>> > -                    if (actualTypes[i] instanceof Class) {
>>>> > -                        buffer.append(((Class<?>) actualTypes[i]).getSimpleName());
>>>> > -                    } else {
>>>> > -                        buffer.append(actualTypes[i].toString());
>>>> > -                    }
>>>> > -                    if (i != actualTypes.length - 1) {
>>>> > -                        buffer.append(",");
>>>> > -                    }
>>>> > -                }
>>>> >
>>>> > -                buffer.append(">");
>>>> > -            }
>>>> > -            return buffer.toString();
>>>> > -        }
>>>> > +    static boolean isDefaultUnset(String defaultValue) {
>>>> > +        return defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);
>>>> >      }
>>>> >  }
>>>> >
>>>> > Modified: geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
>>>> > URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java?rev=1804397&r1=1804396&r2=1804397&view=diff
>>>> > ==============================================================================
>>>> > --- geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java (original)
>>>> > +++ geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java Tue Aug  8 10:55:56 2017
>>>> > @@ -16,49 +16,59 @@
>>>> >   */
>>>> >  package org.apache.geronimo.config.cdi;
>>>> >
>>>> > -import org.eclipse.microprofile.config.inject.ConfigProperty;
>>>> > +import java.io.IOException;
>>>> > +import java.io.Serializable;
>>>> > +import java.lang.annotation.Annotation;
>>>> > +import java.lang.reflect.ParameterizedType;
>>>> > +import java.lang.reflect.Type;
>>>> > +import java.util.Collections;
>>>> > +import java.util.HashSet;
>>>> > +import java.util.Optional;
>>>> > +import java.util.Set;
>>>> >
>>>> >  import javax.enterprise.context.Dependent;
>>>> >  import javax.enterprise.context.spi.CreationalContext;
>>>> > -import javax.enterprise.inject.Default;
>>>> >  import javax.enterprise.inject.spi.Annotated;
>>>> > +import javax.enterprise.inject.spi.AnnotatedMember;
>>>> > +import javax.enterprise.inject.spi.AnnotatedType;
>>>> >  import javax.enterprise.inject.spi.Bean;
>>>> > +import javax.enterprise.inject.spi.BeanManager;
>>>> >  import javax.enterprise.inject.spi.InjectionPoint;
>>>> >  import javax.enterprise.inject.spi.PassivationCapable;
>>>> >  import javax.enterprise.util.AnnotationLiteral;
>>>> > -import java.lang.annotation.Annotation;
>>>> > -import java.lang.reflect.Member;
>>>> > -import java.lang.reflect.ParameterizedType;
>>>> > -import java.lang.reflect.Type;
>>>> > -import java.util.Collections;
>>>> > -import java.util.HashSet;
>>>> > -import java.util.Set;
>>>> > +import javax.inject.Provider;
>>>> > +
>>>> > +import org.apache.geronimo.config.ConfigImpl;
>>>> > +import org.eclipse.microprofile.config.Config;
>>>> > +import org.eclipse.microprofile.config.ConfigProvider;
>>>> > +import org.eclipse.microprofile.config.inject.ConfigProperty;
>>>> > +import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
>>>> >
>>>> >  /**
>>>> >   * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
>>>> >   */
>>>> > -public abstract class ConfigInjectionBean<T> implements Bean<T>, PassivationCapable {
>>>> > +public class ConfigInjectionBean<T> implements Bean<T>, PassivationCapable {
>>>> >
>>>> >      private final static Set<Annotation> QUALIFIERS = new HashSet<>();
>>>> >      static {
>>>> >          QUALIFIERS.add(new ConfigPropertyLiteral());
>>>> >      }
>>>> >
>>>> > +    private final BeanManager bm;
>>>> >      private final Class rawType;
>>>> >      private final Set<Type> types;
>>>> > -    private final String id;
>>>> > -    private final boolean alternative;
>>>> > -
>>>> > -    ConfigInjectionBean(Type type) {
>>>> > -        this(type,false);
>>>> > -    }
>>>> >
>>>> > -    ConfigInjectionBean(Type type, boolean alternative) {
>>>> > -        this.types = new HashSet<>();
>>>> > -        this.types.add(type);
>>>> > -        this.rawType = getRawType(type);
>>>> > -        this.id = "ConfigInjectionBean_" + type.toString();
>>>> > -        this.alternative = alternative;
>>>> > +    /**
>>>> > +     * only access via {@link #getConfig(}
>>>> > +     */
>>>> > +    private Config _config;
>>>> > +
>>>> > +    public ConfigInjectionBean(BeanManager bm, Type type) {
>>>> > +        this.bm = bm;
>>>> > +
>>>> > +        types = new HashSet<>();
>>>> > +        types.add(type);
>>>> > +        rawType = getRawType(type);
>>>> >      }
>>>> >
>>>> >      private Class getRawType(Type type) {
>>>> > @@ -76,7 +86,7 @@ public abstract class ConfigInjectionBea
>>>> >
>>>> >      @Override
>>>> >      public Set<InjectionPoint> getInjectionPoints() {
>>>> > -        return Collections.emptySet();
>>>> > +        return Collections.EMPTY_SET;
>>>> >      }
>>>> >
>>>> >      @Override
>>>> > @@ -90,8 +100,90 @@ public abstract class ConfigInjectionBea
>>>> >      }
>>>> >
>>>> >      @Override
>>>> > +    public T create(CreationalContext<T> context) {
>>>> > +        Set<Bean<?>> beans = bm.getBeans(InjectionPoint.class);
>>>> > +        Bean<?> bean = bm.resolve(beans);
>>>> > +        InjectionPoint ip = (InjectionPoint) bm.getReference(bean, InjectionPoint.class,  context);
>>>> > +        if (ip == null) {
>>>> > +            throw new IllegalStateException("Could not retrieve InjectionPoint");
>>>> > +        }
>>>> > +        Annotated annotated = ip.getAnnotated();
>>>> > +        ConfigProperty configProperty = annotated.getAnnotation(ConfigProperty.class);
>>>> > +        String key = getConfigKey(ip, configProperty);
>>>> > +        String defaultValue = configProperty.defaultValue();
>>>> > +
>>>> > +        if (annotated.getBaseType() instanceof ParameterizedType) {
>>>> > +            ParameterizedType paramType = (ParameterizedType) annotated.getBaseType();
>>>> > +            Type rawType = paramType.getRawType();
>>>> > +
>>>> > +            // handle Provider<T>
>>>> > +            if (rawType instanceof Class && ((Class) rawType).isAssignableFrom(Provider.class) && paramType.getActualTypeArguments().length == 1) {
>>>> > +                Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
>>>> > +                return (T) new ConfigValueProvider(getConfig(), key, clazz);
>>>> > +            }
>>>> > +
>>>> > +            // handle Optional<T>
>>>> > +            if (rawType instanceof Class && ((Class) rawType).isAssignableFrom(Optional.class) && paramType.getActualTypeArguments().length == 1) {
>>>> > +                Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
>>>> > +                return (T) getConfig().getOptionalValue(key, clazz);
>>>> > +            }
>>>> > +        }
>>>> > +        else {
>>>> > +            Class clazz = (Class) annotated.getBaseType();
>>>> > +            if (ConfigExtension.isDefaultUnset(defaultValue)) {
>>>> > +                return (T) getConfig().getValue(key, clazz);
>>>> > +            }
>>>> > +            else {
>>>> > +                Config config = getConfig();
>>>> > +                return (T) config.getOptionalValue(key, clazz)
>>>> > +                        .orElse(((ConfigImpl) config).convert(defaultValue, clazz));
>>>> > +            }
>>>> > +        }
>>>> > +
>>>> > +        throw new IllegalStateException("unhandled ConfigProperty");
>>>> > +    }
>>>> > +
>>>> > +
>>>> > +    /**
>>>> > +     * Get the property key to use.
>>>> > +     * In case the {@link ConfigProperty#name()} is empty we will try to determine the key name from the InjectionPoint.
>>>> > +     */
>>>> > +    public static String getConfigKey(InjectionPoint ip, ConfigProperty configProperty) {
>>>> > +        String key = configProperty.name();
>>>> > +        if (key.length() > 0) {
>>>> > +            return key;
>>>> > +        }
>>>> > +        if (ip.getAnnotated() instanceof AnnotatedMember) {
>>>> > +            AnnotatedMember member = (AnnotatedMember) ip.getAnnotated();
>>>> > +            AnnotatedType declaringType = member.getDeclaringType();
>>>> > +            if (declaringType != null) {
>>>> > +                String[] parts = declaringType.getJavaClass().getCanonicalName().split("\\.");
>>>> > +                String cn = parts[parts.length-1];
>>>> > +                parts[parts.length-1] = Character.toLowerCase(cn.charAt(0)) + (cn.length() > 1 ? cn.substring(1) : "");
>>>> > +                StringBuilder sb = new StringBuilder(parts[0]);
>>>> > +                for (int i = 1; i < parts.length; i++) {
>>>> > +                    sb.append(".").append(parts[i]);
>>>> > +                }
>>>> > +
>>>> > +                // now add the field name
>>>> > +                sb.append(".").append(member.getJavaMember().getName());
>>>> > +                return sb.toString();
>>>> > +            }
>>>> > +        }
>>>> > +
>>>> > +        throw new IllegalStateException("Could not find default name for @ConfigProperty InjectionPoint " + ip);
>>>> > +    }
>>>> > +
>>>> > +    public Config getConfig() {
>>>> > +        if (_config == null) {
>>>> > +            _config = ConfigProvider.getConfig();
>>>> > +        }
>>>> > +        return _config;
>>>> > +    }
>>>> > +
>>>> > +    @Override
>>>> >      public void destroy(T instance, CreationalContext<T> context) {
>>>> > -        // no-op
>>>> > +
>>>> >      }
>>>> >
>>>> >      @Override
>>>> > @@ -116,21 +208,17 @@ public abstract class ConfigInjectionBea
>>>> >
>>>> >      @Override
>>>> >      public Set<Class<? extends Annotation>> getStereotypes() {
>>>> > -        return Collections.emptySet();
>>>> > +        return Collections.EMPTY_SET;
>>>> >      }
>>>> >
>>>> >      @Override
>>>> >      public boolean isAlternative() {
>>>> > -        return alternative;
>>>> > +        return true;
>>>> >      }
>>>> >
>>>> >      @Override
>>>> >      public String getId() {
>>>> > -        return id;
>>>> > -    }
>>>> > -
>>>> > -    InjectionPoint getSimpleInjectionPoint() {
>>>> > -        return simpleInjectionPoint;
>>>> > +        return "ConfigInjectionBean_" + rawType.getName();
>>>> >      }
>>>> >
>>>> >      private static class ConfigPropertyLiteral extends AnnotationLiteral<ConfigProperty> implements ConfigProperty {
>>>> > @@ -145,41 +233,31 @@ public abstract class ConfigInjectionBea
>>>> >          }
>>>> >      }
>>>> >
>>>> > -    private final InjectionPoint simpleInjectionPoint = new InjectionPoint() {
>>>> > -
>>>> > -        @Override
>>>> > -        public boolean isTransient() {
>>>> > -            return false;
>>>> > -        }
>>>> > -
>>>> > -        @Override
>>>> > -        public boolean isDelegate() {
>>>> > -            return false;
>>>> > -        }
>>>> > -
>>>> > -        @Override
>>>> > -        public Type getType() {
>>>> > -            return InjectionPoint.class;
>>>> > -        }
>>>> > -
>>>> > -        @Override
>>>> > -        public Set<Annotation> getQualifiers() {
>>>> > -            return Collections.singleton(new AnnotationLiteral<Default>() {});
>>>> > -        }
>>>> > -
>>>> > -        @Override
>>>> > -        public Member getMember() {
>>>> > -            return null;
>>>> > +    /**
>>>> > +     * A special Provider&lt;T&gt;
>>>> > +     * This concrete class is needed because we need the injected Provider for the ConfigProperty
>>>> > +     * to be Serializable. A Lambda would not work in this case
>>>> > +     */
>>>> > +    public static class ConfigValueProvider<T> implements Provider<T>, Serializable {
>>>> > +        private transient Config config;
>>>> > +        private final String key;
>>>> > +        private final Class<T> type;
>>>> > +
>>>> > +        ConfigValueProvider(Config config, String key, Class<T> type) {
>>>> > +            this.config = config;
>>>> > +            this.key = key;
>>>> > +            this.type = type;
>>>> >          }
>>>> >
>>>> >          @Override
>>>> > -        public Bean<?> getBean() {
>>>> > -            return ConfigInjectionBean.this;
>>>> > +        public T get() {
>>>> > +            return (T) config.getValue(key, type);
>>>> > +        }
>>>> > +
>>>> > +        private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
>>>> > +            in.defaultReadObject();
>>>> > +            config = ConfigProviderResolver.instance().getConfig();
>>>> >          }
>>>> >
>>>> > -        @Override
>>>> > -        public Annotated getAnnotated() {
>>>> > -            return null;
>>>> > -        }
>>>> > -    };
>>>> > +    }
>>>> >  }
>>>> >
>>>> > Modified: geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
>>>> > URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java?rev=1804397&r1=1804396&r2=1804397&view=diff
>>>> > ==============================================================================
>>>> > --- geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java (original)
>>>> > +++ geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java Tue Aug  8 10:55:56 2017
>>>> > @@ -33,9 +33,12 @@ import org.testng.annotations.Test;
>>>> >
>>>> >  public class ProviderTest extends Arquillian {
>>>> >      private static final String SOME_KEY = "org.apache.geronimo.config.test.internal.somekey";
>>>> > +    private static final String ANOTHER_KEY = "org.apache.geronimo.config.test.internal.anotherkey";
>>>> >
>>>> >      @Deployment
>>>> >      public static WebArchive deploy() {
>>>> > +        System.setProperty(SOME_KEY, "someval");
>>>> > +        System.setProperty(ANOTHER_KEY, "someval");
>>>> >          JavaArchive testJar = ShrinkWrap
>>>> >                  .create(JavaArchive.class, "configProviderTest.jar")
>>>> >                  .addClasses(ProviderTest.class, SomeBean.class)
>>>> > @@ -70,8 +73,16 @@ public class ProviderTest extends Arquil
>>>> >          @ConfigProperty(name=SOME_KEY)
>>>> >          private Provider<String> myconfig;
>>>> >
>>>> > +        @Inject
>>>> > +        @ConfigProperty(name=ANOTHER_KEY)
>>>> > +        private Provider<String> anotherconfig;
>>>> > +
>>>> >          public String getMyconfig() {
>>>> >              return myconfig.get();
>>>> >          }
>>>> > +
>>>> > +        public Provider<String> getAnotherconfig() {
>>>> > +            return anotherconfig;
>>>> > +        }
>>>> >      }
>>>> >  }
>>>> >
>>>> > Modified: geronimo/components/config/trunk/pom.xml
>>>> > URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/pom.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
>>>> > ==============================================================================
>>>> > --- geronimo/components/config/trunk/pom.xml (original)
>>>> > +++ geronimo/components/config/trunk/pom.xml Tue Aug  8 10:55:56 2017
>>>> > @@ -27,7 +27,7 @@
>>>> >      </parent>
>>>> >
>>>> >      <groupId>org.apache.geronimo.config</groupId>
>>>> > -    <artifactId>config-parent</artifactId>
>>>> > +    <artifactId>geronimo-config</artifactId>
>>>> >      <version>1.1-SNAPSHOT</version>
>>>> >      <packaging>pom</packaging>
>>>> >      <name>Geronimo Microprofile Configuration</name>
>>>> > @@ -50,7 +50,7 @@
>>>> >      <properties>
>>>> >          <maven.compiler.source>1.8</maven.compiler.source>
>>>> >          <maven.compiler.target>1.8</maven.compiler.target>
>>>> > -        <microprofile-config.version>1.1-SNAPSHOT</microprofile-config.version>
>>>> > +        <microprofile-config.version>1.0</microprofile-config.version>
>>>> >          <owb.version>1.7.3</owb.version>
>>>> >          <owb2.version>2.0.1-SNAPSHOT</owb2.version>
>>>> >          <arquillian.version>1.1.13.Final</arquillian.version>
>>>> >
>>>> >
>>>> 
>>>> 

Re: svn commit: r1804397 - in /geronimo/components/config/trunk: ./ impl/ impl/src/main/java/org/apache/geronimo/config/cdi/ impl/src/test/java/org/apache/geronimo/config/test/internal/

Posted by "John D. Ament" <jo...@apache.org>.
Ok, I got tests passing on all three.  It actually looks like its simpler
(and more correct) to not use a custom provider.  The provider approach
wasn't supporting default values.  I've committed changes, please take a
look and hopefully we can plan to reroll 1.0.

John

On Tue, Aug 8, 2017 at 10:02 PM John D. Ament <jo...@apache.org> wrote:

> Ok, I've readded some of the Weld3 support, 3 tests are failing.
>
> Some interesting notes:
>
> - If I remove Provider support, it generally works.  However, I suddenly
> get duplicate beans of type Provider, which is confusing (but probably
> because of the alternative flag).
> - I can get everything to pass in Weld, and 1 test failure in in OWB with
> the following:
>
> - Set alternative = false
> - Remove Provider from the types
> - Remove the filter on types to check if class.
> - Change getId to use all of the types (makes a better toString)
>
>
> If we can figure out the alternative issue with OWB, we'll be good to go
> again.
>
> John
>
> On Tue, Aug 8, 2017 at 8:44 AM John D. Ament <jo...@apache.org>
> wrote:
>
>> I can get to some of it.
>>
>> We have a couple of issues now though:
>>
>> https://issues.jboss.org/browse/WELD-2411
>> https://issues.jboss.org/browse/CDI-712
>>
>> Martin doesn't feel the spec allows you to override Provider impl's.
>> Please feel free to weigh in :-)
>>
>> John
>>
>>
>> On Tue, Aug 8, 2017 at 7:33 AM Mark Struberg <st...@yahoo.de> wrote:
>>
>>> Oh I see what you mean.
>>> Do you mind to re-apply your fix or should I?
>>>
>>> Btw, I also tested with the -PWeld3 but I was not able to resolve
>>> arquillian-weld-embedded:jar:2.0.0-SNAPSHOT
>>> We might need to add a <repository> for it in the Weld3 profile.
>>>
>>> I also would love to add a Weld profile. I thought we have this already
>>> but seems we missed it?
>>>
>>> txs and LieGrue,
>>> strub
>>>
>>> > Am 08.08.2017 um 12:58 schrieb John D. Ament <jo...@apache.org>:
>>> >
>>> > One note - hardcoding "isAlternative" to true breaks in Weld.  Unless
>>> there is a base bean of same type, the alternative is ignored.  Hence why I
>>> only did isAlternative on the provider type, all others are just regular
>>> beans.
>>> >
>>> > John
>>> >
>>> > On Tue, Aug 8, 2017 at 6:55 AM <st...@apache.org> wrote:
>>> > Author: struberg
>>> > Date: Tue Aug  8 10:55:56 2017
>>> > New Revision: 1804397
>>> >
>>> > URL: http://svn.apache.org/viewvc?rev=1804397&view=rev
>>> > Log:
>>> > GERONIMO-6577 move back to a more dynamic version
>>> >
>>> > The goal of r1800748 to calculate all information upfront could not be
>>> achieved
>>> > so we move back to the old version
>>> >
>>> > Modified:
>>> >     geronimo/components/config/trunk/impl/debug-suite.xml
>>> >     geronimo/components/config/trunk/impl/pom.xml
>>> >
>>>  geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
>>> >
>>>  geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
>>> >
>>>  geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
>>> >     geronimo/components/config/trunk/pom.xml
>>> >
>>> > Modified: geronimo/components/config/trunk/impl/debug-suite.xml
>>> > URL:
>>> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/debug-suite.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
>>> >
>>> ==============================================================================
>>> > --- geronimo/components/config/trunk/impl/debug-suite.xml (original)
>>> > +++ geronimo/components/config/trunk/impl/debug-suite.xml Tue Aug  8
>>> 10:55:56 2017
>>> > @@ -24,7 +24,7 @@
>>> >      <classes>
>>> >          <!-- Issues in the spec -->
>>> >          <!-- CDI-437 -->
>>> > -        <class
>>> name="org.eclipse.microprofile.config.tck.CdiOptionalInjectionTest">
>>> > +        <class
>>> name="org.eclipse.microprofile.config.tck.CDIPlainInjectionTest">
>>> >              <methods>
>>> >                  <include name=".*"/>
>>> >              </methods>
>>> >
>>> > Modified: geronimo/components/config/trunk/impl/pom.xml
>>> > URL:
>>> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/pom.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
>>> >
>>> ==============================================================================
>>> > --- geronimo/components/config/trunk/impl/pom.xml (original)
>>> > +++ geronimo/components/config/trunk/impl/pom.xml Tue Aug  8 10:55:56
>>> 2017
>>> > @@ -27,7 +27,6 @@
>>> >      </parent>
>>> >
>>> >      <artifactId>geronimo-config-impl</artifactId>
>>> > -    <name>Geronimo Microprofile Configuration :: Implementation</name>
>>> >
>>> >      <dependencyManagement>
>>> >          <dependencies>
>>> >
>>> > Modified:
>>> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
>>> > URL:
>>> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java?rev=1804397&r1=1804396&r2=1804397&view=diff
>>> >
>>> ==============================================================================
>>> > ---
>>> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
>>> (original)
>>> > +++
>>> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
>>> Tue Aug  8 10:55:56 2017
>>> > @@ -16,54 +16,38 @@
>>> >   */
>>> >  package org.apache.geronimo.config.cdi;
>>> >
>>> > -import org.apache.geronimo.config.ConfigImpl;
>>> > -import org.eclipse.microprofile.config.Config;
>>> > -import org.eclipse.microprofile.config.inject.ConfigProperty;
>>> > -import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
>>> > +import java.lang.reflect.Type;
>>> > +import java.util.ArrayList;
>>> > +import java.util.HashMap;
>>> > +import java.util.HashSet;
>>> > +import java.util.List;
>>> > +import java.util.Map;
>>> > +import java.util.Optional;
>>> > +import java.util.Set;
>>> > +import java.util.stream.Collectors;
>>> >
>>> > -import javax.enterprise.context.spi.CreationalContext;
>>> >  import javax.enterprise.event.Observes;
>>> >  import javax.enterprise.inject.spi.AfterBeanDiscovery;
>>> >  import javax.enterprise.inject.spi.AfterDeploymentValidation;
>>> > -import javax.enterprise.inject.spi.AnnotatedMember;
>>> > -import javax.enterprise.inject.spi.AnnotatedType;
>>> >  import javax.enterprise.inject.spi.BeanManager;
>>> > -import javax.enterprise.inject.spi.BeforeBeanDiscovery;
>>> >  import javax.enterprise.inject.spi.BeforeShutdown;
>>> > +import javax.enterprise.inject.spi.DeploymentException;
>>> >  import javax.enterprise.inject.spi.Extension;
>>> >  import javax.enterprise.inject.spi.InjectionPoint;
>>> >  import javax.enterprise.inject.spi.ProcessInjectionPoint;
>>> >  import javax.inject.Provider;
>>> > -import java.lang.reflect.ParameterizedType;
>>> > -import java.lang.reflect.Type;
>>> > -import java.util.ArrayList;
>>> > -import java.util.Arrays;
>>> > -import java.util.Collection;
>>> > -import java.util.HashMap;
>>> > -import java.util.HashSet;
>>> > -import java.util.List;
>>> > -import java.util.Map;
>>> > -import java.util.Objects;
>>> > -import java.util.Optional;
>>> > -import java.util.Set;
>>> > -import java.util.function.BiFunction;
>>> > -import java.util.stream.Stream;
>>> >
>>> > -import static java.util.function.Function.identity;
>>> > -import static java.util.stream.Collectors.toMap;
>>> > -import static
>>> org.eclipse.microprofile.config.ConfigProvider.getConfig;
>>> > +import org.apache.geronimo.config.DefaultConfigProvider;
>>> > +import org.eclipse.microprofile.config.Config;
>>> > +import org.eclipse.microprofile.config.ConfigProvider;
>>> > +import org.eclipse.microprofile.config.inject.ConfigProperty;
>>> >
>>> >  /**
>>> >   * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
>>> >   */
>>> >  public class ConfigExtension implements Extension {
>>> > -    private static final Object NULL = new Object();
>>> > -
>>> >      private Config config;
>>> > -    private ConfigProviderResolver resolver;
>>> >
>>> > -    private Set<Injection> injections = new HashSet<>();
>>> > -    private List<Throwable> deploymentProblems = new ArrayList<>();
>>> >      private static final Map<Type, Type> REPLACED_TYPES = new
>>> HashMap<>();
>>> >
>>> >      static {
>>> > @@ -74,336 +58,65 @@ public class ConfigExtension implements
>>> >          REPLACED_TYPES.put(boolean.class, Boolean.class);
>>> >      }
>>> >
>>> > -    void init(@Observes final BeforeBeanDiscovery
>>> beforeBeanDiscovery, final BeanManager bm) {
>>> > -        resolver = ConfigProviderResolver.instance();
>>> > -        config = getConfig();
>>> > -    }
>>> > +    private Set<InjectionPoint> injectionPoints = new HashSet<>();
>>> > +
>>> >
>>> >      public void collectConfigProducer(@Observes
>>> ProcessInjectionPoint<?, ?> pip) {
>>> > -        final InjectionPoint injectionPoint = pip.getInjectionPoint();
>>> > -        final ConfigProperty configProperty =
>>> injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class);
>>> > +        ConfigProperty configProperty =
>>> pip.getInjectionPoint().getAnnotated().getAnnotation(ConfigProperty.class);
>>> >          if (configProperty != null) {
>>> > -            Type replacedType =
>>> REPLACED_TYPES.getOrDefault(injectionPoint.getType(),
>>> injectionPoint.getType());
>>> > -            Injection injection = new Injection(replacedType);
>>> > -            final String key = getConfigKey(injectionPoint,
>>> configProperty);
>>> > -            final boolean defaultUnset =
>>> isDefaultUnset(configProperty.defaultValue());
>>> > -            if (!injections.add(injection)) {
>>> > -                final Injection ref = injection;
>>> > -                injection = injections.stream().filter(i ->
>>> i.equals(ref)).findFirst().get();
>>> > -            }
>>> > -            injection.keys.add(key);
>>> > -
>>> injection.defaultValues.add(configProperty.defaultValue());
>>> > -
>>> > -            final ConfigImpl configImpl = unwrapConfig();
>>> > -
>>> > -            // what about lazy runtime lookup, not consistent with
>>> tck and system prop usage, for now assume optional=optional ;)
>>> > -            boolean hasValue = true;
>>> > -            if (defaultUnset) { // value validation
>>> > -                if
>>> (ParameterizedType.class.isInstance(injection.type)) {
>>> > -                    final ParameterizedType pt =
>>> ParameterizedType.class.cast(injection.type);
>>> > -                    if (pt.getRawType() != Optional.class &&
>>> !configImpl.getOptionalValue(key, String.class).isPresent()) {
>>> > -                        hasValue = false;
>>> > -                    }
>>> > -                } else if (!configImpl.getOptionalValue(key,
>>> String.class).isPresent()) {
>>> > -                    hasValue = false;
>>> > -                }
>>> > -                if (!hasValue) {
>>> > -                    deploymentProblems.add(new
>>> IllegalArgumentException("No configured value for '" + key + "' from " +
>>> injectionPoint));
>>> > -                }
>>> > -            }
>>> > -
>>> > -            Class<?> instanceType = null;
>>> > -            if (ParameterizedType.class.isInstance(injection.type)) {
>>> // converters validation
>>> > -                final ParameterizedType pt =
>>> ParameterizedType.class.cast(injection.type);
>>> > -                if (pt.getRawType() == Provider.class &&
>>> pt.getActualTypeArguments().length == 1 &&
>>> Class.class.isInstance(pt.getActualTypeArguments()[0])
>>> > -                        &&
>>> !configImpl.getConverters().containsKey(Class.class.cast(pt.getActualTypeArguments()[0])))
>>> {
>>> > -                    instanceType =
>>> Class.class.cast(pt.getActualTypeArguments()[0]);
>>> > -                } // else if Optional it is fine, else we don't know
>>> how to process
>>> > -            } else if (Class.class.isInstance(injection.type)) {
>>> > -                instanceType = Class.class.cast(injection.type);
>>> > -            }
>>> > -            if (instanceType != null) { // validate we have a
>>> converter + we can convert the existing value
>>> > -                if
>>> (!configImpl.getConverters().containsKey(instanceType)) {
>>> > -                    deploymentProblems.add(new
>>> IllegalArgumentException("Missing converter for '" + key + "' from " +
>>> injectionPoint));
>>> > -                } else if (hasValue) {
>>> > -                    try {
>>> > -
>>> configImpl.getConverters().get(injection.type).convert(configImpl.getValue(key));
>>> > -                    } catch (final RuntimeException re) {
>>> > -                        deploymentProblems.add(re);
>>> > -                    }
>>> > -                }
>>> > -            }
>>> > +            injectionPoints.add(pip.getInjectionPoint());
>>> >          }
>>> >      }
>>> >
>>> >      public void registerConfigProducer(@Observes AfterBeanDiscovery
>>> abd, BeanManager bm) {
>>> > -        injections.stream()
>>> > -                .flatMap(injection -> {
>>> > -                    final BiFunction<CreationalContext<?>,
>>> ConfigInjectionBean<?>, String> keyProvider;
>>> > -                    if (injection.keys.size() == 1) {
>>> > -                        final String key =
>>> injection.keys.iterator().next();
>>> > -                        keyProvider = (ctx, bean) -> key;
>>> > -                    } else {
>>> > -                        keyProvider = (ctx, bean) ->
>>> getName(findInjectionPoint(bm, ctx, bean));
>>> > -                    }
>>> > -
>>> > -                    if
>>> (ParameterizedType.class.isInstance(injection.type)) {
>>> > -                        final ParameterizedType paramType =
>>> ParameterizedType.class.cast(injection.type);
>>> > -                        final Type rawType = paramType.getRawType();
>>> > -
>>> > -                        // todo: do we care of Instance injection?
>>> doesnt make much sense right?
>>> > -                        if (Provider.class == rawType &&
>>> paramType.getActualTypeArguments().length == 1) {
>>> > -                            if
>>> (!Class.class.isInstance(paramType.getActualTypeArguments()[0])) {
>>> > -                                deploymentProblems.add(new
>>> IllegalArgumentException("@ConfigProperty can only be used with Provider<T>
>>> where T is a Class"));
>>> > -                                return Stream.empty();
>>> > -                            }
>>> > -                            final Class<?> providerType =
>>> Class.class.cast(paramType.getActualTypeArguments()[0]);
>>> > -                            return Stream.of(new
>>> ConfigInjectionBean<Provider<?>>(injection.type, true) {
>>> > -                                @Override
>>> > -                                public Provider<?> create(final
>>> CreationalContext<Provider<?>> context) {
>>> > -                                    return () ->
>>> config.getValue(keyProvider.apply(context, this), providerType);
>>> > -                                }
>>> > -                            });
>>> > -                        } else if (Optional.class == rawType &&
>>> paramType.getActualTypeArguments().length == 1) {
>>> > -                            if
>>> (!Class.class.isInstance(paramType.getActualTypeArguments()[0])) {
>>> > -                                deploymentProblems.add(new
>>> IllegalArgumentException("@ConfigProperty can only be used with Optional<T>
>>> where T is a Class"));
>>> > -                                return null;
>>> > -                            }
>>> > -                            final Class<?> optionalType =
>>> Class.class.cast(paramType.getActualTypeArguments()[0]);
>>> > -                            return Stream.of(new
>>> ConfigInjectionBean<Optional<?>>(injection.type) {
>>> > -                                @Override
>>> > -                                public Optional<?> create(final
>>> CreationalContext<Optional<?>> context) {
>>> > -                                    return
>>> config.getOptionalValue(keyProvider.apply(context, this), optionalType);
>>> > -                                }
>>> > -                            });
>>> > -                        } else {
>>> > -                            deploymentProblems.add(new
>>> IllegalArgumentException("Unsupported parameterized type " + paramType));
>>> > -                            return Stream.empty();
>>> > -                        }
>>> > -                    } else if
>>> (Class.class.isInstance(injection.type)) {
>>> > -                        final Class clazz =
>>> Class.class.cast(injection.type);
>>> > -                        final ConfigInjectionBean bean;
>>> > -                        if (injection.defaultValues.isEmpty()) {
>>> > -                            bean = new
>>> ConfigInjectionBean<Object>(injection.type) {
>>> > -                                @Override
>>> > -                                public Object create(final
>>> CreationalContext<Object> context) {
>>> > -                                    return
>>> config.getOptionalValue(keyProvider.apply(context, this), clazz);
>>> > -                                }
>>> > -                            };
>>> > -                        } else if (injection.defaultValues.size() ==
>>> 1) { // common enough to be optimized
>>> > -                            final String defVal =
>>> injection.defaultValues.iterator().next();
>>> > -                            final Object alternativeVal =
>>> isDefaultUnset(defVal) ? null : unwrapConfig().convert(defVal, clazz);
>>> > -                            bean = new
>>> ConfigInjectionBean<Object>(injection.type) {
>>> > -                                @Override
>>> > -                                public Object create(final
>>> CreationalContext<Object> context) {
>>> > -                                    final Optional optionalValue =
>>> config.getOptionalValue(keyProvider.apply(context, this), clazz);
>>> > -                                    return
>>> optionalValue.orElse(alternativeVal);
>>> > -                                }
>>> > -                            };
>>> > -                        } else { // sadly we need to get back to the
>>> injection point to know which one we need to use
>>> > -                            final Map<String, Object> prepared =
>>> injection.defaultValues.stream()
>>> > -                                    .collect(toMap(identity(), k ->
>>> isDefaultUnset(k) ? NULL : unwrapConfig().convert(k, clazz), (a, b) -> b));
>>> > -                            bean = new
>>> ConfigInjectionBean<Object>(injection.type) {
>>> > -                                @Override
>>> > -                                public Object create(final
>>> CreationalContext<Object> context) {
>>> > -                                    final InjectionPoint ip =
>>> findInjectionPoint(bm, context, this);
>>> > -                                    if (ip == null) {
>>> > -                                        throw new
>>> IllegalStateException("Could not retrieve InjectionPoint");
>>> > -                                    }
>>> > -                                    return
>>> config.getOptionalValue(ConfigExtension.this.getName(ip), clazz)
>>> > -                                            .orElseGet(() -> {
>>> > -                                                final Object val =
>>> prepared.get(ip.getAnnotated().getAnnotation(ConfigProperty.class).defaultValue());
>>> > -                                                return val == NULL ?
>>> null : val;
>>> > -                                            });
>>> > -                                }
>>> > -                            };
>>> > -                        }
>>> > -
>>> > -                        final Collection<ConfigInjectionBean<?>>
>>> beans = new ArrayList<>();
>>> > -                        beans.add(bean);
>>> > -
>>> > -                        // is adding these beans is that useful? we
>>> captured them all so only a programmatic lookup would justify it
>>> > -                        // and not sure it would be done this way
>>> anyway
>>> > -                        final ParameterizedTypeImpl providerType =
>>> new ParameterizedTypeImpl(Provider.class, injection.type);
>>> > -                        if (injections.stream().noneMatch(i ->
>>> i.type.equals(providerType))) {
>>> > -                            beans.add(new
>>> ConfigInjectionBean<Provider<?>>(providerType, true) {
>>> > -                                @Override
>>> > -                                public Provider<?> create(final
>>> CreationalContext<Provider<?>> context) {
>>> > -                                    return () -> bean.create(context);
>>> > -                                }
>>> > -                            });
>>> > -                        }
>>> > -
>>> > -                        final ParameterizedTypeImpl optionalType =
>>> new ParameterizedTypeImpl(Optional.class, injection.type);
>>> > -                        if (injections.stream().noneMatch(i ->
>>> i.type.equals(optionalType))) {
>>> > -                            beans.add(new
>>> ConfigInjectionBean<Optional<?>>(optionalType) {
>>> > -                                @Override
>>> > -                                public Optional<?> create(final
>>> CreationalContext<Optional<?>> context) {
>>> > -                                    return
>>> Optional.ofNullable(bean.create(context));
>>> > -                                }
>>> > -                            });
>>> > -                        }
>>> > -
>>> > -                        return beans.stream();
>>> > -                    } else {
>>> > -                        deploymentProblems.add(new
>>> IllegalArgumentException("Unknown type " + injection.type));
>>> > -                        return Stream.empty();
>>> > -                    }
>>> > -                })
>>> > -                .forEach(abd::addBean);
>>> > -    }
>>> > +        Set<Class> types = injectionPoints.stream()
>>> > +                .filter(ip -> ip.getType() instanceof Class)
>>> > +                .map(ip -> (Class)
>>> REPLACED_TYPES.getOrDefault(ip.getType(), ip.getType()))
>>> > +                .collect(Collectors.toSet());
>>> > +
>>> > +        // Provider and Optional are ParameterizedTypes and not a
>>> Class, so we need to add them manually
>>> > +        types.add(Provider.class);
>>> > +        types.add(Optional.class);
>>> >
>>> > -    public void validate(@Observes AfterDeploymentValidation add) {
>>> > -        deploymentProblems.forEach(add::addDeploymentProblem);
>>> > -        injections.clear();
>>> > -        deploymentProblems.clear();
>>> > +        types.forEach(type -> abd.addBean(new ConfigInjectionBean(bm,
>>> type)));
>>> >      }
>>> >
>>> > -    public void shutdown(@Observes BeforeShutdown bsd) {
>>> > -        resolver.releaseConfig(config);
>>> > -    }
>>> > +    public void validate(@Observes AfterDeploymentValidation add) {
>>> > +        List<String> deploymentProblems = new ArrayList<>();
>>> >
>>> > -    private ConfigImpl unwrapConfig() {
>>> > -        return ConfigImpl.class.cast(config);
>>> > -    }
>>> > +        config = ConfigProvider.getConfig();
>>> >
>>> > -    private static String getName(final InjectionPoint ip) {
>>> > -        final ConfigProperty annotation =
>>> ip.getAnnotated().getAnnotation(ConfigProperty.class);
>>> > -        final String name = annotation.name();
>>> > -        return isDefaultUnset(name) ? getConfigKey(ip, annotation) :
>>> name;
>>> > -    }
>>> > +        for (InjectionPoint injectionPoint : injectionPoints) {
>>> > +            Type type = injectionPoint.getType();
>>> >
>>> > -    /**
>>> > -     * Get the property key to use.
>>> > -     * In case the {@link ConfigProperty#name()} is empty we will try
>>> to determine the key name from the InjectionPoint.
>>> > -     */
>>> > -    private static String getConfigKey(InjectionPoint ip,
>>> ConfigProperty configProperty) {
>>> > -        String key = configProperty.name();
>>> > -        if (!key.isEmpty()) {
>>> > -            return key;
>>> > -        }
>>> > -        if (ip.getAnnotated() instanceof AnnotatedMember) {
>>> > -            AnnotatedMember member = (AnnotatedMember)
>>> ip.getAnnotated();
>>> > -            AnnotatedType declaringType = member.getDeclaringType();
>>> > -            if (declaringType != null) {
>>> > -                String[] parts =
>>> declaringType.getJavaClass().getCanonicalName().split("\\.");
>>> > -                String cn = parts[parts.length - 1];
>>> > -                parts[parts.length - 1] =
>>> Character.toLowerCase(cn.charAt(0)) + (cn.length() > 1 ? cn.substring(1) :
>>> "");
>>> > -                StringBuilder sb = new StringBuilder(parts[0]);
>>> > -                for (int i = 1; i < parts.length; i++) {
>>> > -                    sb.append(".").append(parts[i]);
>>> > +            // replace native types with their Wrapper types
>>> > +            type = REPLACED_TYPES.getOrDefault(type, type);
>>> > +
>>> > +            ConfigProperty configProperty =
>>> injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class);
>>> > +            if (type instanceof Class) {
>>> > +                // a direct injection of a ConfigProperty
>>> > +                // that means a Converter must exist.
>>> > +                String key =
>>> ConfigInjectionBean.getConfigKey(injectionPoint, configProperty);
>>> > +                if ((isDefaultUnset(configProperty.defaultValue()))
>>> > +                        && !config.getOptionalValue(key, (Class)
>>> type).isPresent()) {
>>> > +                    deploymentProblems.add("No Config Value exists
>>> for " + key);
>>> >                  }
>>> > -
>>> > -                // now add the field name
>>> > -
>>> sb.append(".").append(member.getJavaMember().getName());
>>> > -                return sb.toString();
>>> >              }
>>> >          }
>>> >
>>> > -        throw new IllegalStateException("Could not find default name
>>> for @ConfigProperty InjectionPoint " + ip);
>>> > -    }
>>> > -
>>> > -    private static boolean isDefaultUnset(String defaultValue) {
>>> > -        return defaultValue == null || defaultValue.length() == 0 ||
>>> defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);
>>> > -    }
>>> > -
>>> > -    private static InjectionPoint findInjectionPoint(final
>>> BeanManager bm, final CreationalContext<?> ctx,
>>> > -
>>>  ConfigInjectionBean bean) {
>>> > -        return
>>> InjectionPoint.class.cast(bm.getInjectableReference(bean.getSimpleInjectionPoint(),
>>> ctx));
>>> > -    }
>>> > -
>>> > -    private static final class Injection {
>>> > -        private final Type type;
>>> > -        private final Collection<String> keys = new ArrayList<>();
>>> > -        private final Collection<String> defaultValues = new
>>> ArrayList<>();
>>> > -
>>> > -        private Injection(final Type type) {
>>> > -            this.type = type;
>>> > -        }
>>> > -
>>> > -        @Override
>>> > -        public boolean equals(final Object o) {
>>> > -            if (this == o) {
>>> > -                return true;
>>> > -            }
>>> > -            if (o == null || Injection.class != o.getClass()) {
>>> > -                return false;
>>> > -            }
>>> > -            final Injection injection = Injection.class.cast(o);
>>> > -            return Objects.equals(type, injection.type);
>>> > +        if (!deploymentProblems.isEmpty()) {
>>> > +            add.addDeploymentProblem(new DeploymentException("Error
>>> while validating Configuration\n"
>>> > +                                                             +
>>> String.join("\n", deploymentProblems)));
>>> >          }
>>> >
>>> > -        @Override
>>> > -        public int hashCode() {
>>> > -            return type.hashCode();
>>> > -        }
>>> >      }
>>> >
>>> > -    private class ParameterizedTypeImpl implements ParameterizedType {
>>> > -        private final Type rawType;
>>> > -        private final Type[] types;
>>> > -
>>> > -        private ParameterizedTypeImpl(final Type raw, final Type...
>>> types) {
>>> > -            this.rawType = raw;
>>> > -            this.types = types;
>>> > -        }
>>> > -
>>> > -        @Override
>>> > -        public Type[] getActualTypeArguments() {
>>> > -            return types.clone();
>>> > -        }
>>> > -
>>> > -        @Override
>>> > -        public Type getOwnerType() {
>>> > -            return null;
>>> > -        }
>>> > -
>>> > -        @Override
>>> > -        public Type getRawType() {
>>> > -            return rawType;
>>> > -        }
>>> > -
>>> > -        @Override
>>> > -        public int hashCode() {
>>> > -            return Arrays.hashCode(types) ^ rawType.hashCode();
>>> > -        }
>>> > -
>>> > -        @Override
>>> > -        public boolean equals(final Object obj) {
>>> > -            if (this == obj) {
>>> > -                return true;
>>> > -            }
>>> > -            if (ParameterizedType.class.isInstance(obj)) {
>>> > -                final ParameterizedType that =
>>> ParameterizedType.class.cast(obj);
>>> > -                final Type thatRawType = that.getRawType();
>>> > -                return (rawType == null ? thatRawType == null :
>>> rawType.equals(thatRawType))
>>> > -                        && Arrays.equals(types,
>>> that.getActualTypeArguments());
>>> > -            }
>>> > -            return false;
>>> > -        }
>>> > +    public void shutdown(@Observes BeforeShutdown bsd) {
>>> > +        DefaultConfigProvider.instance().releaseConfig(config);
>>> > +    }
>>> >
>>> > -        @Override
>>> > -        public String toString() {
>>> > -            final StringBuilder buffer = new StringBuilder();
>>> > -            buffer.append(Class.class.cast(rawType).getName());
>>> > -            final Type[] actualTypes = getActualTypeArguments();
>>> > -            if (actualTypes.length > 0) {
>>> > -                buffer.append("<");
>>> > -                final int length = actualTypes.length;
>>> > -                for (int i = 0; i < length; i++) {
>>> > -                    if (actualTypes[i] instanceof Class) {
>>> > -                        buffer.append(((Class<?>)
>>> actualTypes[i]).getSimpleName());
>>> > -                    } else {
>>> > -                        buffer.append(actualTypes[i].toString());
>>> > -                    }
>>> > -                    if (i != actualTypes.length - 1) {
>>> > -                        buffer.append(",");
>>> > -                    }
>>> > -                }
>>> >
>>> > -                buffer.append(">");
>>> > -            }
>>> > -            return buffer.toString();
>>> > -        }
>>> > +    static boolean isDefaultUnset(String defaultValue) {
>>> > +        return defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);
>>> >      }
>>> >  }
>>> >
>>> > Modified:
>>> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
>>> > URL:
>>> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java?rev=1804397&r1=1804396&r2=1804397&view=diff
>>> >
>>> ==============================================================================
>>> > ---
>>> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
>>> (original)
>>> > +++
>>> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
>>> Tue Aug  8 10:55:56 2017
>>> > @@ -16,49 +16,59 @@
>>> >   */
>>> >  package org.apache.geronimo.config.cdi;
>>> >
>>> > -import org.eclipse.microprofile.config.inject.ConfigProperty;
>>> > +import java.io.IOException;
>>> > +import java.io.Serializable;
>>> > +import java.lang.annotation.Annotation;
>>> > +import java.lang.reflect.ParameterizedType;
>>> > +import java.lang.reflect.Type;
>>> > +import java.util.Collections;
>>> > +import java.util.HashSet;
>>> > +import java.util.Optional;
>>> > +import java.util.Set;
>>> >
>>> >  import javax.enterprise.context.Dependent;
>>> >  import javax.enterprise.context.spi.CreationalContext;
>>> > -import javax.enterprise.inject.Default;
>>> >  import javax.enterprise.inject.spi.Annotated;
>>> > +import javax.enterprise.inject.spi.AnnotatedMember;
>>> > +import javax.enterprise.inject.spi.AnnotatedType;
>>> >  import javax.enterprise.inject.spi.Bean;
>>> > +import javax.enterprise.inject.spi.BeanManager;
>>> >  import javax.enterprise.inject.spi.InjectionPoint;
>>> >  import javax.enterprise.inject.spi.PassivationCapable;
>>> >  import javax.enterprise.util.AnnotationLiteral;
>>> > -import java.lang.annotation.Annotation;
>>> > -import java.lang.reflect.Member;
>>> > -import java.lang.reflect.ParameterizedType;
>>> > -import java.lang.reflect.Type;
>>> > -import java.util.Collections;
>>> > -import java.util.HashSet;
>>> > -import java.util.Set;
>>> > +import javax.inject.Provider;
>>> > +
>>> > +import org.apache.geronimo.config.ConfigImpl;
>>> > +import org.eclipse.microprofile.config.Config;
>>> > +import org.eclipse.microprofile.config.ConfigProvider;
>>> > +import org.eclipse.microprofile.config.inject.ConfigProperty;
>>> > +import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
>>> >
>>> >  /**
>>> >   * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
>>> >   */
>>> > -public abstract class ConfigInjectionBean<T> implements Bean<T>,
>>> PassivationCapable {
>>> > +public class ConfigInjectionBean<T> implements Bean<T>,
>>> PassivationCapable {
>>> >
>>> >      private final static Set<Annotation> QUALIFIERS = new HashSet<>();
>>> >      static {
>>> >          QUALIFIERS.add(new ConfigPropertyLiteral());
>>> >      }
>>> >
>>> > +    private final BeanManager bm;
>>> >      private final Class rawType;
>>> >      private final Set<Type> types;
>>> > -    private final String id;
>>> > -    private final boolean alternative;
>>> > -
>>> > -    ConfigInjectionBean(Type type) {
>>> > -        this(type,false);
>>> > -    }
>>> >
>>> > -    ConfigInjectionBean(Type type, boolean alternative) {
>>> > -        this.types = new HashSet<>();
>>> > -        this.types.add(type);
>>> > -        this.rawType = getRawType(type);
>>> > -        this.id = "ConfigInjectionBean_" + type.toString();
>>> > -        this.alternative = alternative;
>>> > +    /**
>>> > +     * only access via {@link #getConfig(}
>>> > +     */
>>> > +    private Config _config;
>>> > +
>>> > +    public ConfigInjectionBean(BeanManager bm, Type type) {
>>> > +        this.bm = bm;
>>> > +
>>> > +        types = new HashSet<>();
>>> > +        types.add(type);
>>> > +        rawType = getRawType(type);
>>> >      }
>>> >
>>> >      private Class getRawType(Type type) {
>>> > @@ -76,7 +86,7 @@ public abstract class ConfigInjectionBea
>>> >
>>> >      @Override
>>> >      public Set<InjectionPoint> getInjectionPoints() {
>>> > -        return Collections.emptySet();
>>> > +        return Collections.EMPTY_SET;
>>> >      }
>>> >
>>> >      @Override
>>> > @@ -90,8 +100,90 @@ public abstract class ConfigInjectionBea
>>> >      }
>>> >
>>> >      @Override
>>> > +    public T create(CreationalContext<T> context) {
>>> > +        Set<Bean<?>> beans = bm.getBeans(InjectionPoint.class);
>>> > +        Bean<?> bean = bm.resolve(beans);
>>> > +        InjectionPoint ip = (InjectionPoint) bm.getReference(bean,
>>> InjectionPoint.class,  context);
>>> > +        if (ip == null) {
>>> > +            throw new IllegalStateException("Could not retrieve
>>> InjectionPoint");
>>> > +        }
>>> > +        Annotated annotated = ip.getAnnotated();
>>> > +        ConfigProperty configProperty =
>>> annotated.getAnnotation(ConfigProperty.class);
>>> > +        String key = getConfigKey(ip, configProperty);
>>> > +        String defaultValue = configProperty.defaultValue();
>>> > +
>>> > +        if (annotated.getBaseType() instanceof ParameterizedType) {
>>> > +            ParameterizedType paramType = (ParameterizedType)
>>> annotated.getBaseType();
>>> > +            Type rawType = paramType.getRawType();
>>> > +
>>> > +            // handle Provider<T>
>>> > +            if (rawType instanceof Class && ((Class)
>>> rawType).isAssignableFrom(Provider.class) &&
>>> paramType.getActualTypeArguments().length == 1) {
>>> > +                Class clazz = (Class)
>>> paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
>>> > +                return (T) new ConfigValueProvider(getConfig(), key,
>>> clazz);
>>> > +            }
>>> > +
>>> > +            // handle Optional<T>
>>> > +            if (rawType instanceof Class && ((Class)
>>> rawType).isAssignableFrom(Optional.class) &&
>>> paramType.getActualTypeArguments().length == 1) {
>>> > +                Class clazz = (Class)
>>> paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
>>> > +                return (T) getConfig().getOptionalValue(key, clazz);
>>> > +            }
>>> > +        }
>>> > +        else {
>>> > +            Class clazz = (Class) annotated.getBaseType();
>>> > +            if (ConfigExtension.isDefaultUnset(defaultValue)) {
>>> > +                return (T) getConfig().getValue(key, clazz);
>>> > +            }
>>> > +            else {
>>> > +                Config config = getConfig();
>>> > +                return (T) config.getOptionalValue(key, clazz)
>>> > +                        .orElse(((ConfigImpl)
>>> config).convert(defaultValue, clazz));
>>> > +            }
>>> > +        }
>>> > +
>>> > +        throw new IllegalStateException("unhandled ConfigProperty");
>>> > +    }
>>> > +
>>> > +
>>> > +    /**
>>> > +     * Get the property key to use.
>>> > +     * In case the {@link ConfigProperty#name()} is empty we will try
>>> to determine the key name from the InjectionPoint.
>>> > +     */
>>> > +    public static String getConfigKey(InjectionPoint ip,
>>> ConfigProperty configProperty) {
>>> > +        String key = configProperty.name();
>>> > +        if (key.length() > 0) {
>>> > +            return key;
>>> > +        }
>>> > +        if (ip.getAnnotated() instanceof AnnotatedMember) {
>>> > +            AnnotatedMember member = (AnnotatedMember)
>>> ip.getAnnotated();
>>> > +            AnnotatedType declaringType = member.getDeclaringType();
>>> > +            if (declaringType != null) {
>>> > +                String[] parts =
>>> declaringType.getJavaClass().getCanonicalName().split("\\.");
>>> > +                String cn = parts[parts.length-1];
>>> > +                parts[parts.length-1] =
>>> Character.toLowerCase(cn.charAt(0)) + (cn.length() > 1 ? cn.substring(1) :
>>> "");
>>> > +                StringBuilder sb = new StringBuilder(parts[0]);
>>> > +                for (int i = 1; i < parts.length; i++) {
>>> > +                    sb.append(".").append(parts[i]);
>>> > +                }
>>> > +
>>> > +                // now add the field name
>>> > +
>>> sb.append(".").append(member.getJavaMember().getName());
>>> > +                return sb.toString();
>>> > +            }
>>> > +        }
>>> > +
>>> > +        throw new IllegalStateException("Could not find default name
>>> for @ConfigProperty InjectionPoint " + ip);
>>> > +    }
>>> > +
>>> > +    public Config getConfig() {
>>> > +        if (_config == null) {
>>> > +            _config = ConfigProvider.getConfig();
>>> > +        }
>>> > +        return _config;
>>> > +    }
>>> > +
>>> > +    @Override
>>> >      public void destroy(T instance, CreationalContext<T> context) {
>>> > -        // no-op
>>> > +
>>> >      }
>>> >
>>> >      @Override
>>> > @@ -116,21 +208,17 @@ public abstract class ConfigInjectionBea
>>> >
>>> >      @Override
>>> >      public Set<Class<? extends Annotation>> getStereotypes() {
>>> > -        return Collections.emptySet();
>>> > +        return Collections.EMPTY_SET;
>>> >      }
>>> >
>>> >      @Override
>>> >      public boolean isAlternative() {
>>> > -        return alternative;
>>> > +        return true;
>>> >      }
>>> >
>>> >      @Override
>>> >      public String getId() {
>>> > -        return id;
>>> > -    }
>>> > -
>>> > -    InjectionPoint getSimpleInjectionPoint() {
>>> > -        return simpleInjectionPoint;
>>> > +        return "ConfigInjectionBean_" + rawType.getName();
>>> >      }
>>> >
>>> >      private static class ConfigPropertyLiteral extends
>>> AnnotationLiteral<ConfigProperty> implements ConfigProperty {
>>> > @@ -145,41 +233,31 @@ public abstract class ConfigInjectionBea
>>> >          }
>>> >      }
>>> >
>>> > -    private final InjectionPoint simpleInjectionPoint = new
>>> InjectionPoint() {
>>> > -
>>> > -        @Override
>>> > -        public boolean isTransient() {
>>> > -            return false;
>>> > -        }
>>> > -
>>> > -        @Override
>>> > -        public boolean isDelegate() {
>>> > -            return false;
>>> > -        }
>>> > -
>>> > -        @Override
>>> > -        public Type getType() {
>>> > -            return InjectionPoint.class;
>>> > -        }
>>> > -
>>> > -        @Override
>>> > -        public Set<Annotation> getQualifiers() {
>>> > -            return Collections.singleton(new
>>> AnnotationLiteral<Default>() {});
>>> > -        }
>>> > -
>>> > -        @Override
>>> > -        public Member getMember() {
>>> > -            return null;
>>> > +    /**
>>> > +     * A special Provider&lt;T&gt;
>>> > +     * This concrete class is needed because we need the injected
>>> Provider for the ConfigProperty
>>> > +     * to be Serializable. A Lambda would not work in this case
>>> > +     */
>>> > +    public static class ConfigValueProvider<T> implements
>>> Provider<T>, Serializable {
>>> > +        private transient Config config;
>>> > +        private final String key;
>>> > +        private final Class<T> type;
>>> > +
>>> > +        ConfigValueProvider(Config config, String key, Class<T> type)
>>> {
>>> > +            this.config = config;
>>> > +            this.key = key;
>>> > +            this.type = type;
>>> >          }
>>> >
>>> >          @Override
>>> > -        public Bean<?> getBean() {
>>> > -            return ConfigInjectionBean.this;
>>> > +        public T get() {
>>> > +            return (T) config.getValue(key, type);
>>> > +        }
>>> > +
>>> > +        private void readObject(java.io.ObjectInputStream in) throws
>>> IOException, ClassNotFoundException {
>>> > +            in.defaultReadObject();
>>> > +            config = ConfigProviderResolver.instance().getConfig();
>>> >          }
>>> >
>>> > -        @Override
>>> > -        public Annotated getAnnotated() {
>>> > -            return null;
>>> > -        }
>>> > -    };
>>> > +    }
>>> >  }
>>> >
>>> > Modified:
>>> geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
>>> > URL:
>>> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java?rev=1804397&r1=1804396&r2=1804397&view=diff
>>> >
>>> ==============================================================================
>>> > ---
>>> geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
>>> (original)
>>> > +++
>>> geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
>>> Tue Aug  8 10:55:56 2017
>>> > @@ -33,9 +33,12 @@ import org.testng.annotations.Test;
>>> >
>>> >  public class ProviderTest extends Arquillian {
>>> >      private static final String SOME_KEY =
>>> "org.apache.geronimo.config.test.internal.somekey";
>>> > +    private static final String ANOTHER_KEY =
>>> "org.apache.geronimo.config.test.internal.anotherkey";
>>> >
>>> >      @Deployment
>>> >      public static WebArchive deploy() {
>>> > +        System.setProperty(SOME_KEY, "someval");
>>> > +        System.setProperty(ANOTHER_KEY, "someval");
>>> >          JavaArchive testJar = ShrinkWrap
>>> >                  .create(JavaArchive.class, "configProviderTest.jar")
>>> >                  .addClasses(ProviderTest.class, SomeBean.class)
>>> > @@ -70,8 +73,16 @@ public class ProviderTest extends Arquil
>>> >          @ConfigProperty(name=SOME_KEY)
>>> >          private Provider<String> myconfig;
>>> >
>>> > +        @Inject
>>> > +        @ConfigProperty(name=ANOTHER_KEY)
>>> > +        private Provider<String> anotherconfig;
>>> > +
>>> >          public String getMyconfig() {
>>> >              return myconfig.get();
>>> >          }
>>> > +
>>> > +        public Provider<String> getAnotherconfig() {
>>> > +            return anotherconfig;
>>> > +        }
>>> >      }
>>> >  }
>>> >
>>> > Modified: geronimo/components/config/trunk/pom.xml
>>> > URL:
>>> http://svn.apache.org/viewvc/geronimo/components/config/trunk/pom.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
>>> >
>>> ==============================================================================
>>> > --- geronimo/components/config/trunk/pom.xml (original)
>>> > +++ geronimo/components/config/trunk/pom.xml Tue Aug  8 10:55:56 2017
>>> > @@ -27,7 +27,7 @@
>>> >      </parent>
>>> >
>>> >      <groupId>org.apache.geronimo.config</groupId>
>>> > -    <artifactId>config-parent</artifactId>
>>> > +    <artifactId>geronimo-config</artifactId>
>>> >      <version>1.1-SNAPSHOT</version>
>>> >      <packaging>pom</packaging>
>>> >      <name>Geronimo Microprofile Configuration</name>
>>> > @@ -50,7 +50,7 @@
>>> >      <properties>
>>> >          <maven.compiler.source>1.8</maven.compiler.source>
>>> >          <maven.compiler.target>1.8</maven.compiler.target>
>>> > -
>>> <microprofile-config.version>1.1-SNAPSHOT</microprofile-config.version>
>>> > +        <microprofile-config.version>1.0</microprofile-config.version>
>>> >          <owb.version>1.7.3</owb.version>
>>> >          <owb2.version>2.0.1-SNAPSHOT</owb2.version>
>>> >          <arquillian.version>1.1.13.Final</arquillian.version>
>>> >
>>> >
>>>
>>>
>>>

Re: svn commit: r1804397 - in /geronimo/components/config/trunk: ./ impl/ impl/src/main/java/org/apache/geronimo/config/cdi/ impl/src/test/java/org/apache/geronimo/config/test/internal/

Posted by "John D. Ament" <jo...@apache.org>.
Ok, I've readded some of the Weld3 support, 3 tests are failing.

Some interesting notes:

- If I remove Provider support, it generally works.  However, I suddenly
get duplicate beans of type Provider, which is confusing (but probably
because of the alternative flag).
- I can get everything to pass in Weld, and 1 test failure in in OWB with
the following:

- Set alternative = false
- Remove Provider from the types
- Remove the filter on types to check if class.
- Change getId to use all of the types (makes a better toString)


If we can figure out the alternative issue with OWB, we'll be good to go
again.

John

On Tue, Aug 8, 2017 at 8:44 AM John D. Ament <jo...@apache.org> wrote:

> I can get to some of it.
>
> We have a couple of issues now though:
>
> https://issues.jboss.org/browse/WELD-2411
> https://issues.jboss.org/browse/CDI-712
>
> Martin doesn't feel the spec allows you to override Provider impl's.
> Please feel free to weigh in :-)
>
> John
>
>
> On Tue, Aug 8, 2017 at 7:33 AM Mark Struberg <st...@yahoo.de> wrote:
>
>> Oh I see what you mean.
>> Do you mind to re-apply your fix or should I?
>>
>> Btw, I also tested with the -PWeld3 but I was not able to resolve
>> arquillian-weld-embedded:jar:2.0.0-SNAPSHOT
>> We might need to add a <repository> for it in the Weld3 profile.
>>
>> I also would love to add a Weld profile. I thought we have this already
>> but seems we missed it?
>>
>> txs and LieGrue,
>> strub
>>
>> > Am 08.08.2017 um 12:58 schrieb John D. Ament <jo...@apache.org>:
>> >
>> > One note - hardcoding "isAlternative" to true breaks in Weld.  Unless
>> there is a base bean of same type, the alternative is ignored.  Hence why I
>> only did isAlternative on the provider type, all others are just regular
>> beans.
>> >
>> > John
>> >
>> > On Tue, Aug 8, 2017 at 6:55 AM <st...@apache.org> wrote:
>> > Author: struberg
>> > Date: Tue Aug  8 10:55:56 2017
>> > New Revision: 1804397
>> >
>> > URL: http://svn.apache.org/viewvc?rev=1804397&view=rev
>> > Log:
>> > GERONIMO-6577 move back to a more dynamic version
>> >
>> > The goal of r1800748 to calculate all information upfront could not be
>> achieved
>> > so we move back to the old version
>> >
>> > Modified:
>> >     geronimo/components/config/trunk/impl/debug-suite.xml
>> >     geronimo/components/config/trunk/impl/pom.xml
>> >
>>  geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
>> >
>>  geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
>> >
>>  geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
>> >     geronimo/components/config/trunk/pom.xml
>> >
>> > Modified: geronimo/components/config/trunk/impl/debug-suite.xml
>> > URL:
>> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/debug-suite.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
>> >
>> ==============================================================================
>> > --- geronimo/components/config/trunk/impl/debug-suite.xml (original)
>> > +++ geronimo/components/config/trunk/impl/debug-suite.xml Tue Aug  8
>> 10:55:56 2017
>> > @@ -24,7 +24,7 @@
>> >      <classes>
>> >          <!-- Issues in the spec -->
>> >          <!-- CDI-437 -->
>> > -        <class
>> name="org.eclipse.microprofile.config.tck.CdiOptionalInjectionTest">
>> > +        <class
>> name="org.eclipse.microprofile.config.tck.CDIPlainInjectionTest">
>> >              <methods>
>> >                  <include name=".*"/>
>> >              </methods>
>> >
>> > Modified: geronimo/components/config/trunk/impl/pom.xml
>> > URL:
>> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/pom.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
>> >
>> ==============================================================================
>> > --- geronimo/components/config/trunk/impl/pom.xml (original)
>> > +++ geronimo/components/config/trunk/impl/pom.xml Tue Aug  8 10:55:56
>> 2017
>> > @@ -27,7 +27,6 @@
>> >      </parent>
>> >
>> >      <artifactId>geronimo-config-impl</artifactId>
>> > -    <name>Geronimo Microprofile Configuration :: Implementation</name>
>> >
>> >      <dependencyManagement>
>> >          <dependencies>
>> >
>> > Modified:
>> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
>> > URL:
>> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java?rev=1804397&r1=1804396&r2=1804397&view=diff
>> >
>> ==============================================================================
>> > ---
>> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
>> (original)
>> > +++
>> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
>> Tue Aug  8 10:55:56 2017
>> > @@ -16,54 +16,38 @@
>> >   */
>> >  package org.apache.geronimo.config.cdi;
>> >
>> > -import org.apache.geronimo.config.ConfigImpl;
>> > -import org.eclipse.microprofile.config.Config;
>> > -import org.eclipse.microprofile.config.inject.ConfigProperty;
>> > -import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
>> > +import java.lang.reflect.Type;
>> > +import java.util.ArrayList;
>> > +import java.util.HashMap;
>> > +import java.util.HashSet;
>> > +import java.util.List;
>> > +import java.util.Map;
>> > +import java.util.Optional;
>> > +import java.util.Set;
>> > +import java.util.stream.Collectors;
>> >
>> > -import javax.enterprise.context.spi.CreationalContext;
>> >  import javax.enterprise.event.Observes;
>> >  import javax.enterprise.inject.spi.AfterBeanDiscovery;
>> >  import javax.enterprise.inject.spi.AfterDeploymentValidation;
>> > -import javax.enterprise.inject.spi.AnnotatedMember;
>> > -import javax.enterprise.inject.spi.AnnotatedType;
>> >  import javax.enterprise.inject.spi.BeanManager;
>> > -import javax.enterprise.inject.spi.BeforeBeanDiscovery;
>> >  import javax.enterprise.inject.spi.BeforeShutdown;
>> > +import javax.enterprise.inject.spi.DeploymentException;
>> >  import javax.enterprise.inject.spi.Extension;
>> >  import javax.enterprise.inject.spi.InjectionPoint;
>> >  import javax.enterprise.inject.spi.ProcessInjectionPoint;
>> >  import javax.inject.Provider;
>> > -import java.lang.reflect.ParameterizedType;
>> > -import java.lang.reflect.Type;
>> > -import java.util.ArrayList;
>> > -import java.util.Arrays;
>> > -import java.util.Collection;
>> > -import java.util.HashMap;
>> > -import java.util.HashSet;
>> > -import java.util.List;
>> > -import java.util.Map;
>> > -import java.util.Objects;
>> > -import java.util.Optional;
>> > -import java.util.Set;
>> > -import java.util.function.BiFunction;
>> > -import java.util.stream.Stream;
>> >
>> > -import static java.util.function.Function.identity;
>> > -import static java.util.stream.Collectors.toMap;
>> > -import static org.eclipse.microprofile.config.ConfigProvider.getConfig;
>> > +import org.apache.geronimo.config.DefaultConfigProvider;
>> > +import org.eclipse.microprofile.config.Config;
>> > +import org.eclipse.microprofile.config.ConfigProvider;
>> > +import org.eclipse.microprofile.config.inject.ConfigProperty;
>> >
>> >  /**
>> >   * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
>> >   */
>> >  public class ConfigExtension implements Extension {
>> > -    private static final Object NULL = new Object();
>> > -
>> >      private Config config;
>> > -    private ConfigProviderResolver resolver;
>> >
>> > -    private Set<Injection> injections = new HashSet<>();
>> > -    private List<Throwable> deploymentProblems = new ArrayList<>();
>> >      private static final Map<Type, Type> REPLACED_TYPES = new
>> HashMap<>();
>> >
>> >      static {
>> > @@ -74,336 +58,65 @@ public class ConfigExtension implements
>> >          REPLACED_TYPES.put(boolean.class, Boolean.class);
>> >      }
>> >
>> > -    void init(@Observes final BeforeBeanDiscovery beforeBeanDiscovery,
>> final BeanManager bm) {
>> > -        resolver = ConfigProviderResolver.instance();
>> > -        config = getConfig();
>> > -    }
>> > +    private Set<InjectionPoint> injectionPoints = new HashSet<>();
>> > +
>> >
>> >      public void collectConfigProducer(@Observes
>> ProcessInjectionPoint<?, ?> pip) {
>> > -        final InjectionPoint injectionPoint = pip.getInjectionPoint();
>> > -        final ConfigProperty configProperty =
>> injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class);
>> > +        ConfigProperty configProperty =
>> pip.getInjectionPoint().getAnnotated().getAnnotation(ConfigProperty.class);
>> >          if (configProperty != null) {
>> > -            Type replacedType =
>> REPLACED_TYPES.getOrDefault(injectionPoint.getType(),
>> injectionPoint.getType());
>> > -            Injection injection = new Injection(replacedType);
>> > -            final String key = getConfigKey(injectionPoint,
>> configProperty);
>> > -            final boolean defaultUnset =
>> isDefaultUnset(configProperty.defaultValue());
>> > -            if (!injections.add(injection)) {
>> > -                final Injection ref = injection;
>> > -                injection = injections.stream().filter(i ->
>> i.equals(ref)).findFirst().get();
>> > -            }
>> > -            injection.keys.add(key);
>> > -            injection.defaultValues.add(configProperty.defaultValue());
>> > -
>> > -            final ConfigImpl configImpl = unwrapConfig();
>> > -
>> > -            // what about lazy runtime lookup, not consistent with tck
>> and system prop usage, for now assume optional=optional ;)
>> > -            boolean hasValue = true;
>> > -            if (defaultUnset) { // value validation
>> > -                if
>> (ParameterizedType.class.isInstance(injection.type)) {
>> > -                    final ParameterizedType pt =
>> ParameterizedType.class.cast(injection.type);
>> > -                    if (pt.getRawType() != Optional.class &&
>> !configImpl.getOptionalValue(key, String.class).isPresent()) {
>> > -                        hasValue = false;
>> > -                    }
>> > -                } else if (!configImpl.getOptionalValue(key,
>> String.class).isPresent()) {
>> > -                    hasValue = false;
>> > -                }
>> > -                if (!hasValue) {
>> > -                    deploymentProblems.add(new
>> IllegalArgumentException("No configured value for '" + key + "' from " +
>> injectionPoint));
>> > -                }
>> > -            }
>> > -
>> > -            Class<?> instanceType = null;
>> > -            if (ParameterizedType.class.isInstance(injection.type)) {
>> // converters validation
>> > -                final ParameterizedType pt =
>> ParameterizedType.class.cast(injection.type);
>> > -                if (pt.getRawType() == Provider.class &&
>> pt.getActualTypeArguments().length == 1 &&
>> Class.class.isInstance(pt.getActualTypeArguments()[0])
>> > -                        &&
>> !configImpl.getConverters().containsKey(Class.class.cast(pt.getActualTypeArguments()[0])))
>> {
>> > -                    instanceType =
>> Class.class.cast(pt.getActualTypeArguments()[0]);
>> > -                } // else if Optional it is fine, else we don't know
>> how to process
>> > -            } else if (Class.class.isInstance(injection.type)) {
>> > -                instanceType = Class.class.cast(injection.type);
>> > -            }
>> > -            if (instanceType != null) { // validate we have a
>> converter + we can convert the existing value
>> > -                if
>> (!configImpl.getConverters().containsKey(instanceType)) {
>> > -                    deploymentProblems.add(new
>> IllegalArgumentException("Missing converter for '" + key + "' from " +
>> injectionPoint));
>> > -                } else if (hasValue) {
>> > -                    try {
>> > -
>> configImpl.getConverters().get(injection.type).convert(configImpl.getValue(key));
>> > -                    } catch (final RuntimeException re) {
>> > -                        deploymentProblems.add(re);
>> > -                    }
>> > -                }
>> > -            }
>> > +            injectionPoints.add(pip.getInjectionPoint());
>> >          }
>> >      }
>> >
>> >      public void registerConfigProducer(@Observes AfterBeanDiscovery
>> abd, BeanManager bm) {
>> > -        injections.stream()
>> > -                .flatMap(injection -> {
>> > -                    final BiFunction<CreationalContext<?>,
>> ConfigInjectionBean<?>, String> keyProvider;
>> > -                    if (injection.keys.size() == 1) {
>> > -                        final String key =
>> injection.keys.iterator().next();
>> > -                        keyProvider = (ctx, bean) -> key;
>> > -                    } else {
>> > -                        keyProvider = (ctx, bean) ->
>> getName(findInjectionPoint(bm, ctx, bean));
>> > -                    }
>> > -
>> > -                    if
>> (ParameterizedType.class.isInstance(injection.type)) {
>> > -                        final ParameterizedType paramType =
>> ParameterizedType.class.cast(injection.type);
>> > -                        final Type rawType = paramType.getRawType();
>> > -
>> > -                        // todo: do we care of Instance injection?
>> doesnt make much sense right?
>> > -                        if (Provider.class == rawType &&
>> paramType.getActualTypeArguments().length == 1) {
>> > -                            if
>> (!Class.class.isInstance(paramType.getActualTypeArguments()[0])) {
>> > -                                deploymentProblems.add(new
>> IllegalArgumentException("@ConfigProperty can only be used with Provider<T>
>> where T is a Class"));
>> > -                                return Stream.empty();
>> > -                            }
>> > -                            final Class<?> providerType =
>> Class.class.cast(paramType.getActualTypeArguments()[0]);
>> > -                            return Stream.of(new
>> ConfigInjectionBean<Provider<?>>(injection.type, true) {
>> > -                                @Override
>> > -                                public Provider<?> create(final
>> CreationalContext<Provider<?>> context) {
>> > -                                    return () ->
>> config.getValue(keyProvider.apply(context, this), providerType);
>> > -                                }
>> > -                            });
>> > -                        } else if (Optional.class == rawType &&
>> paramType.getActualTypeArguments().length == 1) {
>> > -                            if
>> (!Class.class.isInstance(paramType.getActualTypeArguments()[0])) {
>> > -                                deploymentProblems.add(new
>> IllegalArgumentException("@ConfigProperty can only be used with Optional<T>
>> where T is a Class"));
>> > -                                return null;
>> > -                            }
>> > -                            final Class<?> optionalType =
>> Class.class.cast(paramType.getActualTypeArguments()[0]);
>> > -                            return Stream.of(new
>> ConfigInjectionBean<Optional<?>>(injection.type) {
>> > -                                @Override
>> > -                                public Optional<?> create(final
>> CreationalContext<Optional<?>> context) {
>> > -                                    return
>> config.getOptionalValue(keyProvider.apply(context, this), optionalType);
>> > -                                }
>> > -                            });
>> > -                        } else {
>> > -                            deploymentProblems.add(new
>> IllegalArgumentException("Unsupported parameterized type " + paramType));
>> > -                            return Stream.empty();
>> > -                        }
>> > -                    } else if (Class.class.isInstance(injection.type))
>> {
>> > -                        final Class clazz =
>> Class.class.cast(injection.type);
>> > -                        final ConfigInjectionBean bean;
>> > -                        if (injection.defaultValues.isEmpty()) {
>> > -                            bean = new
>> ConfigInjectionBean<Object>(injection.type) {
>> > -                                @Override
>> > -                                public Object create(final
>> CreationalContext<Object> context) {
>> > -                                    return
>> config.getOptionalValue(keyProvider.apply(context, this), clazz);
>> > -                                }
>> > -                            };
>> > -                        } else if (injection.defaultValues.size() ==
>> 1) { // common enough to be optimized
>> > -                            final String defVal =
>> injection.defaultValues.iterator().next();
>> > -                            final Object alternativeVal =
>> isDefaultUnset(defVal) ? null : unwrapConfig().convert(defVal, clazz);
>> > -                            bean = new
>> ConfigInjectionBean<Object>(injection.type) {
>> > -                                @Override
>> > -                                public Object create(final
>> CreationalContext<Object> context) {
>> > -                                    final Optional optionalValue =
>> config.getOptionalValue(keyProvider.apply(context, this), clazz);
>> > -                                    return
>> optionalValue.orElse(alternativeVal);
>> > -                                }
>> > -                            };
>> > -                        } else { // sadly we need to get back to the
>> injection point to know which one we need to use
>> > -                            final Map<String, Object> prepared =
>> injection.defaultValues.stream()
>> > -                                    .collect(toMap(identity(), k ->
>> isDefaultUnset(k) ? NULL : unwrapConfig().convert(k, clazz), (a, b) -> b));
>> > -                            bean = new
>> ConfigInjectionBean<Object>(injection.type) {
>> > -                                @Override
>> > -                                public Object create(final
>> CreationalContext<Object> context) {
>> > -                                    final InjectionPoint ip =
>> findInjectionPoint(bm, context, this);
>> > -                                    if (ip == null) {
>> > -                                        throw new
>> IllegalStateException("Could not retrieve InjectionPoint");
>> > -                                    }
>> > -                                    return
>> config.getOptionalValue(ConfigExtension.this.getName(ip), clazz)
>> > -                                            .orElseGet(() -> {
>> > -                                                final Object val =
>> prepared.get(ip.getAnnotated().getAnnotation(ConfigProperty.class).defaultValue());
>> > -                                                return val == NULL ?
>> null : val;
>> > -                                            });
>> > -                                }
>> > -                            };
>> > -                        }
>> > -
>> > -                        final Collection<ConfigInjectionBean<?>> beans
>> = new ArrayList<>();
>> > -                        beans.add(bean);
>> > -
>> > -                        // is adding these beans is that useful? we
>> captured them all so only a programmatic lookup would justify it
>> > -                        // and not sure it would be done this way
>> anyway
>> > -                        final ParameterizedTypeImpl providerType = new
>> ParameterizedTypeImpl(Provider.class, injection.type);
>> > -                        if (injections.stream().noneMatch(i ->
>> i.type.equals(providerType))) {
>> > -                            beans.add(new
>> ConfigInjectionBean<Provider<?>>(providerType, true) {
>> > -                                @Override
>> > -                                public Provider<?> create(final
>> CreationalContext<Provider<?>> context) {
>> > -                                    return () -> bean.create(context);
>> > -                                }
>> > -                            });
>> > -                        }
>> > -
>> > -                        final ParameterizedTypeImpl optionalType = new
>> ParameterizedTypeImpl(Optional.class, injection.type);
>> > -                        if (injections.stream().noneMatch(i ->
>> i.type.equals(optionalType))) {
>> > -                            beans.add(new
>> ConfigInjectionBean<Optional<?>>(optionalType) {
>> > -                                @Override
>> > -                                public Optional<?> create(final
>> CreationalContext<Optional<?>> context) {
>> > -                                    return
>> Optional.ofNullable(bean.create(context));
>> > -                                }
>> > -                            });
>> > -                        }
>> > -
>> > -                        return beans.stream();
>> > -                    } else {
>> > -                        deploymentProblems.add(new
>> IllegalArgumentException("Unknown type " + injection.type));
>> > -                        return Stream.empty();
>> > -                    }
>> > -                })
>> > -                .forEach(abd::addBean);
>> > -    }
>> > +        Set<Class> types = injectionPoints.stream()
>> > +                .filter(ip -> ip.getType() instanceof Class)
>> > +                .map(ip -> (Class)
>> REPLACED_TYPES.getOrDefault(ip.getType(), ip.getType()))
>> > +                .collect(Collectors.toSet());
>> > +
>> > +        // Provider and Optional are ParameterizedTypes and not a
>> Class, so we need to add them manually
>> > +        types.add(Provider.class);
>> > +        types.add(Optional.class);
>> >
>> > -    public void validate(@Observes AfterDeploymentValidation add) {
>> > -        deploymentProblems.forEach(add::addDeploymentProblem);
>> > -        injections.clear();
>> > -        deploymentProblems.clear();
>> > +        types.forEach(type -> abd.addBean(new ConfigInjectionBean(bm,
>> type)));
>> >      }
>> >
>> > -    public void shutdown(@Observes BeforeShutdown bsd) {
>> > -        resolver.releaseConfig(config);
>> > -    }
>> > +    public void validate(@Observes AfterDeploymentValidation add) {
>> > +        List<String> deploymentProblems = new ArrayList<>();
>> >
>> > -    private ConfigImpl unwrapConfig() {
>> > -        return ConfigImpl.class.cast(config);
>> > -    }
>> > +        config = ConfigProvider.getConfig();
>> >
>> > -    private static String getName(final InjectionPoint ip) {
>> > -        final ConfigProperty annotation =
>> ip.getAnnotated().getAnnotation(ConfigProperty.class);
>> > -        final String name = annotation.name();
>> > -        return isDefaultUnset(name) ? getConfigKey(ip, annotation) :
>> name;
>> > -    }
>> > +        for (InjectionPoint injectionPoint : injectionPoints) {
>> > +            Type type = injectionPoint.getType();
>> >
>> > -    /**
>> > -     * Get the property key to use.
>> > -     * In case the {@link ConfigProperty#name()} is empty we will try
>> to determine the key name from the InjectionPoint.
>> > -     */
>> > -    private static String getConfigKey(InjectionPoint ip,
>> ConfigProperty configProperty) {
>> > -        String key = configProperty.name();
>> > -        if (!key.isEmpty()) {
>> > -            return key;
>> > -        }
>> > -        if (ip.getAnnotated() instanceof AnnotatedMember) {
>> > -            AnnotatedMember member = (AnnotatedMember)
>> ip.getAnnotated();
>> > -            AnnotatedType declaringType = member.getDeclaringType();
>> > -            if (declaringType != null) {
>> > -                String[] parts =
>> declaringType.getJavaClass().getCanonicalName().split("\\.");
>> > -                String cn = parts[parts.length - 1];
>> > -                parts[parts.length - 1] =
>> Character.toLowerCase(cn.charAt(0)) + (cn.length() > 1 ? cn.substring(1) :
>> "");
>> > -                StringBuilder sb = new StringBuilder(parts[0]);
>> > -                for (int i = 1; i < parts.length; i++) {
>> > -                    sb.append(".").append(parts[i]);
>> > +            // replace native types with their Wrapper types
>> > +            type = REPLACED_TYPES.getOrDefault(type, type);
>> > +
>> > +            ConfigProperty configProperty =
>> injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class);
>> > +            if (type instanceof Class) {
>> > +                // a direct injection of a ConfigProperty
>> > +                // that means a Converter must exist.
>> > +                String key =
>> ConfigInjectionBean.getConfigKey(injectionPoint, configProperty);
>> > +                if ((isDefaultUnset(configProperty.defaultValue()))
>> > +                        && !config.getOptionalValue(key, (Class)
>> type).isPresent()) {
>> > +                    deploymentProblems.add("No Config Value exists for
>> " + key);
>> >                  }
>> > -
>> > -                // now add the field name
>> > -
>> sb.append(".").append(member.getJavaMember().getName());
>> > -                return sb.toString();
>> >              }
>> >          }
>> >
>> > -        throw new IllegalStateException("Could not find default name
>> for @ConfigProperty InjectionPoint " + ip);
>> > -    }
>> > -
>> > -    private static boolean isDefaultUnset(String defaultValue) {
>> > -        return defaultValue == null || defaultValue.length() == 0 ||
>> defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);
>> > -    }
>> > -
>> > -    private static InjectionPoint findInjectionPoint(final BeanManager
>> bm, final CreationalContext<?> ctx,
>> > -
>>  ConfigInjectionBean bean) {
>> > -        return
>> InjectionPoint.class.cast(bm.getInjectableReference(bean.getSimpleInjectionPoint(),
>> ctx));
>> > -    }
>> > -
>> > -    private static final class Injection {
>> > -        private final Type type;
>> > -        private final Collection<String> keys = new ArrayList<>();
>> > -        private final Collection<String> defaultValues = new
>> ArrayList<>();
>> > -
>> > -        private Injection(final Type type) {
>> > -            this.type = type;
>> > -        }
>> > -
>> > -        @Override
>> > -        public boolean equals(final Object o) {
>> > -            if (this == o) {
>> > -                return true;
>> > -            }
>> > -            if (o == null || Injection.class != o.getClass()) {
>> > -                return false;
>> > -            }
>> > -            final Injection injection = Injection.class.cast(o);
>> > -            return Objects.equals(type, injection.type);
>> > +        if (!deploymentProblems.isEmpty()) {
>> > +            add.addDeploymentProblem(new DeploymentException("Error
>> while validating Configuration\n"
>> > +                                                             +
>> String.join("\n", deploymentProblems)));
>> >          }
>> >
>> > -        @Override
>> > -        public int hashCode() {
>> > -            return type.hashCode();
>> > -        }
>> >      }
>> >
>> > -    private class ParameterizedTypeImpl implements ParameterizedType {
>> > -        private final Type rawType;
>> > -        private final Type[] types;
>> > -
>> > -        private ParameterizedTypeImpl(final Type raw, final Type...
>> types) {
>> > -            this.rawType = raw;
>> > -            this.types = types;
>> > -        }
>> > -
>> > -        @Override
>> > -        public Type[] getActualTypeArguments() {
>> > -            return types.clone();
>> > -        }
>> > -
>> > -        @Override
>> > -        public Type getOwnerType() {
>> > -            return null;
>> > -        }
>> > -
>> > -        @Override
>> > -        public Type getRawType() {
>> > -            return rawType;
>> > -        }
>> > -
>> > -        @Override
>> > -        public int hashCode() {
>> > -            return Arrays.hashCode(types) ^ rawType.hashCode();
>> > -        }
>> > -
>> > -        @Override
>> > -        public boolean equals(final Object obj) {
>> > -            if (this == obj) {
>> > -                return true;
>> > -            }
>> > -            if (ParameterizedType.class.isInstance(obj)) {
>> > -                final ParameterizedType that =
>> ParameterizedType.class.cast(obj);
>> > -                final Type thatRawType = that.getRawType();
>> > -                return (rawType == null ? thatRawType == null :
>> rawType.equals(thatRawType))
>> > -                        && Arrays.equals(types,
>> that.getActualTypeArguments());
>> > -            }
>> > -            return false;
>> > -        }
>> > +    public void shutdown(@Observes BeforeShutdown bsd) {
>> > +        DefaultConfigProvider.instance().releaseConfig(config);
>> > +    }
>> >
>> > -        @Override
>> > -        public String toString() {
>> > -            final StringBuilder buffer = new StringBuilder();
>> > -            buffer.append(Class.class.cast(rawType).getName());
>> > -            final Type[] actualTypes = getActualTypeArguments();
>> > -            if (actualTypes.length > 0) {
>> > -                buffer.append("<");
>> > -                final int length = actualTypes.length;
>> > -                for (int i = 0; i < length; i++) {
>> > -                    if (actualTypes[i] instanceof Class) {
>> > -                        buffer.append(((Class<?>)
>> actualTypes[i]).getSimpleName());
>> > -                    } else {
>> > -                        buffer.append(actualTypes[i].toString());
>> > -                    }
>> > -                    if (i != actualTypes.length - 1) {
>> > -                        buffer.append(",");
>> > -                    }
>> > -                }
>> >
>> > -                buffer.append(">");
>> > -            }
>> > -            return buffer.toString();
>> > -        }
>> > +    static boolean isDefaultUnset(String defaultValue) {
>> > +        return defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);
>> >      }
>> >  }
>> >
>> > Modified:
>> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
>> > URL:
>> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java?rev=1804397&r1=1804396&r2=1804397&view=diff
>> >
>> ==============================================================================
>> > ---
>> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
>> (original)
>> > +++
>> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
>> Tue Aug  8 10:55:56 2017
>> > @@ -16,49 +16,59 @@
>> >   */
>> >  package org.apache.geronimo.config.cdi;
>> >
>> > -import org.eclipse.microprofile.config.inject.ConfigProperty;
>> > +import java.io.IOException;
>> > +import java.io.Serializable;
>> > +import java.lang.annotation.Annotation;
>> > +import java.lang.reflect.ParameterizedType;
>> > +import java.lang.reflect.Type;
>> > +import java.util.Collections;
>> > +import java.util.HashSet;
>> > +import java.util.Optional;
>> > +import java.util.Set;
>> >
>> >  import javax.enterprise.context.Dependent;
>> >  import javax.enterprise.context.spi.CreationalContext;
>> > -import javax.enterprise.inject.Default;
>> >  import javax.enterprise.inject.spi.Annotated;
>> > +import javax.enterprise.inject.spi.AnnotatedMember;
>> > +import javax.enterprise.inject.spi.AnnotatedType;
>> >  import javax.enterprise.inject.spi.Bean;
>> > +import javax.enterprise.inject.spi.BeanManager;
>> >  import javax.enterprise.inject.spi.InjectionPoint;
>> >  import javax.enterprise.inject.spi.PassivationCapable;
>> >  import javax.enterprise.util.AnnotationLiteral;
>> > -import java.lang.annotation.Annotation;
>> > -import java.lang.reflect.Member;
>> > -import java.lang.reflect.ParameterizedType;
>> > -import java.lang.reflect.Type;
>> > -import java.util.Collections;
>> > -import java.util.HashSet;
>> > -import java.util.Set;
>> > +import javax.inject.Provider;
>> > +
>> > +import org.apache.geronimo.config.ConfigImpl;
>> > +import org.eclipse.microprofile.config.Config;
>> > +import org.eclipse.microprofile.config.ConfigProvider;
>> > +import org.eclipse.microprofile.config.inject.ConfigProperty;
>> > +import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
>> >
>> >  /**
>> >   * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
>> >   */
>> > -public abstract class ConfigInjectionBean<T> implements Bean<T>,
>> PassivationCapable {
>> > +public class ConfigInjectionBean<T> implements Bean<T>,
>> PassivationCapable {
>> >
>> >      private final static Set<Annotation> QUALIFIERS = new HashSet<>();
>> >      static {
>> >          QUALIFIERS.add(new ConfigPropertyLiteral());
>> >      }
>> >
>> > +    private final BeanManager bm;
>> >      private final Class rawType;
>> >      private final Set<Type> types;
>> > -    private final String id;
>> > -    private final boolean alternative;
>> > -
>> > -    ConfigInjectionBean(Type type) {
>> > -        this(type,false);
>> > -    }
>> >
>> > -    ConfigInjectionBean(Type type, boolean alternative) {
>> > -        this.types = new HashSet<>();
>> > -        this.types.add(type);
>> > -        this.rawType = getRawType(type);
>> > -        this.id = "ConfigInjectionBean_" + type.toString();
>> > -        this.alternative = alternative;
>> > +    /**
>> > +     * only access via {@link #getConfig(}
>> > +     */
>> > +    private Config _config;
>> > +
>> > +    public ConfigInjectionBean(BeanManager bm, Type type) {
>> > +        this.bm = bm;
>> > +
>> > +        types = new HashSet<>();
>> > +        types.add(type);
>> > +        rawType = getRawType(type);
>> >      }
>> >
>> >      private Class getRawType(Type type) {
>> > @@ -76,7 +86,7 @@ public abstract class ConfigInjectionBea
>> >
>> >      @Override
>> >      public Set<InjectionPoint> getInjectionPoints() {
>> > -        return Collections.emptySet();
>> > +        return Collections.EMPTY_SET;
>> >      }
>> >
>> >      @Override
>> > @@ -90,8 +100,90 @@ public abstract class ConfigInjectionBea
>> >      }
>> >
>> >      @Override
>> > +    public T create(CreationalContext<T> context) {
>> > +        Set<Bean<?>> beans = bm.getBeans(InjectionPoint.class);
>> > +        Bean<?> bean = bm.resolve(beans);
>> > +        InjectionPoint ip = (InjectionPoint) bm.getReference(bean,
>> InjectionPoint.class,  context);
>> > +        if (ip == null) {
>> > +            throw new IllegalStateException("Could not retrieve
>> InjectionPoint");
>> > +        }
>> > +        Annotated annotated = ip.getAnnotated();
>> > +        ConfigProperty configProperty =
>> annotated.getAnnotation(ConfigProperty.class);
>> > +        String key = getConfigKey(ip, configProperty);
>> > +        String defaultValue = configProperty.defaultValue();
>> > +
>> > +        if (annotated.getBaseType() instanceof ParameterizedType) {
>> > +            ParameterizedType paramType = (ParameterizedType)
>> annotated.getBaseType();
>> > +            Type rawType = paramType.getRawType();
>> > +
>> > +            // handle Provider<T>
>> > +            if (rawType instanceof Class && ((Class)
>> rawType).isAssignableFrom(Provider.class) &&
>> paramType.getActualTypeArguments().length == 1) {
>> > +                Class clazz = (Class)
>> paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
>> > +                return (T) new ConfigValueProvider(getConfig(), key,
>> clazz);
>> > +            }
>> > +
>> > +            // handle Optional<T>
>> > +            if (rawType instanceof Class && ((Class)
>> rawType).isAssignableFrom(Optional.class) &&
>> paramType.getActualTypeArguments().length == 1) {
>> > +                Class clazz = (Class)
>> paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
>> > +                return (T) getConfig().getOptionalValue(key, clazz);
>> > +            }
>> > +        }
>> > +        else {
>> > +            Class clazz = (Class) annotated.getBaseType();
>> > +            if (ConfigExtension.isDefaultUnset(defaultValue)) {
>> > +                return (T) getConfig().getValue(key, clazz);
>> > +            }
>> > +            else {
>> > +                Config config = getConfig();
>> > +                return (T) config.getOptionalValue(key, clazz)
>> > +                        .orElse(((ConfigImpl)
>> config).convert(defaultValue, clazz));
>> > +            }
>> > +        }
>> > +
>> > +        throw new IllegalStateException("unhandled ConfigProperty");
>> > +    }
>> > +
>> > +
>> > +    /**
>> > +     * Get the property key to use.
>> > +     * In case the {@link ConfigProperty#name()} is empty we will try
>> to determine the key name from the InjectionPoint.
>> > +     */
>> > +    public static String getConfigKey(InjectionPoint ip,
>> ConfigProperty configProperty) {
>> > +        String key = configProperty.name();
>> > +        if (key.length() > 0) {
>> > +            return key;
>> > +        }
>> > +        if (ip.getAnnotated() instanceof AnnotatedMember) {
>> > +            AnnotatedMember member = (AnnotatedMember)
>> ip.getAnnotated();
>> > +            AnnotatedType declaringType = member.getDeclaringType();
>> > +            if (declaringType != null) {
>> > +                String[] parts =
>> declaringType.getJavaClass().getCanonicalName().split("\\.");
>> > +                String cn = parts[parts.length-1];
>> > +                parts[parts.length-1] =
>> Character.toLowerCase(cn.charAt(0)) + (cn.length() > 1 ? cn.substring(1) :
>> "");
>> > +                StringBuilder sb = new StringBuilder(parts[0]);
>> > +                for (int i = 1; i < parts.length; i++) {
>> > +                    sb.append(".").append(parts[i]);
>> > +                }
>> > +
>> > +                // now add the field name
>> > +
>> sb.append(".").append(member.getJavaMember().getName());
>> > +                return sb.toString();
>> > +            }
>> > +        }
>> > +
>> > +        throw new IllegalStateException("Could not find default name
>> for @ConfigProperty InjectionPoint " + ip);
>> > +    }
>> > +
>> > +    public Config getConfig() {
>> > +        if (_config == null) {
>> > +            _config = ConfigProvider.getConfig();
>> > +        }
>> > +        return _config;
>> > +    }
>> > +
>> > +    @Override
>> >      public void destroy(T instance, CreationalContext<T> context) {
>> > -        // no-op
>> > +
>> >      }
>> >
>> >      @Override
>> > @@ -116,21 +208,17 @@ public abstract class ConfigInjectionBea
>> >
>> >      @Override
>> >      public Set<Class<? extends Annotation>> getStereotypes() {
>> > -        return Collections.emptySet();
>> > +        return Collections.EMPTY_SET;
>> >      }
>> >
>> >      @Override
>> >      public boolean isAlternative() {
>> > -        return alternative;
>> > +        return true;
>> >      }
>> >
>> >      @Override
>> >      public String getId() {
>> > -        return id;
>> > -    }
>> > -
>> > -    InjectionPoint getSimpleInjectionPoint() {
>> > -        return simpleInjectionPoint;
>> > +        return "ConfigInjectionBean_" + rawType.getName();
>> >      }
>> >
>> >      private static class ConfigPropertyLiteral extends
>> AnnotationLiteral<ConfigProperty> implements ConfigProperty {
>> > @@ -145,41 +233,31 @@ public abstract class ConfigInjectionBea
>> >          }
>> >      }
>> >
>> > -    private final InjectionPoint simpleInjectionPoint = new
>> InjectionPoint() {
>> > -
>> > -        @Override
>> > -        public boolean isTransient() {
>> > -            return false;
>> > -        }
>> > -
>> > -        @Override
>> > -        public boolean isDelegate() {
>> > -            return false;
>> > -        }
>> > -
>> > -        @Override
>> > -        public Type getType() {
>> > -            return InjectionPoint.class;
>> > -        }
>> > -
>> > -        @Override
>> > -        public Set<Annotation> getQualifiers() {
>> > -            return Collections.singleton(new
>> AnnotationLiteral<Default>() {});
>> > -        }
>> > -
>> > -        @Override
>> > -        public Member getMember() {
>> > -            return null;
>> > +    /**
>> > +     * A special Provider&lt;T&gt;
>> > +     * This concrete class is needed because we need the injected
>> Provider for the ConfigProperty
>> > +     * to be Serializable. A Lambda would not work in this case
>> > +     */
>> > +    public static class ConfigValueProvider<T> implements Provider<T>,
>> Serializable {
>> > +        private transient Config config;
>> > +        private final String key;
>> > +        private final Class<T> type;
>> > +
>> > +        ConfigValueProvider(Config config, String key, Class<T> type) {
>> > +            this.config = config;
>> > +            this.key = key;
>> > +            this.type = type;
>> >          }
>> >
>> >          @Override
>> > -        public Bean<?> getBean() {
>> > -            return ConfigInjectionBean.this;
>> > +        public T get() {
>> > +            return (T) config.getValue(key, type);
>> > +        }
>> > +
>> > +        private void readObject(java.io.ObjectInputStream in) throws
>> IOException, ClassNotFoundException {
>> > +            in.defaultReadObject();
>> > +            config = ConfigProviderResolver.instance().getConfig();
>> >          }
>> >
>> > -        @Override
>> > -        public Annotated getAnnotated() {
>> > -            return null;
>> > -        }
>> > -    };
>> > +    }
>> >  }
>> >
>> > Modified:
>> geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
>> > URL:
>> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java?rev=1804397&r1=1804396&r2=1804397&view=diff
>> >
>> ==============================================================================
>> > ---
>> geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
>> (original)
>> > +++
>> geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
>> Tue Aug  8 10:55:56 2017
>> > @@ -33,9 +33,12 @@ import org.testng.annotations.Test;
>> >
>> >  public class ProviderTest extends Arquillian {
>> >      private static final String SOME_KEY =
>> "org.apache.geronimo.config.test.internal.somekey";
>> > +    private static final String ANOTHER_KEY =
>> "org.apache.geronimo.config.test.internal.anotherkey";
>> >
>> >      @Deployment
>> >      public static WebArchive deploy() {
>> > +        System.setProperty(SOME_KEY, "someval");
>> > +        System.setProperty(ANOTHER_KEY, "someval");
>> >          JavaArchive testJar = ShrinkWrap
>> >                  .create(JavaArchive.class, "configProviderTest.jar")
>> >                  .addClasses(ProviderTest.class, SomeBean.class)
>> > @@ -70,8 +73,16 @@ public class ProviderTest extends Arquil
>> >          @ConfigProperty(name=SOME_KEY)
>> >          private Provider<String> myconfig;
>> >
>> > +        @Inject
>> > +        @ConfigProperty(name=ANOTHER_KEY)
>> > +        private Provider<String> anotherconfig;
>> > +
>> >          public String getMyconfig() {
>> >              return myconfig.get();
>> >          }
>> > +
>> > +        public Provider<String> getAnotherconfig() {
>> > +            return anotherconfig;
>> > +        }
>> >      }
>> >  }
>> >
>> > Modified: geronimo/components/config/trunk/pom.xml
>> > URL:
>> http://svn.apache.org/viewvc/geronimo/components/config/trunk/pom.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
>> >
>> ==============================================================================
>> > --- geronimo/components/config/trunk/pom.xml (original)
>> > +++ geronimo/components/config/trunk/pom.xml Tue Aug  8 10:55:56 2017
>> > @@ -27,7 +27,7 @@
>> >      </parent>
>> >
>> >      <groupId>org.apache.geronimo.config</groupId>
>> > -    <artifactId>config-parent</artifactId>
>> > +    <artifactId>geronimo-config</artifactId>
>> >      <version>1.1-SNAPSHOT</version>
>> >      <packaging>pom</packaging>
>> >      <name>Geronimo Microprofile Configuration</name>
>> > @@ -50,7 +50,7 @@
>> >      <properties>
>> >          <maven.compiler.source>1.8</maven.compiler.source>
>> >          <maven.compiler.target>1.8</maven.compiler.target>
>> > -
>> <microprofile-config.version>1.1-SNAPSHOT</microprofile-config.version>
>> > +        <microprofile-config.version>1.0</microprofile-config.version>
>> >          <owb.version>1.7.3</owb.version>
>> >          <owb2.version>2.0.1-SNAPSHOT</owb2.version>
>> >          <arquillian.version>1.1.13.Final</arquillian.version>
>> >
>> >
>>
>>
>>

Re: svn commit: r1804397 - in /geronimo/components/config/trunk: ./ impl/ impl/src/main/java/org/apache/geronimo/config/cdi/ impl/src/test/java/org/apache/geronimo/config/test/internal/

Posted by "John D. Ament" <jo...@apache.org>.
I can get to some of it.

We have a couple of issues now though:

https://issues.jboss.org/browse/WELD-2411
https://issues.jboss.org/browse/CDI-712

Martin doesn't feel the spec allows you to override Provider impl's.
Please feel free to weigh in :-)

John

On Tue, Aug 8, 2017 at 7:33 AM Mark Struberg <st...@yahoo.de> wrote:

> Oh I see what you mean.
> Do you mind to re-apply your fix or should I?
>
> Btw, I also tested with the -PWeld3 but I was not able to resolve
> arquillian-weld-embedded:jar:2.0.0-SNAPSHOT
> We might need to add a <repository> for it in the Weld3 profile.
>
> I also would love to add a Weld profile. I thought we have this already
> but seems we missed it?
>
> txs and LieGrue,
> strub
>
> > Am 08.08.2017 um 12:58 schrieb John D. Ament <jo...@apache.org>:
> >
> > One note - hardcoding "isAlternative" to true breaks in Weld.  Unless
> there is a base bean of same type, the alternative is ignored.  Hence why I
> only did isAlternative on the provider type, all others are just regular
> beans.
> >
> > John
> >
> > On Tue, Aug 8, 2017 at 6:55 AM <st...@apache.org> wrote:
> > Author: struberg
> > Date: Tue Aug  8 10:55:56 2017
> > New Revision: 1804397
> >
> > URL: http://svn.apache.org/viewvc?rev=1804397&view=rev
> > Log:
> > GERONIMO-6577 move back to a more dynamic version
> >
> > The goal of r1800748 to calculate all information upfront could not be
> achieved
> > so we move back to the old version
> >
> > Modified:
> >     geronimo/components/config/trunk/impl/debug-suite.xml
> >     geronimo/components/config/trunk/impl/pom.xml
> >
>  geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
> >
>  geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
> >
>  geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
> >     geronimo/components/config/trunk/pom.xml
> >
> > Modified: geronimo/components/config/trunk/impl/debug-suite.xml
> > URL:
> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/debug-suite.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
> >
> ==============================================================================
> > --- geronimo/components/config/trunk/impl/debug-suite.xml (original)
> > +++ geronimo/components/config/trunk/impl/debug-suite.xml Tue Aug  8
> 10:55:56 2017
> > @@ -24,7 +24,7 @@
> >      <classes>
> >          <!-- Issues in the spec -->
> >          <!-- CDI-437 -->
> > -        <class
> name="org.eclipse.microprofile.config.tck.CdiOptionalInjectionTest">
> > +        <class
> name="org.eclipse.microprofile.config.tck.CDIPlainInjectionTest">
> >              <methods>
> >                  <include name=".*"/>
> >              </methods>
> >
> > Modified: geronimo/components/config/trunk/impl/pom.xml
> > URL:
> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/pom.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
> >
> ==============================================================================
> > --- geronimo/components/config/trunk/impl/pom.xml (original)
> > +++ geronimo/components/config/trunk/impl/pom.xml Tue Aug  8 10:55:56
> 2017
> > @@ -27,7 +27,6 @@
> >      </parent>
> >
> >      <artifactId>geronimo-config-impl</artifactId>
> > -    <name>Geronimo Microprofile Configuration :: Implementation</name>
> >
> >      <dependencyManagement>
> >          <dependencies>
> >
> > Modified:
> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
> > URL:
> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java?rev=1804397&r1=1804396&r2=1804397&view=diff
> >
> ==============================================================================
> > ---
> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
> (original)
> > +++
> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
> Tue Aug  8 10:55:56 2017
> > @@ -16,54 +16,38 @@
> >   */
> >  package org.apache.geronimo.config.cdi;
> >
> > -import org.apache.geronimo.config.ConfigImpl;
> > -import org.eclipse.microprofile.config.Config;
> > -import org.eclipse.microprofile.config.inject.ConfigProperty;
> > -import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
> > +import java.lang.reflect.Type;
> > +import java.util.ArrayList;
> > +import java.util.HashMap;
> > +import java.util.HashSet;
> > +import java.util.List;
> > +import java.util.Map;
> > +import java.util.Optional;
> > +import java.util.Set;
> > +import java.util.stream.Collectors;
> >
> > -import javax.enterprise.context.spi.CreationalContext;
> >  import javax.enterprise.event.Observes;
> >  import javax.enterprise.inject.spi.AfterBeanDiscovery;
> >  import javax.enterprise.inject.spi.AfterDeploymentValidation;
> > -import javax.enterprise.inject.spi.AnnotatedMember;
> > -import javax.enterprise.inject.spi.AnnotatedType;
> >  import javax.enterprise.inject.spi.BeanManager;
> > -import javax.enterprise.inject.spi.BeforeBeanDiscovery;
> >  import javax.enterprise.inject.spi.BeforeShutdown;
> > +import javax.enterprise.inject.spi.DeploymentException;
> >  import javax.enterprise.inject.spi.Extension;
> >  import javax.enterprise.inject.spi.InjectionPoint;
> >  import javax.enterprise.inject.spi.ProcessInjectionPoint;
> >  import javax.inject.Provider;
> > -import java.lang.reflect.ParameterizedType;
> > -import java.lang.reflect.Type;
> > -import java.util.ArrayList;
> > -import java.util.Arrays;
> > -import java.util.Collection;
> > -import java.util.HashMap;
> > -import java.util.HashSet;
> > -import java.util.List;
> > -import java.util.Map;
> > -import java.util.Objects;
> > -import java.util.Optional;
> > -import java.util.Set;
> > -import java.util.function.BiFunction;
> > -import java.util.stream.Stream;
> >
> > -import static java.util.function.Function.identity;
> > -import static java.util.stream.Collectors.toMap;
> > -import static org.eclipse.microprofile.config.ConfigProvider.getConfig;
> > +import org.apache.geronimo.config.DefaultConfigProvider;
> > +import org.eclipse.microprofile.config.Config;
> > +import org.eclipse.microprofile.config.ConfigProvider;
> > +import org.eclipse.microprofile.config.inject.ConfigProperty;
> >
> >  /**
> >   * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
> >   */
> >  public class ConfigExtension implements Extension {
> > -    private static final Object NULL = new Object();
> > -
> >      private Config config;
> > -    private ConfigProviderResolver resolver;
> >
> > -    private Set<Injection> injections = new HashSet<>();
> > -    private List<Throwable> deploymentProblems = new ArrayList<>();
> >      private static final Map<Type, Type> REPLACED_TYPES = new
> HashMap<>();
> >
> >      static {
> > @@ -74,336 +58,65 @@ public class ConfigExtension implements
> >          REPLACED_TYPES.put(boolean.class, Boolean.class);
> >      }
> >
> > -    void init(@Observes final BeforeBeanDiscovery beforeBeanDiscovery,
> final BeanManager bm) {
> > -        resolver = ConfigProviderResolver.instance();
> > -        config = getConfig();
> > -    }
> > +    private Set<InjectionPoint> injectionPoints = new HashSet<>();
> > +
> >
> >      public void collectConfigProducer(@Observes
> ProcessInjectionPoint<?, ?> pip) {
> > -        final InjectionPoint injectionPoint = pip.getInjectionPoint();
> > -        final ConfigProperty configProperty =
> injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class);
> > +        ConfigProperty configProperty =
> pip.getInjectionPoint().getAnnotated().getAnnotation(ConfigProperty.class);
> >          if (configProperty != null) {
> > -            Type replacedType =
> REPLACED_TYPES.getOrDefault(injectionPoint.getType(),
> injectionPoint.getType());
> > -            Injection injection = new Injection(replacedType);
> > -            final String key = getConfigKey(injectionPoint,
> configProperty);
> > -            final boolean defaultUnset =
> isDefaultUnset(configProperty.defaultValue());
> > -            if (!injections.add(injection)) {
> > -                final Injection ref = injection;
> > -                injection = injections.stream().filter(i ->
> i.equals(ref)).findFirst().get();
> > -            }
> > -            injection.keys.add(key);
> > -            injection.defaultValues.add(configProperty.defaultValue());
> > -
> > -            final ConfigImpl configImpl = unwrapConfig();
> > -
> > -            // what about lazy runtime lookup, not consistent with tck
> and system prop usage, for now assume optional=optional ;)
> > -            boolean hasValue = true;
> > -            if (defaultUnset) { // value validation
> > -                if (ParameterizedType.class.isInstance(injection.type))
> {
> > -                    final ParameterizedType pt =
> ParameterizedType.class.cast(injection.type);
> > -                    if (pt.getRawType() != Optional.class &&
> !configImpl.getOptionalValue(key, String.class).isPresent()) {
> > -                        hasValue = false;
> > -                    }
> > -                } else if (!configImpl.getOptionalValue(key,
> String.class).isPresent()) {
> > -                    hasValue = false;
> > -                }
> > -                if (!hasValue) {
> > -                    deploymentProblems.add(new
> IllegalArgumentException("No configured value for '" + key + "' from " +
> injectionPoint));
> > -                }
> > -            }
> > -
> > -            Class<?> instanceType = null;
> > -            if (ParameterizedType.class.isInstance(injection.type)) {
> // converters validation
> > -                final ParameterizedType pt =
> ParameterizedType.class.cast(injection.type);
> > -                if (pt.getRawType() == Provider.class &&
> pt.getActualTypeArguments().length == 1 &&
> Class.class.isInstance(pt.getActualTypeArguments()[0])
> > -                        &&
> !configImpl.getConverters().containsKey(Class.class.cast(pt.getActualTypeArguments()[0])))
> {
> > -                    instanceType =
> Class.class.cast(pt.getActualTypeArguments()[0]);
> > -                } // else if Optional it is fine, else we don't know
> how to process
> > -            } else if (Class.class.isInstance(injection.type)) {
> > -                instanceType = Class.class.cast(injection.type);
> > -            }
> > -            if (instanceType != null) { // validate we have a converter
> + we can convert the existing value
> > -                if
> (!configImpl.getConverters().containsKey(instanceType)) {
> > -                    deploymentProblems.add(new
> IllegalArgumentException("Missing converter for '" + key + "' from " +
> injectionPoint));
> > -                } else if (hasValue) {
> > -                    try {
> > -
> configImpl.getConverters().get(injection.type).convert(configImpl.getValue(key));
> > -                    } catch (final RuntimeException re) {
> > -                        deploymentProblems.add(re);
> > -                    }
> > -                }
> > -            }
> > +            injectionPoints.add(pip.getInjectionPoint());
> >          }
> >      }
> >
> >      public void registerConfigProducer(@Observes AfterBeanDiscovery
> abd, BeanManager bm) {
> > -        injections.stream()
> > -                .flatMap(injection -> {
> > -                    final BiFunction<CreationalContext<?>,
> ConfigInjectionBean<?>, String> keyProvider;
> > -                    if (injection.keys.size() == 1) {
> > -                        final String key =
> injection.keys.iterator().next();
> > -                        keyProvider = (ctx, bean) -> key;
> > -                    } else {
> > -                        keyProvider = (ctx, bean) ->
> getName(findInjectionPoint(bm, ctx, bean));
> > -                    }
> > -
> > -                    if
> (ParameterizedType.class.isInstance(injection.type)) {
> > -                        final ParameterizedType paramType =
> ParameterizedType.class.cast(injection.type);
> > -                        final Type rawType = paramType.getRawType();
> > -
> > -                        // todo: do we care of Instance injection?
> doesnt make much sense right?
> > -                        if (Provider.class == rawType &&
> paramType.getActualTypeArguments().length == 1) {
> > -                            if
> (!Class.class.isInstance(paramType.getActualTypeArguments()[0])) {
> > -                                deploymentProblems.add(new
> IllegalArgumentException("@ConfigProperty can only be used with Provider<T>
> where T is a Class"));
> > -                                return Stream.empty();
> > -                            }
> > -                            final Class<?> providerType =
> Class.class.cast(paramType.getActualTypeArguments()[0]);
> > -                            return Stream.of(new
> ConfigInjectionBean<Provider<?>>(injection.type, true) {
> > -                                @Override
> > -                                public Provider<?> create(final
> CreationalContext<Provider<?>> context) {
> > -                                    return () ->
> config.getValue(keyProvider.apply(context, this), providerType);
> > -                                }
> > -                            });
> > -                        } else if (Optional.class == rawType &&
> paramType.getActualTypeArguments().length == 1) {
> > -                            if
> (!Class.class.isInstance(paramType.getActualTypeArguments()[0])) {
> > -                                deploymentProblems.add(new
> IllegalArgumentException("@ConfigProperty can only be used with Optional<T>
> where T is a Class"));
> > -                                return null;
> > -                            }
> > -                            final Class<?> optionalType =
> Class.class.cast(paramType.getActualTypeArguments()[0]);
> > -                            return Stream.of(new
> ConfigInjectionBean<Optional<?>>(injection.type) {
> > -                                @Override
> > -                                public Optional<?> create(final
> CreationalContext<Optional<?>> context) {
> > -                                    return
> config.getOptionalValue(keyProvider.apply(context, this), optionalType);
> > -                                }
> > -                            });
> > -                        } else {
> > -                            deploymentProblems.add(new
> IllegalArgumentException("Unsupported parameterized type " + paramType));
> > -                            return Stream.empty();
> > -                        }
> > -                    } else if (Class.class.isInstance(injection.type)) {
> > -                        final Class clazz =
> Class.class.cast(injection.type);
> > -                        final ConfigInjectionBean bean;
> > -                        if (injection.defaultValues.isEmpty()) {
> > -                            bean = new
> ConfigInjectionBean<Object>(injection.type) {
> > -                                @Override
> > -                                public Object create(final
> CreationalContext<Object> context) {
> > -                                    return
> config.getOptionalValue(keyProvider.apply(context, this), clazz);
> > -                                }
> > -                            };
> > -                        } else if (injection.defaultValues.size() == 1)
> { // common enough to be optimized
> > -                            final String defVal =
> injection.defaultValues.iterator().next();
> > -                            final Object alternativeVal =
> isDefaultUnset(defVal) ? null : unwrapConfig().convert(defVal, clazz);
> > -                            bean = new
> ConfigInjectionBean<Object>(injection.type) {
> > -                                @Override
> > -                                public Object create(final
> CreationalContext<Object> context) {
> > -                                    final Optional optionalValue =
> config.getOptionalValue(keyProvider.apply(context, this), clazz);
> > -                                    return
> optionalValue.orElse(alternativeVal);
> > -                                }
> > -                            };
> > -                        } else { // sadly we need to get back to the
> injection point to know which one we need to use
> > -                            final Map<String, Object> prepared =
> injection.defaultValues.stream()
> > -                                    .collect(toMap(identity(), k ->
> isDefaultUnset(k) ? NULL : unwrapConfig().convert(k, clazz), (a, b) -> b));
> > -                            bean = new
> ConfigInjectionBean<Object>(injection.type) {
> > -                                @Override
> > -                                public Object create(final
> CreationalContext<Object> context) {
> > -                                    final InjectionPoint ip =
> findInjectionPoint(bm, context, this);
> > -                                    if (ip == null) {
> > -                                        throw new
> IllegalStateException("Could not retrieve InjectionPoint");
> > -                                    }
> > -                                    return
> config.getOptionalValue(ConfigExtension.this.getName(ip), clazz)
> > -                                            .orElseGet(() -> {
> > -                                                final Object val =
> prepared.get(ip.getAnnotated().getAnnotation(ConfigProperty.class).defaultValue());
> > -                                                return val == NULL ?
> null : val;
> > -                                            });
> > -                                }
> > -                            };
> > -                        }
> > -
> > -                        final Collection<ConfigInjectionBean<?>> beans
> = new ArrayList<>();
> > -                        beans.add(bean);
> > -
> > -                        // is adding these beans is that useful? we
> captured them all so only a programmatic lookup would justify it
> > -                        // and not sure it would be done this way anyway
> > -                        final ParameterizedTypeImpl providerType = new
> ParameterizedTypeImpl(Provider.class, injection.type);
> > -                        if (injections.stream().noneMatch(i ->
> i.type.equals(providerType))) {
> > -                            beans.add(new
> ConfigInjectionBean<Provider<?>>(providerType, true) {
> > -                                @Override
> > -                                public Provider<?> create(final
> CreationalContext<Provider<?>> context) {
> > -                                    return () -> bean.create(context);
> > -                                }
> > -                            });
> > -                        }
> > -
> > -                        final ParameterizedTypeImpl optionalType = new
> ParameterizedTypeImpl(Optional.class, injection.type);
> > -                        if (injections.stream().noneMatch(i ->
> i.type.equals(optionalType))) {
> > -                            beans.add(new
> ConfigInjectionBean<Optional<?>>(optionalType) {
> > -                                @Override
> > -                                public Optional<?> create(final
> CreationalContext<Optional<?>> context) {
> > -                                    return
> Optional.ofNullable(bean.create(context));
> > -                                }
> > -                            });
> > -                        }
> > -
> > -                        return beans.stream();
> > -                    } else {
> > -                        deploymentProblems.add(new
> IllegalArgumentException("Unknown type " + injection.type));
> > -                        return Stream.empty();
> > -                    }
> > -                })
> > -                .forEach(abd::addBean);
> > -    }
> > +        Set<Class> types = injectionPoints.stream()
> > +                .filter(ip -> ip.getType() instanceof Class)
> > +                .map(ip -> (Class)
> REPLACED_TYPES.getOrDefault(ip.getType(), ip.getType()))
> > +                .collect(Collectors.toSet());
> > +
> > +        // Provider and Optional are ParameterizedTypes and not a
> Class, so we need to add them manually
> > +        types.add(Provider.class);
> > +        types.add(Optional.class);
> >
> > -    public void validate(@Observes AfterDeploymentValidation add) {
> > -        deploymentProblems.forEach(add::addDeploymentProblem);
> > -        injections.clear();
> > -        deploymentProblems.clear();
> > +        types.forEach(type -> abd.addBean(new ConfigInjectionBean(bm,
> type)));
> >      }
> >
> > -    public void shutdown(@Observes BeforeShutdown bsd) {
> > -        resolver.releaseConfig(config);
> > -    }
> > +    public void validate(@Observes AfterDeploymentValidation add) {
> > +        List<String> deploymentProblems = new ArrayList<>();
> >
> > -    private ConfigImpl unwrapConfig() {
> > -        return ConfigImpl.class.cast(config);
> > -    }
> > +        config = ConfigProvider.getConfig();
> >
> > -    private static String getName(final InjectionPoint ip) {
> > -        final ConfigProperty annotation =
> ip.getAnnotated().getAnnotation(ConfigProperty.class);
> > -        final String name = annotation.name();
> > -        return isDefaultUnset(name) ? getConfigKey(ip, annotation) :
> name;
> > -    }
> > +        for (InjectionPoint injectionPoint : injectionPoints) {
> > +            Type type = injectionPoint.getType();
> >
> > -    /**
> > -     * Get the property key to use.
> > -     * In case the {@link ConfigProperty#name()} is empty we will try
> to determine the key name from the InjectionPoint.
> > -     */
> > -    private static String getConfigKey(InjectionPoint ip,
> ConfigProperty configProperty) {
> > -        String key = configProperty.name();
> > -        if (!key.isEmpty()) {
> > -            return key;
> > -        }
> > -        if (ip.getAnnotated() instanceof AnnotatedMember) {
> > -            AnnotatedMember member = (AnnotatedMember)
> ip.getAnnotated();
> > -            AnnotatedType declaringType = member.getDeclaringType();
> > -            if (declaringType != null) {
> > -                String[] parts =
> declaringType.getJavaClass().getCanonicalName().split("\\.");
> > -                String cn = parts[parts.length - 1];
> > -                parts[parts.length - 1] =
> Character.toLowerCase(cn.charAt(0)) + (cn.length() > 1 ? cn.substring(1) :
> "");
> > -                StringBuilder sb = new StringBuilder(parts[0]);
> > -                for (int i = 1; i < parts.length; i++) {
> > -                    sb.append(".").append(parts[i]);
> > +            // replace native types with their Wrapper types
> > +            type = REPLACED_TYPES.getOrDefault(type, type);
> > +
> > +            ConfigProperty configProperty =
> injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class);
> > +            if (type instanceof Class) {
> > +                // a direct injection of a ConfigProperty
> > +                // that means a Converter must exist.
> > +                String key =
> ConfigInjectionBean.getConfigKey(injectionPoint, configProperty);
> > +                if ((isDefaultUnset(configProperty.defaultValue()))
> > +                        && !config.getOptionalValue(key, (Class)
> type).isPresent()) {
> > +                    deploymentProblems.add("No Config Value exists for
> " + key);
> >                  }
> > -
> > -                // now add the field name
> > -                sb.append(".").append(member.getJavaMember().getName());
> > -                return sb.toString();
> >              }
> >          }
> >
> > -        throw new IllegalStateException("Could not find default name
> for @ConfigProperty InjectionPoint " + ip);
> > -    }
> > -
> > -    private static boolean isDefaultUnset(String defaultValue) {
> > -        return defaultValue == null || defaultValue.length() == 0 ||
> defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);
> > -    }
> > -
> > -    private static InjectionPoint findInjectionPoint(final BeanManager
> bm, final CreationalContext<?> ctx,
> > -
>  ConfigInjectionBean bean) {
> > -        return
> InjectionPoint.class.cast(bm.getInjectableReference(bean.getSimpleInjectionPoint(),
> ctx));
> > -    }
> > -
> > -    private static final class Injection {
> > -        private final Type type;
> > -        private final Collection<String> keys = new ArrayList<>();
> > -        private final Collection<String> defaultValues = new
> ArrayList<>();
> > -
> > -        private Injection(final Type type) {
> > -            this.type = type;
> > -        }
> > -
> > -        @Override
> > -        public boolean equals(final Object o) {
> > -            if (this == o) {
> > -                return true;
> > -            }
> > -            if (o == null || Injection.class != o.getClass()) {
> > -                return false;
> > -            }
> > -            final Injection injection = Injection.class.cast(o);
> > -            return Objects.equals(type, injection.type);
> > +        if (!deploymentProblems.isEmpty()) {
> > +            add.addDeploymentProblem(new DeploymentException("Error
> while validating Configuration\n"
> > +                                                             +
> String.join("\n", deploymentProblems)));
> >          }
> >
> > -        @Override
> > -        public int hashCode() {
> > -            return type.hashCode();
> > -        }
> >      }
> >
> > -    private class ParameterizedTypeImpl implements ParameterizedType {
> > -        private final Type rawType;
> > -        private final Type[] types;
> > -
> > -        private ParameterizedTypeImpl(final Type raw, final Type...
> types) {
> > -            this.rawType = raw;
> > -            this.types = types;
> > -        }
> > -
> > -        @Override
> > -        public Type[] getActualTypeArguments() {
> > -            return types.clone();
> > -        }
> > -
> > -        @Override
> > -        public Type getOwnerType() {
> > -            return null;
> > -        }
> > -
> > -        @Override
> > -        public Type getRawType() {
> > -            return rawType;
> > -        }
> > -
> > -        @Override
> > -        public int hashCode() {
> > -            return Arrays.hashCode(types) ^ rawType.hashCode();
> > -        }
> > -
> > -        @Override
> > -        public boolean equals(final Object obj) {
> > -            if (this == obj) {
> > -                return true;
> > -            }
> > -            if (ParameterizedType.class.isInstance(obj)) {
> > -                final ParameterizedType that =
> ParameterizedType.class.cast(obj);
> > -                final Type thatRawType = that.getRawType();
> > -                return (rawType == null ? thatRawType == null :
> rawType.equals(thatRawType))
> > -                        && Arrays.equals(types,
> that.getActualTypeArguments());
> > -            }
> > -            return false;
> > -        }
> > +    public void shutdown(@Observes BeforeShutdown bsd) {
> > +        DefaultConfigProvider.instance().releaseConfig(config);
> > +    }
> >
> > -        @Override
> > -        public String toString() {
> > -            final StringBuilder buffer = new StringBuilder();
> > -            buffer.append(Class.class.cast(rawType).getName());
> > -            final Type[] actualTypes = getActualTypeArguments();
> > -            if (actualTypes.length > 0) {
> > -                buffer.append("<");
> > -                final int length = actualTypes.length;
> > -                for (int i = 0; i < length; i++) {
> > -                    if (actualTypes[i] instanceof Class) {
> > -                        buffer.append(((Class<?>)
> actualTypes[i]).getSimpleName());
> > -                    } else {
> > -                        buffer.append(actualTypes[i].toString());
> > -                    }
> > -                    if (i != actualTypes.length - 1) {
> > -                        buffer.append(",");
> > -                    }
> > -                }
> >
> > -                buffer.append(">");
> > -            }
> > -            return buffer.toString();
> > -        }
> > +    static boolean isDefaultUnset(String defaultValue) {
> > +        return defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);
> >      }
> >  }
> >
> > Modified:
> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
> > URL:
> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java?rev=1804397&r1=1804396&r2=1804397&view=diff
> >
> ==============================================================================
> > ---
> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
> (original)
> > +++
> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
> Tue Aug  8 10:55:56 2017
> > @@ -16,49 +16,59 @@
> >   */
> >  package org.apache.geronimo.config.cdi;
> >
> > -import org.eclipse.microprofile.config.inject.ConfigProperty;
> > +import java.io.IOException;
> > +import java.io.Serializable;
> > +import java.lang.annotation.Annotation;
> > +import java.lang.reflect.ParameterizedType;
> > +import java.lang.reflect.Type;
> > +import java.util.Collections;
> > +import java.util.HashSet;
> > +import java.util.Optional;
> > +import java.util.Set;
> >
> >  import javax.enterprise.context.Dependent;
> >  import javax.enterprise.context.spi.CreationalContext;
> > -import javax.enterprise.inject.Default;
> >  import javax.enterprise.inject.spi.Annotated;
> > +import javax.enterprise.inject.spi.AnnotatedMember;
> > +import javax.enterprise.inject.spi.AnnotatedType;
> >  import javax.enterprise.inject.spi.Bean;
> > +import javax.enterprise.inject.spi.BeanManager;
> >  import javax.enterprise.inject.spi.InjectionPoint;
> >  import javax.enterprise.inject.spi.PassivationCapable;
> >  import javax.enterprise.util.AnnotationLiteral;
> > -import java.lang.annotation.Annotation;
> > -import java.lang.reflect.Member;
> > -import java.lang.reflect.ParameterizedType;
> > -import java.lang.reflect.Type;
> > -import java.util.Collections;
> > -import java.util.HashSet;
> > -import java.util.Set;
> > +import javax.inject.Provider;
> > +
> > +import org.apache.geronimo.config.ConfigImpl;
> > +import org.eclipse.microprofile.config.Config;
> > +import org.eclipse.microprofile.config.ConfigProvider;
> > +import org.eclipse.microprofile.config.inject.ConfigProperty;
> > +import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
> >
> >  /**
> >   * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
> >   */
> > -public abstract class ConfigInjectionBean<T> implements Bean<T>,
> PassivationCapable {
> > +public class ConfigInjectionBean<T> implements Bean<T>,
> PassivationCapable {
> >
> >      private final static Set<Annotation> QUALIFIERS = new HashSet<>();
> >      static {
> >          QUALIFIERS.add(new ConfigPropertyLiteral());
> >      }
> >
> > +    private final BeanManager bm;
> >      private final Class rawType;
> >      private final Set<Type> types;
> > -    private final String id;
> > -    private final boolean alternative;
> > -
> > -    ConfigInjectionBean(Type type) {
> > -        this(type,false);
> > -    }
> >
> > -    ConfigInjectionBean(Type type, boolean alternative) {
> > -        this.types = new HashSet<>();
> > -        this.types.add(type);
> > -        this.rawType = getRawType(type);
> > -        this.id = "ConfigInjectionBean_" + type.toString();
> > -        this.alternative = alternative;
> > +    /**
> > +     * only access via {@link #getConfig(}
> > +     */
> > +    private Config _config;
> > +
> > +    public ConfigInjectionBean(BeanManager bm, Type type) {
> > +        this.bm = bm;
> > +
> > +        types = new HashSet<>();
> > +        types.add(type);
> > +        rawType = getRawType(type);
> >      }
> >
> >      private Class getRawType(Type type) {
> > @@ -76,7 +86,7 @@ public abstract class ConfigInjectionBea
> >
> >      @Override
> >      public Set<InjectionPoint> getInjectionPoints() {
> > -        return Collections.emptySet();
> > +        return Collections.EMPTY_SET;
> >      }
> >
> >      @Override
> > @@ -90,8 +100,90 @@ public abstract class ConfigInjectionBea
> >      }
> >
> >      @Override
> > +    public T create(CreationalContext<T> context) {
> > +        Set<Bean<?>> beans = bm.getBeans(InjectionPoint.class);
> > +        Bean<?> bean = bm.resolve(beans);
> > +        InjectionPoint ip = (InjectionPoint) bm.getReference(bean,
> InjectionPoint.class,  context);
> > +        if (ip == null) {
> > +            throw new IllegalStateException("Could not retrieve
> InjectionPoint");
> > +        }
> > +        Annotated annotated = ip.getAnnotated();
> > +        ConfigProperty configProperty =
> annotated.getAnnotation(ConfigProperty.class);
> > +        String key = getConfigKey(ip, configProperty);
> > +        String defaultValue = configProperty.defaultValue();
> > +
> > +        if (annotated.getBaseType() instanceof ParameterizedType) {
> > +            ParameterizedType paramType = (ParameterizedType)
> annotated.getBaseType();
> > +            Type rawType = paramType.getRawType();
> > +
> > +            // handle Provider<T>
> > +            if (rawType instanceof Class && ((Class)
> rawType).isAssignableFrom(Provider.class) &&
> paramType.getActualTypeArguments().length == 1) {
> > +                Class clazz = (Class)
> paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
> > +                return (T) new ConfigValueProvider(getConfig(), key,
> clazz);
> > +            }
> > +
> > +            // handle Optional<T>
> > +            if (rawType instanceof Class && ((Class)
> rawType).isAssignableFrom(Optional.class) &&
> paramType.getActualTypeArguments().length == 1) {
> > +                Class clazz = (Class)
> paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
> > +                return (T) getConfig().getOptionalValue(key, clazz);
> > +            }
> > +        }
> > +        else {
> > +            Class clazz = (Class) annotated.getBaseType();
> > +            if (ConfigExtension.isDefaultUnset(defaultValue)) {
> > +                return (T) getConfig().getValue(key, clazz);
> > +            }
> > +            else {
> > +                Config config = getConfig();
> > +                return (T) config.getOptionalValue(key, clazz)
> > +                        .orElse(((ConfigImpl)
> config).convert(defaultValue, clazz));
> > +            }
> > +        }
> > +
> > +        throw new IllegalStateException("unhandled ConfigProperty");
> > +    }
> > +
> > +
> > +    /**
> > +     * Get the property key to use.
> > +     * In case the {@link ConfigProperty#name()} is empty we will try
> to determine the key name from the InjectionPoint.
> > +     */
> > +    public static String getConfigKey(InjectionPoint ip, ConfigProperty
> configProperty) {
> > +        String key = configProperty.name();
> > +        if (key.length() > 0) {
> > +            return key;
> > +        }
> > +        if (ip.getAnnotated() instanceof AnnotatedMember) {
> > +            AnnotatedMember member = (AnnotatedMember)
> ip.getAnnotated();
> > +            AnnotatedType declaringType = member.getDeclaringType();
> > +            if (declaringType != null) {
> > +                String[] parts =
> declaringType.getJavaClass().getCanonicalName().split("\\.");
> > +                String cn = parts[parts.length-1];
> > +                parts[parts.length-1] =
> Character.toLowerCase(cn.charAt(0)) + (cn.length() > 1 ? cn.substring(1) :
> "");
> > +                StringBuilder sb = new StringBuilder(parts[0]);
> > +                for (int i = 1; i < parts.length; i++) {
> > +                    sb.append(".").append(parts[i]);
> > +                }
> > +
> > +                // now add the field name
> > +                sb.append(".").append(member.getJavaMember().getName());
> > +                return sb.toString();
> > +            }
> > +        }
> > +
> > +        throw new IllegalStateException("Could not find default name
> for @ConfigProperty InjectionPoint " + ip);
> > +    }
> > +
> > +    public Config getConfig() {
> > +        if (_config == null) {
> > +            _config = ConfigProvider.getConfig();
> > +        }
> > +        return _config;
> > +    }
> > +
> > +    @Override
> >      public void destroy(T instance, CreationalContext<T> context) {
> > -        // no-op
> > +
> >      }
> >
> >      @Override
> > @@ -116,21 +208,17 @@ public abstract class ConfigInjectionBea
> >
> >      @Override
> >      public Set<Class<? extends Annotation>> getStereotypes() {
> > -        return Collections.emptySet();
> > +        return Collections.EMPTY_SET;
> >      }
> >
> >      @Override
> >      public boolean isAlternative() {
> > -        return alternative;
> > +        return true;
> >      }
> >
> >      @Override
> >      public String getId() {
> > -        return id;
> > -    }
> > -
> > -    InjectionPoint getSimpleInjectionPoint() {
> > -        return simpleInjectionPoint;
> > +        return "ConfigInjectionBean_" + rawType.getName();
> >      }
> >
> >      private static class ConfigPropertyLiteral extends
> AnnotationLiteral<ConfigProperty> implements ConfigProperty {
> > @@ -145,41 +233,31 @@ public abstract class ConfigInjectionBea
> >          }
> >      }
> >
> > -    private final InjectionPoint simpleInjectionPoint = new
> InjectionPoint() {
> > -
> > -        @Override
> > -        public boolean isTransient() {
> > -            return false;
> > -        }
> > -
> > -        @Override
> > -        public boolean isDelegate() {
> > -            return false;
> > -        }
> > -
> > -        @Override
> > -        public Type getType() {
> > -            return InjectionPoint.class;
> > -        }
> > -
> > -        @Override
> > -        public Set<Annotation> getQualifiers() {
> > -            return Collections.singleton(new
> AnnotationLiteral<Default>() {});
> > -        }
> > -
> > -        @Override
> > -        public Member getMember() {
> > -            return null;
> > +    /**
> > +     * A special Provider&lt;T&gt;
> > +     * This concrete class is needed because we need the injected
> Provider for the ConfigProperty
> > +     * to be Serializable. A Lambda would not work in this case
> > +     */
> > +    public static class ConfigValueProvider<T> implements Provider<T>,
> Serializable {
> > +        private transient Config config;
> > +        private final String key;
> > +        private final Class<T> type;
> > +
> > +        ConfigValueProvider(Config config, String key, Class<T> type) {
> > +            this.config = config;
> > +            this.key = key;
> > +            this.type = type;
> >          }
> >
> >          @Override
> > -        public Bean<?> getBean() {
> > -            return ConfigInjectionBean.this;
> > +        public T get() {
> > +            return (T) config.getValue(key, type);
> > +        }
> > +
> > +        private void readObject(java.io.ObjectInputStream in) throws
> IOException, ClassNotFoundException {
> > +            in.defaultReadObject();
> > +            config = ConfigProviderResolver.instance().getConfig();
> >          }
> >
> > -        @Override
> > -        public Annotated getAnnotated() {
> > -            return null;
> > -        }
> > -    };
> > +    }
> >  }
> >
> > Modified:
> geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
> > URL:
> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java?rev=1804397&r1=1804396&r2=1804397&view=diff
> >
> ==============================================================================
> > ---
> geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
> (original)
> > +++
> geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
> Tue Aug  8 10:55:56 2017
> > @@ -33,9 +33,12 @@ import org.testng.annotations.Test;
> >
> >  public class ProviderTest extends Arquillian {
> >      private static final String SOME_KEY =
> "org.apache.geronimo.config.test.internal.somekey";
> > +    private static final String ANOTHER_KEY =
> "org.apache.geronimo.config.test.internal.anotherkey";
> >
> >      @Deployment
> >      public static WebArchive deploy() {
> > +        System.setProperty(SOME_KEY, "someval");
> > +        System.setProperty(ANOTHER_KEY, "someval");
> >          JavaArchive testJar = ShrinkWrap
> >                  .create(JavaArchive.class, "configProviderTest.jar")
> >                  .addClasses(ProviderTest.class, SomeBean.class)
> > @@ -70,8 +73,16 @@ public class ProviderTest extends Arquil
> >          @ConfigProperty(name=SOME_KEY)
> >          private Provider<String> myconfig;
> >
> > +        @Inject
> > +        @ConfigProperty(name=ANOTHER_KEY)
> > +        private Provider<String> anotherconfig;
> > +
> >          public String getMyconfig() {
> >              return myconfig.get();
> >          }
> > +
> > +        public Provider<String> getAnotherconfig() {
> > +            return anotherconfig;
> > +        }
> >      }
> >  }
> >
> > Modified: geronimo/components/config/trunk/pom.xml
> > URL:
> http://svn.apache.org/viewvc/geronimo/components/config/trunk/pom.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
> >
> ==============================================================================
> > --- geronimo/components/config/trunk/pom.xml (original)
> > +++ geronimo/components/config/trunk/pom.xml Tue Aug  8 10:55:56 2017
> > @@ -27,7 +27,7 @@
> >      </parent>
> >
> >      <groupId>org.apache.geronimo.config</groupId>
> > -    <artifactId>config-parent</artifactId>
> > +    <artifactId>geronimo-config</artifactId>
> >      <version>1.1-SNAPSHOT</version>
> >      <packaging>pom</packaging>
> >      <name>Geronimo Microprofile Configuration</name>
> > @@ -50,7 +50,7 @@
> >      <properties>
> >          <maven.compiler.source>1.8</maven.compiler.source>
> >          <maven.compiler.target>1.8</maven.compiler.target>
> > -
> <microprofile-config.version>1.1-SNAPSHOT</microprofile-config.version>
> > +        <microprofile-config.version>1.0</microprofile-config.version>
> >          <owb.version>1.7.3</owb.version>
> >          <owb2.version>2.0.1-SNAPSHOT</owb2.version>
> >          <arquillian.version>1.1.13.Final</arquillian.version>
> >
> >
>
>
>

Re: svn commit: r1804397 - in /geronimo/components/config/trunk: ./ impl/ impl/src/main/java/org/apache/geronimo/config/cdi/ impl/src/test/java/org/apache/geronimo/config/test/internal/

Posted by Mark Struberg <st...@yahoo.de>.
Oh I see what you mean. 
Do you mind to re-apply your fix or should I?

Btw, I also tested with the -PWeld3 but I was not able to resolve arquillian-weld-embedded:jar:2.0.0-SNAPSHOT
We might need to add a <repository> for it in the Weld3 profile.

I also would love to add a Weld profile. I thought we have this already but seems we missed it?

txs and LieGrue,
strub

> Am 08.08.2017 um 12:58 schrieb John D. Ament <jo...@apache.org>:
> 
> One note - hardcoding "isAlternative" to true breaks in Weld.  Unless there is a base bean of same type, the alternative is ignored.  Hence why I only did isAlternative on the provider type, all others are just regular beans.
> 
> John
> 
> On Tue, Aug 8, 2017 at 6:55 AM <st...@apache.org> wrote:
> Author: struberg
> Date: Tue Aug  8 10:55:56 2017
> New Revision: 1804397
> 
> URL: http://svn.apache.org/viewvc?rev=1804397&view=rev
> Log:
> GERONIMO-6577 move back to a more dynamic version
> 
> The goal of r1800748 to calculate all information upfront could not be achieved
> so we move back to the old version
> 
> Modified:
>     geronimo/components/config/trunk/impl/debug-suite.xml
>     geronimo/components/config/trunk/impl/pom.xml
>     geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
>     geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
>     geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
>     geronimo/components/config/trunk/pom.xml
> 
> Modified: geronimo/components/config/trunk/impl/debug-suite.xml
> URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/debug-suite.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
> ==============================================================================
> --- geronimo/components/config/trunk/impl/debug-suite.xml (original)
> +++ geronimo/components/config/trunk/impl/debug-suite.xml Tue Aug  8 10:55:56 2017
> @@ -24,7 +24,7 @@
>      <classes>
>          <!-- Issues in the spec -->
>          <!-- CDI-437 -->
> -        <class name="org.eclipse.microprofile.config.tck.CdiOptionalInjectionTest">
> +        <class name="org.eclipse.microprofile.config.tck.CDIPlainInjectionTest">
>              <methods>
>                  <include name=".*"/>
>              </methods>
> 
> Modified: geronimo/components/config/trunk/impl/pom.xml
> URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/pom.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
> ==============================================================================
> --- geronimo/components/config/trunk/impl/pom.xml (original)
> +++ geronimo/components/config/trunk/impl/pom.xml Tue Aug  8 10:55:56 2017
> @@ -27,7 +27,6 @@
>      </parent>
> 
>      <artifactId>geronimo-config-impl</artifactId>
> -    <name>Geronimo Microprofile Configuration :: Implementation</name>
> 
>      <dependencyManagement>
>          <dependencies>
> 
> Modified: geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
> URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java?rev=1804397&r1=1804396&r2=1804397&view=diff
> ==============================================================================
> --- geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java (original)
> +++ geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java Tue Aug  8 10:55:56 2017
> @@ -16,54 +16,38 @@
>   */
>  package org.apache.geronimo.config.cdi;
> 
> -import org.apache.geronimo.config.ConfigImpl;
> -import org.eclipse.microprofile.config.Config;
> -import org.eclipse.microprofile.config.inject.ConfigProperty;
> -import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
> +import java.lang.reflect.Type;
> +import java.util.ArrayList;
> +import java.util.HashMap;
> +import java.util.HashSet;
> +import java.util.List;
> +import java.util.Map;
> +import java.util.Optional;
> +import java.util.Set;
> +import java.util.stream.Collectors;
> 
> -import javax.enterprise.context.spi.CreationalContext;
>  import javax.enterprise.event.Observes;
>  import javax.enterprise.inject.spi.AfterBeanDiscovery;
>  import javax.enterprise.inject.spi.AfterDeploymentValidation;
> -import javax.enterprise.inject.spi.AnnotatedMember;
> -import javax.enterprise.inject.spi.AnnotatedType;
>  import javax.enterprise.inject.spi.BeanManager;
> -import javax.enterprise.inject.spi.BeforeBeanDiscovery;
>  import javax.enterprise.inject.spi.BeforeShutdown;
> +import javax.enterprise.inject.spi.DeploymentException;
>  import javax.enterprise.inject.spi.Extension;
>  import javax.enterprise.inject.spi.InjectionPoint;
>  import javax.enterprise.inject.spi.ProcessInjectionPoint;
>  import javax.inject.Provider;
> -import java.lang.reflect.ParameterizedType;
> -import java.lang.reflect.Type;
> -import java.util.ArrayList;
> -import java.util.Arrays;
> -import java.util.Collection;
> -import java.util.HashMap;
> -import java.util.HashSet;
> -import java.util.List;
> -import java.util.Map;
> -import java.util.Objects;
> -import java.util.Optional;
> -import java.util.Set;
> -import java.util.function.BiFunction;
> -import java.util.stream.Stream;
> 
> -import static java.util.function.Function.identity;
> -import static java.util.stream.Collectors.toMap;
> -import static org.eclipse.microprofile.config.ConfigProvider.getConfig;
> +import org.apache.geronimo.config.DefaultConfigProvider;
> +import org.eclipse.microprofile.config.Config;
> +import org.eclipse.microprofile.config.ConfigProvider;
> +import org.eclipse.microprofile.config.inject.ConfigProperty;
> 
>  /**
>   * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
>   */
>  public class ConfigExtension implements Extension {
> -    private static final Object NULL = new Object();
> -
>      private Config config;
> -    private ConfigProviderResolver resolver;
> 
> -    private Set<Injection> injections = new HashSet<>();
> -    private List<Throwable> deploymentProblems = new ArrayList<>();
>      private static final Map<Type, Type> REPLACED_TYPES = new HashMap<>();
> 
>      static {
> @@ -74,336 +58,65 @@ public class ConfigExtension implements
>          REPLACED_TYPES.put(boolean.class, Boolean.class);
>      }
> 
> -    void init(@Observes final BeforeBeanDiscovery beforeBeanDiscovery, final BeanManager bm) {
> -        resolver = ConfigProviderResolver.instance();
> -        config = getConfig();
> -    }
> +    private Set<InjectionPoint> injectionPoints = new HashSet<>();
> +
> 
>      public void collectConfigProducer(@Observes ProcessInjectionPoint<?, ?> pip) {
> -        final InjectionPoint injectionPoint = pip.getInjectionPoint();
> -        final ConfigProperty configProperty = injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class);
> +        ConfigProperty configProperty = pip.getInjectionPoint().getAnnotated().getAnnotation(ConfigProperty.class);
>          if (configProperty != null) {
> -            Type replacedType = REPLACED_TYPES.getOrDefault(injectionPoint.getType(), injectionPoint.getType());
> -            Injection injection = new Injection(replacedType);
> -            final String key = getConfigKey(injectionPoint, configProperty);
> -            final boolean defaultUnset = isDefaultUnset(configProperty.defaultValue());
> -            if (!injections.add(injection)) {
> -                final Injection ref = injection;
> -                injection = injections.stream().filter(i -> i.equals(ref)).findFirst().get();
> -            }
> -            injection.keys.add(key);
> -            injection.defaultValues.add(configProperty.defaultValue());
> -
> -            final ConfigImpl configImpl = unwrapConfig();
> -
> -            // what about lazy runtime lookup, not consistent with tck and system prop usage, for now assume optional=optional ;)
> -            boolean hasValue = true;
> -            if (defaultUnset) { // value validation
> -                if (ParameterizedType.class.isInstance(injection.type)) {
> -                    final ParameterizedType pt = ParameterizedType.class.cast(injection.type);
> -                    if (pt.getRawType() != Optional.class && !configImpl.getOptionalValue(key, String.class).isPresent()) {
> -                        hasValue = false;
> -                    }
> -                } else if (!configImpl.getOptionalValue(key, String.class).isPresent()) {
> -                    hasValue = false;
> -                }
> -                if (!hasValue) {
> -                    deploymentProblems.add(new IllegalArgumentException("No configured value for '" + key + "' from " + injectionPoint));
> -                }
> -            }
> -
> -            Class<?> instanceType = null;
> -            if (ParameterizedType.class.isInstance(injection.type)) { // converters validation
> -                final ParameterizedType pt = ParameterizedType.class.cast(injection.type);
> -                if (pt.getRawType() == Provider.class && pt.getActualTypeArguments().length == 1 && Class.class.isInstance(pt.getActualTypeArguments()[0])
> -                        && !configImpl.getConverters().containsKey(Class.class.cast(pt.getActualTypeArguments()[0]))) {
> -                    instanceType = Class.class.cast(pt.getActualTypeArguments()[0]);
> -                } // else if Optional it is fine, else we don't know how to process
> -            } else if (Class.class.isInstance(injection.type)) {
> -                instanceType = Class.class.cast(injection.type);
> -            }
> -            if (instanceType != null) { // validate we have a converter + we can convert the existing value
> -                if (!configImpl.getConverters().containsKey(instanceType)) {
> -                    deploymentProblems.add(new IllegalArgumentException("Missing converter for '" + key + "' from " + injectionPoint));
> -                } else if (hasValue) {
> -                    try {
> -                        configImpl.getConverters().get(injection.type).convert(configImpl.getValue(key));
> -                    } catch (final RuntimeException re) {
> -                        deploymentProblems.add(re);
> -                    }
> -                }
> -            }
> +            injectionPoints.add(pip.getInjectionPoint());
>          }
>      }
> 
>      public void registerConfigProducer(@Observes AfterBeanDiscovery abd, BeanManager bm) {
> -        injections.stream()
> -                .flatMap(injection -> {
> -                    final BiFunction<CreationalContext<?>, ConfigInjectionBean<?>, String> keyProvider;
> -                    if (injection.keys.size() == 1) {
> -                        final String key = injection.keys.iterator().next();
> -                        keyProvider = (ctx, bean) -> key;
> -                    } else {
> -                        keyProvider = (ctx, bean) -> getName(findInjectionPoint(bm, ctx, bean));
> -                    }
> -
> -                    if (ParameterizedType.class.isInstance(injection.type)) {
> -                        final ParameterizedType paramType = ParameterizedType.class.cast(injection.type);
> -                        final Type rawType = paramType.getRawType();
> -
> -                        // todo: do we care of Instance injection? doesnt make much sense right?
> -                        if (Provider.class == rawType && paramType.getActualTypeArguments().length == 1) {
> -                            if (!Class.class.isInstance(paramType.getActualTypeArguments()[0])) {
> -                                deploymentProblems.add(new IllegalArgumentException("@ConfigProperty can only be used with Provider<T> where T is a Class"));
> -                                return Stream.empty();
> -                            }
> -                            final Class<?> providerType = Class.class.cast(paramType.getActualTypeArguments()[0]);
> -                            return Stream.of(new ConfigInjectionBean<Provider<?>>(injection.type, true) {
> -                                @Override
> -                                public Provider<?> create(final CreationalContext<Provider<?>> context) {
> -                                    return () -> config.getValue(keyProvider.apply(context, this), providerType);
> -                                }
> -                            });
> -                        } else if (Optional.class == rawType && paramType.getActualTypeArguments().length == 1) {
> -                            if (!Class.class.isInstance(paramType.getActualTypeArguments()[0])) {
> -                                deploymentProblems.add(new IllegalArgumentException("@ConfigProperty can only be used with Optional<T> where T is a Class"));
> -                                return null;
> -                            }
> -                            final Class<?> optionalType = Class.class.cast(paramType.getActualTypeArguments()[0]);
> -                            return Stream.of(new ConfigInjectionBean<Optional<?>>(injection.type) {
> -                                @Override
> -                                public Optional<?> create(final CreationalContext<Optional<?>> context) {
> -                                    return config.getOptionalValue(keyProvider.apply(context, this), optionalType);
> -                                }
> -                            });
> -                        } else {
> -                            deploymentProblems.add(new IllegalArgumentException("Unsupported parameterized type " + paramType));
> -                            return Stream.empty();
> -                        }
> -                    } else if (Class.class.isInstance(injection.type)) {
> -                        final Class clazz = Class.class.cast(injection.type);
> -                        final ConfigInjectionBean bean;
> -                        if (injection.defaultValues.isEmpty()) {
> -                            bean = new ConfigInjectionBean<Object>(injection.type) {
> -                                @Override
> -                                public Object create(final CreationalContext<Object> context) {
> -                                    return config.getOptionalValue(keyProvider.apply(context, this), clazz);
> -                                }
> -                            };
> -                        } else if (injection.defaultValues.size() == 1) { // common enough to be optimized
> -                            final String defVal = injection.defaultValues.iterator().next();
> -                            final Object alternativeVal = isDefaultUnset(defVal) ? null : unwrapConfig().convert(defVal, clazz);
> -                            bean = new ConfigInjectionBean<Object>(injection.type) {
> -                                @Override
> -                                public Object create(final CreationalContext<Object> context) {
> -                                    final Optional optionalValue = config.getOptionalValue(keyProvider.apply(context, this), clazz);
> -                                    return optionalValue.orElse(alternativeVal);
> -                                }
> -                            };
> -                        } else { // sadly we need to get back to the injection point to know which one we need to use
> -                            final Map<String, Object> prepared = injection.defaultValues.stream()
> -                                    .collect(toMap(identity(), k -> isDefaultUnset(k) ? NULL : unwrapConfig().convert(k, clazz), (a, b) -> b));
> -                            bean = new ConfigInjectionBean<Object>(injection.type) {
> -                                @Override
> -                                public Object create(final CreationalContext<Object> context) {
> -                                    final InjectionPoint ip = findInjectionPoint(bm, context, this);
> -                                    if (ip == null) {
> -                                        throw new IllegalStateException("Could not retrieve InjectionPoint");
> -                                    }
> -                                    return config.getOptionalValue(ConfigExtension.this.getName(ip), clazz)
> -                                            .orElseGet(() -> {
> -                                                final Object val = prepared.get(ip.getAnnotated().getAnnotation(ConfigProperty.class).defaultValue());
> -                                                return val == NULL ? null : val;
> -                                            });
> -                                }
> -                            };
> -                        }
> -
> -                        final Collection<ConfigInjectionBean<?>> beans = new ArrayList<>();
> -                        beans.add(bean);
> -
> -                        // is adding these beans is that useful? we captured them all so only a programmatic lookup would justify it
> -                        // and not sure it would be done this way anyway
> -                        final ParameterizedTypeImpl providerType = new ParameterizedTypeImpl(Provider.class, injection.type);
> -                        if (injections.stream().noneMatch(i -> i.type.equals(providerType))) {
> -                            beans.add(new ConfigInjectionBean<Provider<?>>(providerType, true) {
> -                                @Override
> -                                public Provider<?> create(final CreationalContext<Provider<?>> context) {
> -                                    return () -> bean.create(context);
> -                                }
> -                            });
> -                        }
> -
> -                        final ParameterizedTypeImpl optionalType = new ParameterizedTypeImpl(Optional.class, injection.type);
> -                        if (injections.stream().noneMatch(i -> i.type.equals(optionalType))) {
> -                            beans.add(new ConfigInjectionBean<Optional<?>>(optionalType) {
> -                                @Override
> -                                public Optional<?> create(final CreationalContext<Optional<?>> context) {
> -                                    return Optional.ofNullable(bean.create(context));
> -                                }
> -                            });
> -                        }
> -
> -                        return beans.stream();
> -                    } else {
> -                        deploymentProblems.add(new IllegalArgumentException("Unknown type " + injection.type));
> -                        return Stream.empty();
> -                    }
> -                })
> -                .forEach(abd::addBean);
> -    }
> +        Set<Class> types = injectionPoints.stream()
> +                .filter(ip -> ip.getType() instanceof Class)
> +                .map(ip -> (Class) REPLACED_TYPES.getOrDefault(ip.getType(), ip.getType()))
> +                .collect(Collectors.toSet());
> +
> +        // Provider and Optional are ParameterizedTypes and not a Class, so we need to add them manually
> +        types.add(Provider.class);
> +        types.add(Optional.class);
> 
> -    public void validate(@Observes AfterDeploymentValidation add) {
> -        deploymentProblems.forEach(add::addDeploymentProblem);
> -        injections.clear();
> -        deploymentProblems.clear();
> +        types.forEach(type -> abd.addBean(new ConfigInjectionBean(bm, type)));
>      }
> 
> -    public void shutdown(@Observes BeforeShutdown bsd) {
> -        resolver.releaseConfig(config);
> -    }
> +    public void validate(@Observes AfterDeploymentValidation add) {
> +        List<String> deploymentProblems = new ArrayList<>();
> 
> -    private ConfigImpl unwrapConfig() {
> -        return ConfigImpl.class.cast(config);
> -    }
> +        config = ConfigProvider.getConfig();
> 
> -    private static String getName(final InjectionPoint ip) {
> -        final ConfigProperty annotation = ip.getAnnotated().getAnnotation(ConfigProperty.class);
> -        final String name = annotation.name();
> -        return isDefaultUnset(name) ? getConfigKey(ip, annotation) : name;
> -    }
> +        for (InjectionPoint injectionPoint : injectionPoints) {
> +            Type type = injectionPoint.getType();
> 
> -    /**
> -     * Get the property key to use.
> -     * In case the {@link ConfigProperty#name()} is empty we will try to determine the key name from the InjectionPoint.
> -     */
> -    private static String getConfigKey(InjectionPoint ip, ConfigProperty configProperty) {
> -        String key = configProperty.name();
> -        if (!key.isEmpty()) {
> -            return key;
> -        }
> -        if (ip.getAnnotated() instanceof AnnotatedMember) {
> -            AnnotatedMember member = (AnnotatedMember) ip.getAnnotated();
> -            AnnotatedType declaringType = member.getDeclaringType();
> -            if (declaringType != null) {
> -                String[] parts = declaringType.getJavaClass().getCanonicalName().split("\\.");
> -                String cn = parts[parts.length - 1];
> -                parts[parts.length - 1] = Character.toLowerCase(cn.charAt(0)) + (cn.length() > 1 ? cn.substring(1) : "");
> -                StringBuilder sb = new StringBuilder(parts[0]);
> -                for (int i = 1; i < parts.length; i++) {
> -                    sb.append(".").append(parts[i]);
> +            // replace native types with their Wrapper types
> +            type = REPLACED_TYPES.getOrDefault(type, type);
> +
> +            ConfigProperty configProperty = injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class);
> +            if (type instanceof Class) {
> +                // a direct injection of a ConfigProperty
> +                // that means a Converter must exist.
> +                String key = ConfigInjectionBean.getConfigKey(injectionPoint, configProperty);
> +                if ((isDefaultUnset(configProperty.defaultValue()))
> +                        && !config.getOptionalValue(key, (Class) type).isPresent()) {
> +                    deploymentProblems.add("No Config Value exists for " + key);
>                  }
> -
> -                // now add the field name
> -                sb.append(".").append(member.getJavaMember().getName());
> -                return sb.toString();
>              }
>          }
> 
> -        throw new IllegalStateException("Could not find default name for @ConfigProperty InjectionPoint " + ip);
> -    }
> -
> -    private static boolean isDefaultUnset(String defaultValue) {
> -        return defaultValue == null || defaultValue.length() == 0 || defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);
> -    }
> -
> -    private static InjectionPoint findInjectionPoint(final BeanManager bm, final CreationalContext<?> ctx,
> -                                                     ConfigInjectionBean bean) {
> -        return InjectionPoint.class.cast(bm.getInjectableReference(bean.getSimpleInjectionPoint(), ctx));
> -    }
> -
> -    private static final class Injection {
> -        private final Type type;
> -        private final Collection<String> keys = new ArrayList<>();
> -        private final Collection<String> defaultValues = new ArrayList<>();
> -
> -        private Injection(final Type type) {
> -            this.type = type;
> -        }
> -
> -        @Override
> -        public boolean equals(final Object o) {
> -            if (this == o) {
> -                return true;
> -            }
> -            if (o == null || Injection.class != o.getClass()) {
> -                return false;
> -            }
> -            final Injection injection = Injection.class.cast(o);
> -            return Objects.equals(type, injection.type);
> +        if (!deploymentProblems.isEmpty()) {
> +            add.addDeploymentProblem(new DeploymentException("Error while validating Configuration\n"
> +                                                             + String.join("\n", deploymentProblems)));
>          }
> 
> -        @Override
> -        public int hashCode() {
> -            return type.hashCode();
> -        }
>      }
> 
> -    private class ParameterizedTypeImpl implements ParameterizedType {
> -        private final Type rawType;
> -        private final Type[] types;
> -
> -        private ParameterizedTypeImpl(final Type raw, final Type... types) {
> -            this.rawType = raw;
> -            this.types = types;
> -        }
> -
> -        @Override
> -        public Type[] getActualTypeArguments() {
> -            return types.clone();
> -        }
> -
> -        @Override
> -        public Type getOwnerType() {
> -            return null;
> -        }
> -
> -        @Override
> -        public Type getRawType() {
> -            return rawType;
> -        }
> -
> -        @Override
> -        public int hashCode() {
> -            return Arrays.hashCode(types) ^ rawType.hashCode();
> -        }
> -
> -        @Override
> -        public boolean equals(final Object obj) {
> -            if (this == obj) {
> -                return true;
> -            }
> -            if (ParameterizedType.class.isInstance(obj)) {
> -                final ParameterizedType that = ParameterizedType.class.cast(obj);
> -                final Type thatRawType = that.getRawType();
> -                return (rawType == null ? thatRawType == null : rawType.equals(thatRawType))
> -                        && Arrays.equals(types, that.getActualTypeArguments());
> -            }
> -            return false;
> -        }
> +    public void shutdown(@Observes BeforeShutdown bsd) {
> +        DefaultConfigProvider.instance().releaseConfig(config);
> +    }
> 
> -        @Override
> -        public String toString() {
> -            final StringBuilder buffer = new StringBuilder();
> -            buffer.append(Class.class.cast(rawType).getName());
> -            final Type[] actualTypes = getActualTypeArguments();
> -            if (actualTypes.length > 0) {
> -                buffer.append("<");
> -                final int length = actualTypes.length;
> -                for (int i = 0; i < length; i++) {
> -                    if (actualTypes[i] instanceof Class) {
> -                        buffer.append(((Class<?>) actualTypes[i]).getSimpleName());
> -                    } else {
> -                        buffer.append(actualTypes[i].toString());
> -                    }
> -                    if (i != actualTypes.length - 1) {
> -                        buffer.append(",");
> -                    }
> -                }
> 
> -                buffer.append(">");
> -            }
> -            return buffer.toString();
> -        }
> +    static boolean isDefaultUnset(String defaultValue) {
> +        return defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);
>      }
>  }
> 
> Modified: geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
> URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java?rev=1804397&r1=1804396&r2=1804397&view=diff
> ==============================================================================
> --- geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java (original)
> +++ geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java Tue Aug  8 10:55:56 2017
> @@ -16,49 +16,59 @@
>   */
>  package org.apache.geronimo.config.cdi;
> 
> -import org.eclipse.microprofile.config.inject.ConfigProperty;
> +import java.io.IOException;
> +import java.io.Serializable;
> +import java.lang.annotation.Annotation;
> +import java.lang.reflect.ParameterizedType;
> +import java.lang.reflect.Type;
> +import java.util.Collections;
> +import java.util.HashSet;
> +import java.util.Optional;
> +import java.util.Set;
> 
>  import javax.enterprise.context.Dependent;
>  import javax.enterprise.context.spi.CreationalContext;
> -import javax.enterprise.inject.Default;
>  import javax.enterprise.inject.spi.Annotated;
> +import javax.enterprise.inject.spi.AnnotatedMember;
> +import javax.enterprise.inject.spi.AnnotatedType;
>  import javax.enterprise.inject.spi.Bean;
> +import javax.enterprise.inject.spi.BeanManager;
>  import javax.enterprise.inject.spi.InjectionPoint;
>  import javax.enterprise.inject.spi.PassivationCapable;
>  import javax.enterprise.util.AnnotationLiteral;
> -import java.lang.annotation.Annotation;
> -import java.lang.reflect.Member;
> -import java.lang.reflect.ParameterizedType;
> -import java.lang.reflect.Type;
> -import java.util.Collections;
> -import java.util.HashSet;
> -import java.util.Set;
> +import javax.inject.Provider;
> +
> +import org.apache.geronimo.config.ConfigImpl;
> +import org.eclipse.microprofile.config.Config;
> +import org.eclipse.microprofile.config.ConfigProvider;
> +import org.eclipse.microprofile.config.inject.ConfigProperty;
> +import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
> 
>  /**
>   * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
>   */
> -public abstract class ConfigInjectionBean<T> implements Bean<T>, PassivationCapable {
> +public class ConfigInjectionBean<T> implements Bean<T>, PassivationCapable {
> 
>      private final static Set<Annotation> QUALIFIERS = new HashSet<>();
>      static {
>          QUALIFIERS.add(new ConfigPropertyLiteral());
>      }
> 
> +    private final BeanManager bm;
>      private final Class rawType;
>      private final Set<Type> types;
> -    private final String id;
> -    private final boolean alternative;
> -
> -    ConfigInjectionBean(Type type) {
> -        this(type,false);
> -    }
> 
> -    ConfigInjectionBean(Type type, boolean alternative) {
> -        this.types = new HashSet<>();
> -        this.types.add(type);
> -        this.rawType = getRawType(type);
> -        this.id = "ConfigInjectionBean_" + type.toString();
> -        this.alternative = alternative;
> +    /**
> +     * only access via {@link #getConfig(}
> +     */
> +    private Config _config;
> +
> +    public ConfigInjectionBean(BeanManager bm, Type type) {
> +        this.bm = bm;
> +
> +        types = new HashSet<>();
> +        types.add(type);
> +        rawType = getRawType(type);
>      }
> 
>      private Class getRawType(Type type) {
> @@ -76,7 +86,7 @@ public abstract class ConfigInjectionBea
> 
>      @Override
>      public Set<InjectionPoint> getInjectionPoints() {
> -        return Collections.emptySet();
> +        return Collections.EMPTY_SET;
>      }
> 
>      @Override
> @@ -90,8 +100,90 @@ public abstract class ConfigInjectionBea
>      }
> 
>      @Override
> +    public T create(CreationalContext<T> context) {
> +        Set<Bean<?>> beans = bm.getBeans(InjectionPoint.class);
> +        Bean<?> bean = bm.resolve(beans);
> +        InjectionPoint ip = (InjectionPoint) bm.getReference(bean, InjectionPoint.class,  context);
> +        if (ip == null) {
> +            throw new IllegalStateException("Could not retrieve InjectionPoint");
> +        }
> +        Annotated annotated = ip.getAnnotated();
> +        ConfigProperty configProperty = annotated.getAnnotation(ConfigProperty.class);
> +        String key = getConfigKey(ip, configProperty);
> +        String defaultValue = configProperty.defaultValue();
> +
> +        if (annotated.getBaseType() instanceof ParameterizedType) {
> +            ParameterizedType paramType = (ParameterizedType) annotated.getBaseType();
> +            Type rawType = paramType.getRawType();
> +
> +            // handle Provider<T>
> +            if (rawType instanceof Class && ((Class) rawType).isAssignableFrom(Provider.class) && paramType.getActualTypeArguments().length == 1) {
> +                Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
> +                return (T) new ConfigValueProvider(getConfig(), key, clazz);
> +            }
> +
> +            // handle Optional<T>
> +            if (rawType instanceof Class && ((Class) rawType).isAssignableFrom(Optional.class) && paramType.getActualTypeArguments().length == 1) {
> +                Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
> +                return (T) getConfig().getOptionalValue(key, clazz);
> +            }
> +        }
> +        else {
> +            Class clazz = (Class) annotated.getBaseType();
> +            if (ConfigExtension.isDefaultUnset(defaultValue)) {
> +                return (T) getConfig().getValue(key, clazz);
> +            }
> +            else {
> +                Config config = getConfig();
> +                return (T) config.getOptionalValue(key, clazz)
> +                        .orElse(((ConfigImpl) config).convert(defaultValue, clazz));
> +            }
> +        }
> +
> +        throw new IllegalStateException("unhandled ConfigProperty");
> +    }
> +
> +
> +    /**
> +     * Get the property key to use.
> +     * In case the {@link ConfigProperty#name()} is empty we will try to determine the key name from the InjectionPoint.
> +     */
> +    public static String getConfigKey(InjectionPoint ip, ConfigProperty configProperty) {
> +        String key = configProperty.name();
> +        if (key.length() > 0) {
> +            return key;
> +        }
> +        if (ip.getAnnotated() instanceof AnnotatedMember) {
> +            AnnotatedMember member = (AnnotatedMember) ip.getAnnotated();
> +            AnnotatedType declaringType = member.getDeclaringType();
> +            if (declaringType != null) {
> +                String[] parts = declaringType.getJavaClass().getCanonicalName().split("\\.");
> +                String cn = parts[parts.length-1];
> +                parts[parts.length-1] = Character.toLowerCase(cn.charAt(0)) + (cn.length() > 1 ? cn.substring(1) : "");
> +                StringBuilder sb = new StringBuilder(parts[0]);
> +                for (int i = 1; i < parts.length; i++) {
> +                    sb.append(".").append(parts[i]);
> +                }
> +
> +                // now add the field name
> +                sb.append(".").append(member.getJavaMember().getName());
> +                return sb.toString();
> +            }
> +        }
> +
> +        throw new IllegalStateException("Could not find default name for @ConfigProperty InjectionPoint " + ip);
> +    }
> +
> +    public Config getConfig() {
> +        if (_config == null) {
> +            _config = ConfigProvider.getConfig();
> +        }
> +        return _config;
> +    }
> +
> +    @Override
>      public void destroy(T instance, CreationalContext<T> context) {
> -        // no-op
> +
>      }
> 
>      @Override
> @@ -116,21 +208,17 @@ public abstract class ConfigInjectionBea
> 
>      @Override
>      public Set<Class<? extends Annotation>> getStereotypes() {
> -        return Collections.emptySet();
> +        return Collections.EMPTY_SET;
>      }
> 
>      @Override
>      public boolean isAlternative() {
> -        return alternative;
> +        return true;
>      }
> 
>      @Override
>      public String getId() {
> -        return id;
> -    }
> -
> -    InjectionPoint getSimpleInjectionPoint() {
> -        return simpleInjectionPoint;
> +        return "ConfigInjectionBean_" + rawType.getName();
>      }
> 
>      private static class ConfigPropertyLiteral extends AnnotationLiteral<ConfigProperty> implements ConfigProperty {
> @@ -145,41 +233,31 @@ public abstract class ConfigInjectionBea
>          }
>      }
> 
> -    private final InjectionPoint simpleInjectionPoint = new InjectionPoint() {
> -
> -        @Override
> -        public boolean isTransient() {
> -            return false;
> -        }
> -
> -        @Override
> -        public boolean isDelegate() {
> -            return false;
> -        }
> -
> -        @Override
> -        public Type getType() {
> -            return InjectionPoint.class;
> -        }
> -
> -        @Override
> -        public Set<Annotation> getQualifiers() {
> -            return Collections.singleton(new AnnotationLiteral<Default>() {});
> -        }
> -
> -        @Override
> -        public Member getMember() {
> -            return null;
> +    /**
> +     * A special Provider&lt;T&gt;
> +     * This concrete class is needed because we need the injected Provider for the ConfigProperty
> +     * to be Serializable. A Lambda would not work in this case
> +     */
> +    public static class ConfigValueProvider<T> implements Provider<T>, Serializable {
> +        private transient Config config;
> +        private final String key;
> +        private final Class<T> type;
> +
> +        ConfigValueProvider(Config config, String key, Class<T> type) {
> +            this.config = config;
> +            this.key = key;
> +            this.type = type;
>          }
> 
>          @Override
> -        public Bean<?> getBean() {
> -            return ConfigInjectionBean.this;
> +        public T get() {
> +            return (T) config.getValue(key, type);
> +        }
> +
> +        private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
> +            in.defaultReadObject();
> +            config = ConfigProviderResolver.instance().getConfig();
>          }
> 
> -        @Override
> -        public Annotated getAnnotated() {
> -            return null;
> -        }
> -    };
> +    }
>  }
> 
> Modified: geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
> URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java?rev=1804397&r1=1804396&r2=1804397&view=diff
> ==============================================================================
> --- geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java (original)
> +++ geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java Tue Aug  8 10:55:56 2017
> @@ -33,9 +33,12 @@ import org.testng.annotations.Test;
> 
>  public class ProviderTest extends Arquillian {
>      private static final String SOME_KEY = "org.apache.geronimo.config.test.internal.somekey";
> +    private static final String ANOTHER_KEY = "org.apache.geronimo.config.test.internal.anotherkey";
> 
>      @Deployment
>      public static WebArchive deploy() {
> +        System.setProperty(SOME_KEY, "someval");
> +        System.setProperty(ANOTHER_KEY, "someval");
>          JavaArchive testJar = ShrinkWrap
>                  .create(JavaArchive.class, "configProviderTest.jar")
>                  .addClasses(ProviderTest.class, SomeBean.class)
> @@ -70,8 +73,16 @@ public class ProviderTest extends Arquil
>          @ConfigProperty(name=SOME_KEY)
>          private Provider<String> myconfig;
> 
> +        @Inject
> +        @ConfigProperty(name=ANOTHER_KEY)
> +        private Provider<String> anotherconfig;
> +
>          public String getMyconfig() {
>              return myconfig.get();
>          }
> +
> +        public Provider<String> getAnotherconfig() {
> +            return anotherconfig;
> +        }
>      }
>  }
> 
> Modified: geronimo/components/config/trunk/pom.xml
> URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/pom.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
> ==============================================================================
> --- geronimo/components/config/trunk/pom.xml (original)
> +++ geronimo/components/config/trunk/pom.xml Tue Aug  8 10:55:56 2017
> @@ -27,7 +27,7 @@
>      </parent>
> 
>      <groupId>org.apache.geronimo.config</groupId>
> -    <artifactId>config-parent</artifactId>
> +    <artifactId>geronimo-config</artifactId>
>      <version>1.1-SNAPSHOT</version>
>      <packaging>pom</packaging>
>      <name>Geronimo Microprofile Configuration</name>
> @@ -50,7 +50,7 @@
>      <properties>
>          <maven.compiler.source>1.8</maven.compiler.source>
>          <maven.compiler.target>1.8</maven.compiler.target>
> -        <microprofile-config.version>1.1-SNAPSHOT</microprofile-config.version>
> +        <microprofile-config.version>1.0</microprofile-config.version>
>          <owb.version>1.7.3</owb.version>
>          <owb2.version>2.0.1-SNAPSHOT</owb2.version>
>          <arquillian.version>1.1.13.Final</arquillian.version>
> 
> 



Re: svn commit: r1804397 - in /geronimo/components/config/trunk: ./ impl/ impl/src/main/java/org/apache/geronimo/config/cdi/ impl/src/test/java/org/apache/geronimo/config/test/internal/

Posted by "John D. Ament" <jo...@apache.org>.
One note - hardcoding "isAlternative" to true breaks in Weld.  Unless there
is a base bean of same type, the alternative is ignored.  Hence why I only
did isAlternative on the provider type, all others are just regular beans.

John

On Tue, Aug 8, 2017 at 6:55 AM <st...@apache.org> wrote:

> Author: struberg
> Date: Tue Aug  8 10:55:56 2017
> New Revision: 1804397
>
> URL: http://svn.apache.org/viewvc?rev=1804397&view=rev
> Log:
> GERONIMO-6577 move back to a more dynamic version
>
> The goal of r1800748 to calculate all information upfront could not be
> achieved
> so we move back to the old version
>
> Modified:
>     geronimo/components/config/trunk/impl/debug-suite.xml
>     geronimo/components/config/trunk/impl/pom.xml
>
> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
>
> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
>
> geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
>     geronimo/components/config/trunk/pom.xml
>
> Modified: geronimo/components/config/trunk/impl/debug-suite.xml
> URL:
> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/debug-suite.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
>
> ==============================================================================
> --- geronimo/components/config/trunk/impl/debug-suite.xml (original)
> +++ geronimo/components/config/trunk/impl/debug-suite.xml Tue Aug  8
> 10:55:56 2017
> @@ -24,7 +24,7 @@
>      <classes>
>          <!-- Issues in the spec -->
>          <!-- CDI-437 -->
> -        <class
> name="org.eclipse.microprofile.config.tck.CdiOptionalInjectionTest">
> +        <class
> name="org.eclipse.microprofile.config.tck.CDIPlainInjectionTest">
>              <methods>
>                  <include name=".*"/>
>              </methods>
>
> Modified: geronimo/components/config/trunk/impl/pom.xml
> URL:
> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/pom.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
>
> ==============================================================================
> --- geronimo/components/config/trunk/impl/pom.xml (original)
> +++ geronimo/components/config/trunk/impl/pom.xml Tue Aug  8 10:55:56 2017
> @@ -27,7 +27,6 @@
>      </parent>
>
>      <artifactId>geronimo-config-impl</artifactId>
> -    <name>Geronimo Microprofile Configuration :: Implementation</name>
>
>      <dependencyManagement>
>          <dependencies>
>
> Modified:
> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
> URL:
> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java?rev=1804397&r1=1804396&r2=1804397&view=diff
>
> ==============================================================================
> ---
> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
> (original)
> +++
> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
> Tue Aug  8 10:55:56 2017
> @@ -16,54 +16,38 @@
>   */
>  package org.apache.geronimo.config.cdi;
>
> -import org.apache.geronimo.config.ConfigImpl;
> -import org.eclipse.microprofile.config.Config;
> -import org.eclipse.microprofile.config.inject.ConfigProperty;
> -import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
> +import java.lang.reflect.Type;
> +import java.util.ArrayList;
> +import java.util.HashMap;
> +import java.util.HashSet;
> +import java.util.List;
> +import java.util.Map;
> +import java.util.Optional;
> +import java.util.Set;
> +import java.util.stream.Collectors;
>
> -import javax.enterprise.context.spi.CreationalContext;
>  import javax.enterprise.event.Observes;
>  import javax.enterprise.inject.spi.AfterBeanDiscovery;
>  import javax.enterprise.inject.spi.AfterDeploymentValidation;
> -import javax.enterprise.inject.spi.AnnotatedMember;
> -import javax.enterprise.inject.spi.AnnotatedType;
>  import javax.enterprise.inject.spi.BeanManager;
> -import javax.enterprise.inject.spi.BeforeBeanDiscovery;
>  import javax.enterprise.inject.spi.BeforeShutdown;
> +import javax.enterprise.inject.spi.DeploymentException;
>  import javax.enterprise.inject.spi.Extension;
>  import javax.enterprise.inject.spi.InjectionPoint;
>  import javax.enterprise.inject.spi.ProcessInjectionPoint;
>  import javax.inject.Provider;
> -import java.lang.reflect.ParameterizedType;
> -import java.lang.reflect.Type;
> -import java.util.ArrayList;
> -import java.util.Arrays;
> -import java.util.Collection;
> -import java.util.HashMap;
> -import java.util.HashSet;
> -import java.util.List;
> -import java.util.Map;
> -import java.util.Objects;
> -import java.util.Optional;
> -import java.util.Set;
> -import java.util.function.BiFunction;
> -import java.util.stream.Stream;
>
> -import static java.util.function.Function.identity;
> -import static java.util.stream.Collectors.toMap;
> -import static org.eclipse.microprofile.config.ConfigProvider.getConfig;
> +import org.apache.geronimo.config.DefaultConfigProvider;
> +import org.eclipse.microprofile.config.Config;
> +import org.eclipse.microprofile.config.ConfigProvider;
> +import org.eclipse.microprofile.config.inject.ConfigProperty;
>
>  /**
>   * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
>   */
>  public class ConfigExtension implements Extension {
> -    private static final Object NULL = new Object();
> -
>      private Config config;
> -    private ConfigProviderResolver resolver;
>
> -    private Set<Injection> injections = new HashSet<>();
> -    private List<Throwable> deploymentProblems = new ArrayList<>();
>      private static final Map<Type, Type> REPLACED_TYPES = new HashMap<>();
>
>      static {
> @@ -74,336 +58,65 @@ public class ConfigExtension implements
>          REPLACED_TYPES.put(boolean.class, Boolean.class);
>      }
>
> -    void init(@Observes final BeforeBeanDiscovery beforeBeanDiscovery,
> final BeanManager bm) {
> -        resolver = ConfigProviderResolver.instance();
> -        config = getConfig();
> -    }
> +    private Set<InjectionPoint> injectionPoints = new HashSet<>();
> +
>
>      public void collectConfigProducer(@Observes ProcessInjectionPoint<?,
> ?> pip) {
> -        final InjectionPoint injectionPoint = pip.getInjectionPoint();
> -        final ConfigProperty configProperty =
> injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class);
> +        ConfigProperty configProperty =
> pip.getInjectionPoint().getAnnotated().getAnnotation(ConfigProperty.class);
>          if (configProperty != null) {
> -            Type replacedType =
> REPLACED_TYPES.getOrDefault(injectionPoint.getType(),
> injectionPoint.getType());
> -            Injection injection = new Injection(replacedType);
> -            final String key = getConfigKey(injectionPoint,
> configProperty);
> -            final boolean defaultUnset =
> isDefaultUnset(configProperty.defaultValue());
> -            if (!injections.add(injection)) {
> -                final Injection ref = injection;
> -                injection = injections.stream().filter(i ->
> i.equals(ref)).findFirst().get();
> -            }
> -            injection.keys.add(key);
> -            injection.defaultValues.add(configProperty.defaultValue());
> -
> -            final ConfigImpl configImpl = unwrapConfig();
> -
> -            // what about lazy runtime lookup, not consistent with tck
> and system prop usage, for now assume optional=optional ;)
> -            boolean hasValue = true;
> -            if (defaultUnset) { // value validation
> -                if (ParameterizedType.class.isInstance(injection.type)) {
> -                    final ParameterizedType pt =
> ParameterizedType.class.cast(injection.type);
> -                    if (pt.getRawType() != Optional.class &&
> !configImpl.getOptionalValue(key, String.class).isPresent()) {
> -                        hasValue = false;
> -                    }
> -                } else if (!configImpl.getOptionalValue(key,
> String.class).isPresent()) {
> -                    hasValue = false;
> -                }
> -                if (!hasValue) {
> -                    deploymentProblems.add(new
> IllegalArgumentException("No configured value for '" + key + "' from " +
> injectionPoint));
> -                }
> -            }
> -
> -            Class<?> instanceType = null;
> -            if (ParameterizedType.class.isInstance(injection.type)) { //
> converters validation
> -                final ParameterizedType pt =
> ParameterizedType.class.cast(injection.type);
> -                if (pt.getRawType() == Provider.class &&
> pt.getActualTypeArguments().length == 1 &&
> Class.class.isInstance(pt.getActualTypeArguments()[0])
> -                        &&
> !configImpl.getConverters().containsKey(Class.class.cast(pt.getActualTypeArguments()[0])))
> {
> -                    instanceType =
> Class.class.cast(pt.getActualTypeArguments()[0]);
> -                } // else if Optional it is fine, else we don't know how
> to process
> -            } else if (Class.class.isInstance(injection.type)) {
> -                instanceType = Class.class.cast(injection.type);
> -            }
> -            if (instanceType != null) { // validate we have a converter +
> we can convert the existing value
> -                if
> (!configImpl.getConverters().containsKey(instanceType)) {
> -                    deploymentProblems.add(new
> IllegalArgumentException("Missing converter for '" + key + "' from " +
> injectionPoint));
> -                } else if (hasValue) {
> -                    try {
> -
> configImpl.getConverters().get(injection.type).convert(configImpl.getValue(key));
> -                    } catch (final RuntimeException re) {
> -                        deploymentProblems.add(re);
> -                    }
> -                }
> -            }
> +            injectionPoints.add(pip.getInjectionPoint());
>          }
>      }
>
>      public void registerConfigProducer(@Observes AfterBeanDiscovery abd,
> BeanManager bm) {
> -        injections.stream()
> -                .flatMap(injection -> {
> -                    final BiFunction<CreationalContext<?>,
> ConfigInjectionBean<?>, String> keyProvider;
> -                    if (injection.keys.size() == 1) {
> -                        final String key =
> injection.keys.iterator().next();
> -                        keyProvider = (ctx, bean) -> key;
> -                    } else {
> -                        keyProvider = (ctx, bean) ->
> getName(findInjectionPoint(bm, ctx, bean));
> -                    }
> -
> -                    if
> (ParameterizedType.class.isInstance(injection.type)) {
> -                        final ParameterizedType paramType =
> ParameterizedType.class.cast(injection.type);
> -                        final Type rawType = paramType.getRawType();
> -
> -                        // todo: do we care of Instance injection? doesnt
> make much sense right?
> -                        if (Provider.class == rawType &&
> paramType.getActualTypeArguments().length == 1) {
> -                            if
> (!Class.class.isInstance(paramType.getActualTypeArguments()[0])) {
> -                                deploymentProblems.add(new
> IllegalArgumentException("@ConfigProperty can only be used with Provider<T>
> where T is a Class"));
> -                                return Stream.empty();
> -                            }
> -                            final Class<?> providerType =
> Class.class.cast(paramType.getActualTypeArguments()[0]);
> -                            return Stream.of(new
> ConfigInjectionBean<Provider<?>>(injection.type, true) {
> -                                @Override
> -                                public Provider<?> create(final
> CreationalContext<Provider<?>> context) {
> -                                    return () ->
> config.getValue(keyProvider.apply(context, this), providerType);
> -                                }
> -                            });
> -                        } else if (Optional.class == rawType &&
> paramType.getActualTypeArguments().length == 1) {
> -                            if
> (!Class.class.isInstance(paramType.getActualTypeArguments()[0])) {
> -                                deploymentProblems.add(new
> IllegalArgumentException("@ConfigProperty can only be used with Optional<T>
> where T is a Class"));
> -                                return null;
> -                            }
> -                            final Class<?> optionalType =
> Class.class.cast(paramType.getActualTypeArguments()[0]);
> -                            return Stream.of(new
> ConfigInjectionBean<Optional<?>>(injection.type) {
> -                                @Override
> -                                public Optional<?> create(final
> CreationalContext<Optional<?>> context) {
> -                                    return
> config.getOptionalValue(keyProvider.apply(context, this), optionalType);
> -                                }
> -                            });
> -                        } else {
> -                            deploymentProblems.add(new
> IllegalArgumentException("Unsupported parameterized type " + paramType));
> -                            return Stream.empty();
> -                        }
> -                    } else if (Class.class.isInstance(injection.type)) {
> -                        final Class clazz =
> Class.class.cast(injection.type);
> -                        final ConfigInjectionBean bean;
> -                        if (injection.defaultValues.isEmpty()) {
> -                            bean = new
> ConfigInjectionBean<Object>(injection.type) {
> -                                @Override
> -                                public Object create(final
> CreationalContext<Object> context) {
> -                                    return
> config.getOptionalValue(keyProvider.apply(context, this), clazz);
> -                                }
> -                            };
> -                        } else if (injection.defaultValues.size() == 1) {
> // common enough to be optimized
> -                            final String defVal =
> injection.defaultValues.iterator().next();
> -                            final Object alternativeVal =
> isDefaultUnset(defVal) ? null : unwrapConfig().convert(defVal, clazz);
> -                            bean = new
> ConfigInjectionBean<Object>(injection.type) {
> -                                @Override
> -                                public Object create(final
> CreationalContext<Object> context) {
> -                                    final Optional optionalValue =
> config.getOptionalValue(keyProvider.apply(context, this), clazz);
> -                                    return
> optionalValue.orElse(alternativeVal);
> -                                }
> -                            };
> -                        } else { // sadly we need to get back to the
> injection point to know which one we need to use
> -                            final Map<String, Object> prepared =
> injection.defaultValues.stream()
> -                                    .collect(toMap(identity(), k ->
> isDefaultUnset(k) ? NULL : unwrapConfig().convert(k, clazz), (a, b) -> b));
> -                            bean = new
> ConfigInjectionBean<Object>(injection.type) {
> -                                @Override
> -                                public Object create(final
> CreationalContext<Object> context) {
> -                                    final InjectionPoint ip =
> findInjectionPoint(bm, context, this);
> -                                    if (ip == null) {
> -                                        throw new
> IllegalStateException("Could not retrieve InjectionPoint");
> -                                    }
> -                                    return
> config.getOptionalValue(ConfigExtension.this.getName(ip), clazz)
> -                                            .orElseGet(() -> {
> -                                                final Object val =
> prepared.get(ip.getAnnotated().getAnnotation(ConfigProperty.class).defaultValue());
> -                                                return val == NULL ? null
> : val;
> -                                            });
> -                                }
> -                            };
> -                        }
> -
> -                        final Collection<ConfigInjectionBean<?>> beans =
> new ArrayList<>();
> -                        beans.add(bean);
> -
> -                        // is adding these beans is that useful? we
> captured them all so only a programmatic lookup would justify it
> -                        // and not sure it would be done this way anyway
> -                        final ParameterizedTypeImpl providerType = new
> ParameterizedTypeImpl(Provider.class, injection.type);
> -                        if (injections.stream().noneMatch(i ->
> i.type.equals(providerType))) {
> -                            beans.add(new
> ConfigInjectionBean<Provider<?>>(providerType, true) {
> -                                @Override
> -                                public Provider<?> create(final
> CreationalContext<Provider<?>> context) {
> -                                    return () -> bean.create(context);
> -                                }
> -                            });
> -                        }
> -
> -                        final ParameterizedTypeImpl optionalType = new
> ParameterizedTypeImpl(Optional.class, injection.type);
> -                        if (injections.stream().noneMatch(i ->
> i.type.equals(optionalType))) {
> -                            beans.add(new
> ConfigInjectionBean<Optional<?>>(optionalType) {
> -                                @Override
> -                                public Optional<?> create(final
> CreationalContext<Optional<?>> context) {
> -                                    return
> Optional.ofNullable(bean.create(context));
> -                                }
> -                            });
> -                        }
> -
> -                        return beans.stream();
> -                    } else {
> -                        deploymentProblems.add(new
> IllegalArgumentException("Unknown type " + injection.type));
> -                        return Stream.empty();
> -                    }
> -                })
> -                .forEach(abd::addBean);
> -    }
> +        Set<Class> types = injectionPoints.stream()
> +                .filter(ip -> ip.getType() instanceof Class)
> +                .map(ip -> (Class)
> REPLACED_TYPES.getOrDefault(ip.getType(), ip.getType()))
> +                .collect(Collectors.toSet());
> +
> +        // Provider and Optional are ParameterizedTypes and not a Class,
> so we need to add them manually
> +        types.add(Provider.class);
> +        types.add(Optional.class);
>
> -    public void validate(@Observes AfterDeploymentValidation add) {
> -        deploymentProblems.forEach(add::addDeploymentProblem);
> -        injections.clear();
> -        deploymentProblems.clear();
> +        types.forEach(type -> abd.addBean(new ConfigInjectionBean(bm,
> type)));
>      }
>
> -    public void shutdown(@Observes BeforeShutdown bsd) {
> -        resolver.releaseConfig(config);
> -    }
> +    public void validate(@Observes AfterDeploymentValidation add) {
> +        List<String> deploymentProblems = new ArrayList<>();
>
> -    private ConfigImpl unwrapConfig() {
> -        return ConfigImpl.class.cast(config);
> -    }
> +        config = ConfigProvider.getConfig();
>
> -    private static String getName(final InjectionPoint ip) {
> -        final ConfigProperty annotation =
> ip.getAnnotated().getAnnotation(ConfigProperty.class);
> -        final String name = annotation.name();
> -        return isDefaultUnset(name) ? getConfigKey(ip, annotation) : name;
> -    }
> +        for (InjectionPoint injectionPoint : injectionPoints) {
> +            Type type = injectionPoint.getType();
>
> -    /**
> -     * Get the property key to use.
> -     * In case the {@link ConfigProperty#name()} is empty we will try to
> determine the key name from the InjectionPoint.
> -     */
> -    private static String getConfigKey(InjectionPoint ip, ConfigProperty
> configProperty) {
> -        String key = configProperty.name();
> -        if (!key.isEmpty()) {
> -            return key;
> -        }
> -        if (ip.getAnnotated() instanceof AnnotatedMember) {
> -            AnnotatedMember member = (AnnotatedMember) ip.getAnnotated();
> -            AnnotatedType declaringType = member.getDeclaringType();
> -            if (declaringType != null) {
> -                String[] parts =
> declaringType.getJavaClass().getCanonicalName().split("\\.");
> -                String cn = parts[parts.length - 1];
> -                parts[parts.length - 1] =
> Character.toLowerCase(cn.charAt(0)) + (cn.length() > 1 ? cn.substring(1) :
> "");
> -                StringBuilder sb = new StringBuilder(parts[0]);
> -                for (int i = 1; i < parts.length; i++) {
> -                    sb.append(".").append(parts[i]);
> +            // replace native types with their Wrapper types
> +            type = REPLACED_TYPES.getOrDefault(type, type);
> +
> +            ConfigProperty configProperty =
> injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class);
> +            if (type instanceof Class) {
> +                // a direct injection of a ConfigProperty
> +                // that means a Converter must exist.
> +                String key =
> ConfigInjectionBean.getConfigKey(injectionPoint, configProperty);
> +                if ((isDefaultUnset(configProperty.defaultValue()))
> +                        && !config.getOptionalValue(key, (Class)
> type).isPresent()) {
> +                    deploymentProblems.add("No Config Value exists for "
> + key);
>                  }
> -
> -                // now add the field name
> -                sb.append(".").append(member.getJavaMember().getName());
> -                return sb.toString();
>              }
>          }
>
> -        throw new IllegalStateException("Could not find default name for
> @ConfigProperty InjectionPoint " + ip);
> -    }
> -
> -    private static boolean isDefaultUnset(String defaultValue) {
> -        return defaultValue == null || defaultValue.length() == 0 ||
> defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);
> -    }
> -
> -    private static InjectionPoint findInjectionPoint(final BeanManager
> bm, final CreationalContext<?> ctx,
> -                                                     ConfigInjectionBean
> bean) {
> -        return
> InjectionPoint.class.cast(bm.getInjectableReference(bean.getSimpleInjectionPoint(),
> ctx));
> -    }
> -
> -    private static final class Injection {
> -        private final Type type;
> -        private final Collection<String> keys = new ArrayList<>();
> -        private final Collection<String> defaultValues = new
> ArrayList<>();
> -
> -        private Injection(final Type type) {
> -            this.type = type;
> -        }
> -
> -        @Override
> -        public boolean equals(final Object o) {
> -            if (this == o) {
> -                return true;
> -            }
> -            if (o == null || Injection.class != o.getClass()) {
> -                return false;
> -            }
> -            final Injection injection = Injection.class.cast(o);
> -            return Objects.equals(type, injection.type);
> +        if (!deploymentProblems.isEmpty()) {
> +            add.addDeploymentProblem(new DeploymentException("Error while
> validating Configuration\n"
> +                                                             +
> String.join("\n", deploymentProblems)));
>          }
>
> -        @Override
> -        public int hashCode() {
> -            return type.hashCode();
> -        }
>      }
>
> -    private class ParameterizedTypeImpl implements ParameterizedType {
> -        private final Type rawType;
> -        private final Type[] types;
> -
> -        private ParameterizedTypeImpl(final Type raw, final Type...
> types) {
> -            this.rawType = raw;
> -            this.types = types;
> -        }
> -
> -        @Override
> -        public Type[] getActualTypeArguments() {
> -            return types.clone();
> -        }
> -
> -        @Override
> -        public Type getOwnerType() {
> -            return null;
> -        }
> -
> -        @Override
> -        public Type getRawType() {
> -            return rawType;
> -        }
> -
> -        @Override
> -        public int hashCode() {
> -            return Arrays.hashCode(types) ^ rawType.hashCode();
> -        }
> -
> -        @Override
> -        public boolean equals(final Object obj) {
> -            if (this == obj) {
> -                return true;
> -            }
> -            if (ParameterizedType.class.isInstance(obj)) {
> -                final ParameterizedType that =
> ParameterizedType.class.cast(obj);
> -                final Type thatRawType = that.getRawType();
> -                return (rawType == null ? thatRawType == null :
> rawType.equals(thatRawType))
> -                        && Arrays.equals(types,
> that.getActualTypeArguments());
> -            }
> -            return false;
> -        }
> +    public void shutdown(@Observes BeforeShutdown bsd) {
> +        DefaultConfigProvider.instance().releaseConfig(config);
> +    }
>
> -        @Override
> -        public String toString() {
> -            final StringBuilder buffer = new StringBuilder();
> -            buffer.append(Class.class.cast(rawType).getName());
> -            final Type[] actualTypes = getActualTypeArguments();
> -            if (actualTypes.length > 0) {
> -                buffer.append("<");
> -                final int length = actualTypes.length;
> -                for (int i = 0; i < length; i++) {
> -                    if (actualTypes[i] instanceof Class) {
> -                        buffer.append(((Class<?>)
> actualTypes[i]).getSimpleName());
> -                    } else {
> -                        buffer.append(actualTypes[i].toString());
> -                    }
> -                    if (i != actualTypes.length - 1) {
> -                        buffer.append(",");
> -                    }
> -                }
>
> -                buffer.append(">");
> -            }
> -            return buffer.toString();
> -        }
> +    static boolean isDefaultUnset(String defaultValue) {
> +        return defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);
>      }
>  }
>
> Modified:
> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
> URL:
> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java?rev=1804397&r1=1804396&r2=1804397&view=diff
>
> ==============================================================================
> ---
> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
> (original)
> +++
> geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
> Tue Aug  8 10:55:56 2017
> @@ -16,49 +16,59 @@
>   */
>  package org.apache.geronimo.config.cdi;
>
> -import org.eclipse.microprofile.config.inject.ConfigProperty;
> +import java.io.IOException;
> +import java.io.Serializable;
> +import java.lang.annotation.Annotation;
> +import java.lang.reflect.ParameterizedType;
> +import java.lang.reflect.Type;
> +import java.util.Collections;
> +import java.util.HashSet;
> +import java.util.Optional;
> +import java.util.Set;
>
>  import javax.enterprise.context.Dependent;
>  import javax.enterprise.context.spi.CreationalContext;
> -import javax.enterprise.inject.Default;
>  import javax.enterprise.inject.spi.Annotated;
> +import javax.enterprise.inject.spi.AnnotatedMember;
> +import javax.enterprise.inject.spi.AnnotatedType;
>  import javax.enterprise.inject.spi.Bean;
> +import javax.enterprise.inject.spi.BeanManager;
>  import javax.enterprise.inject.spi.InjectionPoint;
>  import javax.enterprise.inject.spi.PassivationCapable;
>  import javax.enterprise.util.AnnotationLiteral;
> -import java.lang.annotation.Annotation;
> -import java.lang.reflect.Member;
> -import java.lang.reflect.ParameterizedType;
> -import java.lang.reflect.Type;
> -import java.util.Collections;
> -import java.util.HashSet;
> -import java.util.Set;
> +import javax.inject.Provider;
> +
> +import org.apache.geronimo.config.ConfigImpl;
> +import org.eclipse.microprofile.config.Config;
> +import org.eclipse.microprofile.config.ConfigProvider;
> +import org.eclipse.microprofile.config.inject.ConfigProperty;
> +import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
>
>  /**
>   * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
>   */
> -public abstract class ConfigInjectionBean<T> implements Bean<T>,
> PassivationCapable {
> +public class ConfigInjectionBean<T> implements Bean<T>,
> PassivationCapable {
>
>      private final static Set<Annotation> QUALIFIERS = new HashSet<>();
>      static {
>          QUALIFIERS.add(new ConfigPropertyLiteral());
>      }
>
> +    private final BeanManager bm;
>      private final Class rawType;
>      private final Set<Type> types;
> -    private final String id;
> -    private final boolean alternative;
> -
> -    ConfigInjectionBean(Type type) {
> -        this(type,false);
> -    }
>
> -    ConfigInjectionBean(Type type, boolean alternative) {
> -        this.types = new HashSet<>();
> -        this.types.add(type);
> -        this.rawType = getRawType(type);
> -        this.id = "ConfigInjectionBean_" + type.toString();
> -        this.alternative = alternative;
> +    /**
> +     * only access via {@link #getConfig(}
> +     */
> +    private Config _config;
> +
> +    public ConfigInjectionBean(BeanManager bm, Type type) {
> +        this.bm = bm;
> +
> +        types = new HashSet<>();
> +        types.add(type);
> +        rawType = getRawType(type);
>      }
>
>      private Class getRawType(Type type) {
> @@ -76,7 +86,7 @@ public abstract class ConfigInjectionBea
>
>      @Override
>      public Set<InjectionPoint> getInjectionPoints() {
> -        return Collections.emptySet();
> +        return Collections.EMPTY_SET;
>      }
>
>      @Override
> @@ -90,8 +100,90 @@ public abstract class ConfigInjectionBea
>      }
>
>      @Override
> +    public T create(CreationalContext<T> context) {
> +        Set<Bean<?>> beans = bm.getBeans(InjectionPoint.class);
> +        Bean<?> bean = bm.resolve(beans);
> +        InjectionPoint ip = (InjectionPoint) bm.getReference(bean,
> InjectionPoint.class,  context);
> +        if (ip == null) {
> +            throw new IllegalStateException("Could not retrieve
> InjectionPoint");
> +        }
> +        Annotated annotated = ip.getAnnotated();
> +        ConfigProperty configProperty =
> annotated.getAnnotation(ConfigProperty.class);
> +        String key = getConfigKey(ip, configProperty);
> +        String defaultValue = configProperty.defaultValue();
> +
> +        if (annotated.getBaseType() instanceof ParameterizedType) {
> +            ParameterizedType paramType = (ParameterizedType)
> annotated.getBaseType();
> +            Type rawType = paramType.getRawType();
> +
> +            // handle Provider<T>
> +            if (rawType instanceof Class && ((Class)
> rawType).isAssignableFrom(Provider.class) &&
> paramType.getActualTypeArguments().length == 1) {
> +                Class clazz = (Class)
> paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
> +                return (T) new ConfigValueProvider(getConfig(), key,
> clazz);
> +            }
> +
> +            // handle Optional<T>
> +            if (rawType instanceof Class && ((Class)
> rawType).isAssignableFrom(Optional.class) &&
> paramType.getActualTypeArguments().length == 1) {
> +                Class clazz = (Class)
> paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
> +                return (T) getConfig().getOptionalValue(key, clazz);
> +            }
> +        }
> +        else {
> +            Class clazz = (Class) annotated.getBaseType();
> +            if (ConfigExtension.isDefaultUnset(defaultValue)) {
> +                return (T) getConfig().getValue(key, clazz);
> +            }
> +            else {
> +                Config config = getConfig();
> +                return (T) config.getOptionalValue(key, clazz)
> +                        .orElse(((ConfigImpl)
> config).convert(defaultValue, clazz));
> +            }
> +        }
> +
> +        throw new IllegalStateException("unhandled ConfigProperty");
> +    }
> +
> +
> +    /**
> +     * Get the property key to use.
> +     * In case the {@link ConfigProperty#name()} is empty we will try to
> determine the key name from the InjectionPoint.
> +     */
> +    public static String getConfigKey(InjectionPoint ip, ConfigProperty
> configProperty) {
> +        String key = configProperty.name();
> +        if (key.length() > 0) {
> +            return key;
> +        }
> +        if (ip.getAnnotated() instanceof AnnotatedMember) {
> +            AnnotatedMember member = (AnnotatedMember) ip.getAnnotated();
> +            AnnotatedType declaringType = member.getDeclaringType();
> +            if (declaringType != null) {
> +                String[] parts =
> declaringType.getJavaClass().getCanonicalName().split("\\.");
> +                String cn = parts[parts.length-1];
> +                parts[parts.length-1] =
> Character.toLowerCase(cn.charAt(0)) + (cn.length() > 1 ? cn.substring(1) :
> "");
> +                StringBuilder sb = new StringBuilder(parts[0]);
> +                for (int i = 1; i < parts.length; i++) {
> +                    sb.append(".").append(parts[i]);
> +                }
> +
> +                // now add the field name
> +                sb.append(".").append(member.getJavaMember().getName());
> +                return sb.toString();
> +            }
> +        }
> +
> +        throw new IllegalStateException("Could not find default name for
> @ConfigProperty InjectionPoint " + ip);
> +    }
> +
> +    public Config getConfig() {
> +        if (_config == null) {
> +            _config = ConfigProvider.getConfig();
> +        }
> +        return _config;
> +    }
> +
> +    @Override
>      public void destroy(T instance, CreationalContext<T> context) {
> -        // no-op
> +
>      }
>
>      @Override
> @@ -116,21 +208,17 @@ public abstract class ConfigInjectionBea
>
>      @Override
>      public Set<Class<? extends Annotation>> getStereotypes() {
> -        return Collections.emptySet();
> +        return Collections.EMPTY_SET;
>      }
>
>      @Override
>      public boolean isAlternative() {
> -        return alternative;
> +        return true;
>      }
>
>      @Override
>      public String getId() {
> -        return id;
> -    }
> -
> -    InjectionPoint getSimpleInjectionPoint() {
> -        return simpleInjectionPoint;
> +        return "ConfigInjectionBean_" + rawType.getName();
>      }
>
>      private static class ConfigPropertyLiteral extends
> AnnotationLiteral<ConfigProperty> implements ConfigProperty {
> @@ -145,41 +233,31 @@ public abstract class ConfigInjectionBea
>          }
>      }
>
> -    private final InjectionPoint simpleInjectionPoint = new
> InjectionPoint() {
> -
> -        @Override
> -        public boolean isTransient() {
> -            return false;
> -        }
> -
> -        @Override
> -        public boolean isDelegate() {
> -            return false;
> -        }
> -
> -        @Override
> -        public Type getType() {
> -            return InjectionPoint.class;
> -        }
> -
> -        @Override
> -        public Set<Annotation> getQualifiers() {
> -            return Collections.singleton(new AnnotationLiteral<Default>()
> {});
> -        }
> -
> -        @Override
> -        public Member getMember() {
> -            return null;
> +    /**
> +     * A special Provider&lt;T&gt;
> +     * This concrete class is needed because we need the injected
> Provider for the ConfigProperty
> +     * to be Serializable. A Lambda would not work in this case
> +     */
> +    public static class ConfigValueProvider<T> implements Provider<T>,
> Serializable {
> +        private transient Config config;
> +        private final String key;
> +        private final Class<T> type;
> +
> +        ConfigValueProvider(Config config, String key, Class<T> type) {
> +            this.config = config;
> +            this.key = key;
> +            this.type = type;
>          }
>
>          @Override
> -        public Bean<?> getBean() {
> -            return ConfigInjectionBean.this;
> +        public T get() {
> +            return (T) config.getValue(key, type);
> +        }
> +
> +        private void readObject(java.io.ObjectInputStream in) throws
> IOException, ClassNotFoundException {
> +            in.defaultReadObject();
> +            config = ConfigProviderResolver.instance().getConfig();
>          }
>
> -        @Override
> -        public Annotated getAnnotated() {
> -            return null;
> -        }
> -    };
> +    }
>  }
>
> Modified:
> geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
> URL:
> http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java?rev=1804397&r1=1804396&r2=1804397&view=diff
>
> ==============================================================================
> ---
> geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
> (original)
> +++
> geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
> Tue Aug  8 10:55:56 2017
> @@ -33,9 +33,12 @@ import org.testng.annotations.Test;
>
>  public class ProviderTest extends Arquillian {
>      private static final String SOME_KEY =
> "org.apache.geronimo.config.test.internal.somekey";
> +    private static final String ANOTHER_KEY =
> "org.apache.geronimo.config.test.internal.anotherkey";
>
>      @Deployment
>      public static WebArchive deploy() {
> +        System.setProperty(SOME_KEY, "someval");
> +        System.setProperty(ANOTHER_KEY, "someval");
>          JavaArchive testJar = ShrinkWrap
>                  .create(JavaArchive.class, "configProviderTest.jar")
>                  .addClasses(ProviderTest.class, SomeBean.class)
> @@ -70,8 +73,16 @@ public class ProviderTest extends Arquil
>          @ConfigProperty(name=SOME_KEY)
>          private Provider<String> myconfig;
>
> +        @Inject
> +        @ConfigProperty(name=ANOTHER_KEY)
> +        private Provider<String> anotherconfig;
> +
>          public String getMyconfig() {
>              return myconfig.get();
>          }
> +
> +        public Provider<String> getAnotherconfig() {
> +            return anotherconfig;
> +        }
>      }
>  }
>
> Modified: geronimo/components/config/trunk/pom.xml
> URL:
> http://svn.apache.org/viewvc/geronimo/components/config/trunk/pom.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
>
> ==============================================================================
> --- geronimo/components/config/trunk/pom.xml (original)
> +++ geronimo/components/config/trunk/pom.xml Tue Aug  8 10:55:56 2017
> @@ -27,7 +27,7 @@
>      </parent>
>
>      <groupId>org.apache.geronimo.config</groupId>
> -    <artifactId>config-parent</artifactId>
> +    <artifactId>geronimo-config</artifactId>
>      <version>1.1-SNAPSHOT</version>
>      <packaging>pom</packaging>
>      <name>Geronimo Microprofile Configuration</name>
> @@ -50,7 +50,7 @@
>      <properties>
>          <maven.compiler.source>1.8</maven.compiler.source>
>          <maven.compiler.target>1.8</maven.compiler.target>
> -
> <microprofile-config.version>1.1-SNAPSHOT</microprofile-config.version>
> +        <microprofile-config.version>1.0</microprofile-config.version>
>          <owb.version>1.7.3</owb.version>
>          <owb2.version>2.0.1-SNAPSHOT</owb2.version>
>          <arquillian.version>1.1.13.Final</arquillian.version>
>
>
>