This is an automated email from the ASF dual-hosted git repository.

struberg pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/deltaspike.git

commit 941e3717c18196dc7bcee1de8dcaac86e6f874c4
Author: Mark Struberg <[email protected]>
AuthorDate: Wed Dec 8 22:29:29 2021 +0100

    DELTASPIKE-1445 implement Supplier<T> support
---
 .../deltaspike/core/api/config/ConfigProperty.java |  17 +
 .../spi/config/BaseConfigPropertyProducer.java     |  43 +-
 .../impl/config/DefaultConfigPropertyProducer.java |  40 ++
 .../core/impl/config/DeltaSpikeConfigInfo.java     | 504 ++++++++++-----------
 .../impl/config/DeltaSpikeConfigInfoMBean.java     |  66 +--
 .../config/converter/BeanConverterFactory.java     |   6 +-
 .../core/api/config/BeanConfigResolverTest.java    |  37 +-
 .../config/beans/ServerEndpointPojoWithCt.java}    |  70 +--
 .../config/beans/ServerEndpointPojoWithFields.java |  62 +++
 .../injectable/InjectableConfigPropertyTest.java   |  38 +-
 .../core/api/config/injectable/SettingsBean.java   |  19 +
 11 files changed, 539 insertions(+), 363 deletions(-)

diff --git 
a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigProperty.java
 
b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigProperty.java
index a856ad7..586a21a 100644
--- 
a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigProperty.java
+++ 
b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigProperty.java
@@ -23,6 +23,7 @@ import javax.inject.Qualifier;
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
+import java.util.concurrent.TimeUnit;
 
 import static java.lang.annotation.ElementType.CONSTRUCTOR;
 import static java.lang.annotation.ElementType.FIELD;
@@ -30,6 +31,7 @@ import static java.lang.annotation.ElementType.METHOD;
 import static java.lang.annotation.ElementType.PARAMETER;
 import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.util.concurrent.TimeUnit.SECONDS;
 
 /**
  * This Qualifier allows simple injection of configuration properties through 
the DeltaSpike configuration 
@@ -151,4 +153,19 @@ public @interface ConfigProperty
      */
     @Nonbinding
     Class<? extends ConfigResolver.Converter> converter() default 
ConfigResolver.Converter.class;
+
+    /**
+     * This only applies when used with injecting a {@link 
java.util.function.Supplier} for the requested configuration.
+     * @return the duration while the value is not reloaded.
+     */
+    @Nonbinding
+    long cacheFor() default -1;
+
+    /**
+     * This only applies when used with injecting a {@link 
java.util.function.Supplier} for the requested configuration.
+     * @return the duration unit for {@see cacheFor()}.
+     */
+    @Nonbinding
+    TimeUnit cacheUnit() default SECONDS;
+
 }
diff --git 
a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/config/BaseConfigPropertyProducer.java
 
b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/config/BaseConfigPropertyProducer.java
index 48517dc..f120736 100644
--- 
a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/config/BaseConfigPropertyProducer.java
+++ 
b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/config/BaseConfigPropertyProducer.java
@@ -23,6 +23,7 @@ import javax.enterprise.inject.spi.InjectionPoint;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 
+import org.apache.deltaspike.core.api.config.Config;
 import org.apache.deltaspike.core.api.config.ConfigResolver;
 import org.apache.deltaspike.core.api.config.ConfigProperty;
 import org.apache.deltaspike.core.api.provider.BeanProvider;
@@ -176,12 +177,26 @@ public abstract class BaseConfigPropertyProducer
                                                           final String 
parameterizedBy,
                                                           final boolean 
projectStageAware, final boolean evaluate)
     {
-        final ConfigResolver.UntypedResolver<String> untypedResolver = 
ConfigResolver.resolve(key);
-        final ConfigResolver.TypedResolver<T> resolver =
-                (ConfigResolver.Converter.class == converterType ?
-                        untypedResolver.as(Class.class.cast(ipCls)) :
-                        untypedResolver.as(ipCls, 
BeanProvider.getContextualReference(converterType)))
-                        .withCurrentProjectStage(projectStageAware);
+        final Config config = ConfigResolver.getConfig();
+        final ConfigResolver.UntypedResolver<String> untypedResolver = 
config.resolve(key);
+
+        final ConfigResolver.TypedResolver<T> resolver;
+
+        if (ConfigResolver.Converter.class != converterType)
+        {
+            resolver = untypedResolver.as(ipCls, 
BeanProvider.getContextualReference(converterType));
+        }
+        else if (converterExists(config, ipCls))
+        {
+            resolver = untypedResolver.as(Class.class.cast(ipCls));
+        }
+        else
+        {
+            resolver = untypedResolver.asBean(Class.class.cast(ipCls));
+        }
+
+        resolver.withCurrentProjectStage(projectStageAware);
+
         if (!ConfigProperty.NULL.equals(stringDefault))
         {
             resolver.withStringDefault(stringDefault);
@@ -192,4 +207,20 @@ public abstract class BaseConfigPropertyProducer
         }
         return resolver.evaluateVariables(evaluate);
     }
+
+    /**
+     * TODO we should make Converters for single attributes configurable.
+     * Until then the list is fixed.
+     * See TypedResolverImpl#convert
+     */
+    private boolean converterExists(Config config, Type ipCls)
+    {
+        return (String.class == ipCls ||
+                Integer.class == ipCls ||
+                Boolean.class == ipCls ||
+                Long.class == ipCls ||
+                Float.class == ipCls ||
+                Double.class == ipCls
+                );
+    }
 }
diff --git 
a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/DefaultConfigPropertyProducer.java
 
b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/DefaultConfigPropertyProducer.java
index 7e7efeb..0a00ece 100644
--- 
a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/DefaultConfigPropertyProducer.java
+++ 
b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/DefaultConfigPropertyProducer.java
@@ -23,10 +23,13 @@ import javax.enterprise.context.Dependent;
 import javax.enterprise.inject.Produces;
 import javax.enterprise.inject.spi.InjectionPoint;
 
+import org.apache.deltaspike.core.api.config.ConfigResolver;
 import org.apache.deltaspike.core.spi.config.BaseConfigPropertyProducer;
 import org.apache.deltaspike.core.api.config.ConfigProperty;
 
+import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
+import java.util.function.Supplier;
 
 /**
  * This class contains producer methods for injecting
@@ -92,7 +95,44 @@ public class DefaultConfigPropertyProducer extends 
BaseConfigPropertyProducer
     public Double produceDoubleConfiguration(InjectionPoint injectionPoint)
     {
         return getPropertyWithException(injectionPoint, Double.class);
+    }
+
+    @Produces
+    @Dependent
+    @ConfigProperty(name = "ignore")
+    public <C> Supplier<C> produceConfigSupplier(InjectionPoint injectionPoint)
+    {
+        ConfigProperty configProperty = getAnnotation(injectionPoint, 
ConfigProperty.class);
+
+        if (configProperty == null)
+        {
+            throw new IllegalStateException("producer method called without 
@ConfigProperty being present!");
+        }
+        final Type injectionPointType = injectionPoint.getType();
+        Type ipClass = null;
+        if (injectionPointType instanceof ParameterizedType && 
((ParameterizedType) injectionPointType).getActualTypeArguments().length == 1)
+        {
+            ipClass = ((ParameterizedType) 
injectionPointType).getActualTypeArguments()[0];
+        }
+        else
+        {
+            throw new IllegalStateException("Supplier for Configuration must 
be a Parameterized Type");
+        }
+
+        ConfigResolver.TypedResolver<C> resolver = 
asResolver(configProperty.name(),
+            configProperty.defaultValue(),
+            ipClass,
+            configProperty.converter(),
+            configProperty.parameterizedBy(),
+            configProperty.projectStageAware(),
+            configProperty.evaluateVariables());
+
+        if (configProperty.cacheFor() > 0)
+        {
+            resolver.cacheFor(configProperty.cacheUnit(), 
configProperty.cacheFor());
+        }
 
+        return () -> resolver.getValue();
     }
 
     private <T> T getPropertyWithException(InjectionPoint ip, Type ipCls)
diff --git 
a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/DeltaSpikeConfigInfo.java
 
b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/DeltaSpikeConfigInfo.java
index 6efb1e7..6aa7b9e 100644
--- 
a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/DeltaSpikeConfigInfo.java
+++ 
b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/DeltaSpikeConfigInfo.java
@@ -1,252 +1,252 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.deltaspike.core.impl.config;
-
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import javax.management.openmbean.TabularType;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.deltaspike.core.api.config.ConfigResolver;
-import org.apache.deltaspike.core.spi.config.ConfigSource;
-
-/**
- * JMX MBean for DeltaSpike
- */
-public class DeltaSpikeConfigInfo implements DeltaSpikeConfigInfoMBean
-{
-    private final ClassLoader appConfigClassLoader;
-
-    public DeltaSpikeConfigInfo(ClassLoader appConfigClassLoader)
-    {
-        this.appConfigClassLoader = appConfigClassLoader;
-    }
-
-    @Override
-    public String[] getConfigSourcesAsString()
-    {
-        ClassLoader originalCl = 
Thread.currentThread().getContextClassLoader();
-        try
-        {
-            Thread.currentThread().setContextClassLoader(appConfigClassLoader);
-
-            ConfigSource[] configSources = ConfigResolver.getConfigSources();
-            List<String> configSourceInfo = new ArrayList<String>();
-            for (ConfigSource configSource : configSources)
-            {
-                
configSourceInfo.add(Integer.toString(configSource.getOrdinal())
-                    + " - " + configSource.getConfigName());
-            }
-
-            return configSourceInfo.toArray(new 
String[configSourceInfo.size()]);
-        }
-        finally
-        {
-            // set back the original TCCL
-            Thread.currentThread().setContextClassLoader(originalCl);
-        }
-
-    }
-
-    @Override
-    public String[] getConfigEntriesAsString()
-    {
-        ClassLoader originalCl = 
Thread.currentThread().getContextClassLoader();
-        try
-        {
-            Thread.currentThread().setContextClassLoader(appConfigClassLoader);
-
-            List<ConfigEntry> configEntries = calculateConfigEntries();
-
-            String[] configArray = new String[configEntries.size()];
-
-            for (int i = 0 ; i < configEntries.size(); i++)
-            {
-                ConfigEntry configEntry = configEntries.get(i);
-                configArray[i] = configEntry.getKey() + " = " + 
configEntry.getValue()
-                    + " - picked up from: " + 
configEntry.getFromConfigSource();
-            }
-
-            return configArray;
-
-        }
-        finally
-        {
-            // set back the original TCCL
-            Thread.currentThread().setContextClassLoader(originalCl);
-        }
-    }
-
-    @Override
-    public TabularData getConfigEntries()
-    {
-        ClassLoader originalCl = 
Thread.currentThread().getContextClassLoader();
-        try
-        {
-            Thread.currentThread().setContextClassLoader(appConfigClassLoader);
-
-            List<ConfigEntry> configEntries = calculateConfigEntries();
-
-            String[] configArray = new String[configEntries.size()];
-
-            for (int i = 0 ; i < configEntries.size(); i++)
-            {
-                ConfigEntry configEntry = configEntries.get(i);
-                configArray[i] = configEntry.getKey() + " = " + 
configEntry.getValue()
-                    + " - picked up from: " + 
configEntry.getFromConfigSource();
-            }
-
-            String typeName = "ConfigEntries";
-            OpenType<?>[] types = new OpenType<?>[]{SimpleType.STRING, 
SimpleType.STRING, SimpleType.STRING};
-            String[] keys = new String[]{"Key", "Value", "fromConfigSource"};
-
-            CompositeType ct = new CompositeType(typeName, typeName, keys, 
keys, types);
-            TabularType type = new TabularType(typeName, typeName, ct, keys);
-            TabularDataSupport configEntryInfo = new TabularDataSupport(type);
-
-            ConfigSource[] configSources = ConfigResolver.getConfigSources();
-            for (ConfigEntry configEntry : configEntries)
-            {
-                configEntryInfo.put(
-                    new CompositeDataSupport(ct, keys,
-                        new Object[]{configEntry.getKey(), 
configEntry.getValue(), configEntry.getFromConfigSource()}));
-            }
-
-            return configEntryInfo;
-        }
-        catch (OpenDataException e)
-        {
-            throw new RuntimeException(e);
-        }
-        finally
-        {
-            // set back the original TCCL
-            Thread.currentThread().setContextClassLoader(originalCl);
-        }
-    }
-
-    @Override
-    public TabularData getConfigSources()
-    {
-        ClassLoader originalCl = 
Thread.currentThread().getContextClassLoader();
-        try
-        {
-            Thread.currentThread().setContextClassLoader(appConfigClassLoader);
-
-            String typeName = "ConfigSources";
-            OpenType<?>[] types = new OpenType<?>[]{SimpleType.INTEGER, 
SimpleType.STRING};
-            String[] keys = new String[]{"Ordinal", "ConfigSource"};
-
-            CompositeType ct = new CompositeType(typeName, typeName, keys, 
keys, types);
-            TabularType type = new TabularType(typeName, typeName, ct, keys);
-            TabularDataSupport configSourceInfo = new TabularDataSupport(type);
-
-            ConfigSource[] configSources = ConfigResolver.getConfigSources();
-            for (ConfigSource configSource : configSources)
-            {
-                configSourceInfo.put(
-                    new CompositeDataSupport(ct, keys,
-                            new Object[]{configSource.getOrdinal(), 
configSource.getConfigName()}));
-            }
-
-            return configSourceInfo;
-        }
-        catch (OpenDataException e)
-        {
-            throw new RuntimeException(e);
-        }
-        finally
-        {
-            // set back the original TCCL
-            Thread.currentThread().setContextClassLoader(originalCl);
-        }
-    }
-
-    private List<ConfigEntry> calculateConfigEntries()
-    {
-        Map<String, String> allProperties = ConfigResolver.getAllProperties();
-        List<ConfigEntry> configEntries = new 
ArrayList<ConfigEntry>(allProperties.size());
-        ConfigSource[] configSources = ConfigResolver.getConfigSources();
-
-        for (Map.Entry<String, String> configEntry : allProperties.entrySet())
-        {
-            String key = configEntry.getKey();
-            String value = ConfigResolver.filterConfigValueForLog(key,
-                                    
ConfigResolver.getProjectStageAwarePropertyValue(key));
-
-            String fromConfigSource = getFromConfigSource(configSources, key);
-            configEntries.add(new ConfigEntry(key, value, fromConfigSource));
-        }
-
-        return configEntries;
-    }
-
-    private String getFromConfigSource(ConfigSource[] configSources, String 
key)
-    {
-        for (ConfigSource configSource : configSources)
-        {
-            if (configSource.getPropertyValue(key) != null)
-            {
-                return configSource.getConfigName();
-            }
-        }
-
-        return null;
-    }
-
-
-
-    private class ConfigEntry
-    {
-        private final String key;
-        private final String value;
-        private final String fromConfigSource;
-
-        ConfigEntry(String key, String value, String fromConfigSource)
-        {
-            this.key = key;
-            this.value = value;
-            this.fromConfigSource = fromConfigSource;
-        }
-
-        String getKey()
-        {
-            return key;
-        }
-
-        String getValue()
-        {
-            return value;
-        }
-
-        String getFromConfigSource()
-        {
-            return fromConfigSource;
-        }
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.core.impl.config;
+
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.deltaspike.core.api.config.ConfigResolver;
+import org.apache.deltaspike.core.spi.config.ConfigSource;
+
+/**
+ * JMX MBean for DeltaSpike
+ */
+public class DeltaSpikeConfigInfo implements DeltaSpikeConfigInfoMBean
+{
+    private final ClassLoader appConfigClassLoader;
+
+    public DeltaSpikeConfigInfo(ClassLoader appConfigClassLoader)
+    {
+        this.appConfigClassLoader = appConfigClassLoader;
+    }
+
+    @Override
+    public String[] getConfigSourcesAsString()
+    {
+        ClassLoader originalCl = 
Thread.currentThread().getContextClassLoader();
+        try
+        {
+            Thread.currentThread().setContextClassLoader(appConfigClassLoader);
+
+            ConfigSource[] configSources = ConfigResolver.getConfigSources();
+            List<String> configSourceInfo = new ArrayList<String>();
+            for (ConfigSource configSource : configSources)
+            {
+                
configSourceInfo.add(Integer.toString(configSource.getOrdinal())
+                    + " - " + configSource.getConfigName());
+            }
+
+            return configSourceInfo.toArray(new 
String[configSourceInfo.size()]);
+        }
+        finally
+        {
+            // set back the original TCCL
+            Thread.currentThread().setContextClassLoader(originalCl);
+        }
+
+    }
+
+    @Override
+    public String[] getConfigEntriesAsString()
+    {
+        ClassLoader originalCl = 
Thread.currentThread().getContextClassLoader();
+        try
+        {
+            Thread.currentThread().setContextClassLoader(appConfigClassLoader);
+
+            List<ConfigEntry> configEntries = calculateConfigEntries();
+
+            String[] configArray = new String[configEntries.size()];
+
+            for (int i = 0 ; i < configEntries.size(); i++)
+            {
+                ConfigEntry configEntry = configEntries.get(i);
+                configArray[i] = configEntry.getKey() + " = " + 
configEntry.getValue()
+                    + " - picked up from: " + 
configEntry.getFromConfigSource();
+            }
+
+            return configArray;
+
+        }
+        finally
+        {
+            // set back the original TCCL
+            Thread.currentThread().setContextClassLoader(originalCl);
+        }
+    }
+
+    @Override
+    public TabularData getConfigEntries()
+    {
+        ClassLoader originalCl = 
Thread.currentThread().getContextClassLoader();
+        try
+        {
+            Thread.currentThread().setContextClassLoader(appConfigClassLoader);
+
+            List<ConfigEntry> configEntries = calculateConfigEntries();
+
+            String[] configArray = new String[configEntries.size()];
+
+            for (int i = 0 ; i < configEntries.size(); i++)
+            {
+                ConfigEntry configEntry = configEntries.get(i);
+                configArray[i] = configEntry.getKey() + " = " + 
configEntry.getValue()
+                    + " - picked up from: " + 
configEntry.getFromConfigSource();
+            }
+
+            String typeName = "ConfigEntries";
+            OpenType<?>[] types = new OpenType<?>[]{SimpleType.STRING, 
SimpleType.STRING, SimpleType.STRING};
+            String[] keys = new String[]{"Key", "Value", "fromConfigSource"};
+
+            CompositeType ct = new CompositeType(typeName, typeName, keys, 
keys, types);
+            TabularType type = new TabularType(typeName, typeName, ct, keys);
+            TabularDataSupport configEntryInfo = new TabularDataSupport(type);
+
+            ConfigSource[] configSources = ConfigResolver.getConfigSources();
+            for (ConfigEntry configEntry : configEntries)
+            {
+                configEntryInfo.put(
+                    new CompositeDataSupport(ct, keys,
+                        new Object[]{configEntry.getKey(), 
configEntry.getValue(), configEntry.getFromConfigSource()}));
+            }
+
+            return configEntryInfo;
+        }
+        catch (OpenDataException e)
+        {
+            throw new RuntimeException(e);
+        }
+        finally
+        {
+            // set back the original TCCL
+            Thread.currentThread().setContextClassLoader(originalCl);
+        }
+    }
+
+    @Override
+    public TabularData getConfigSources()
+    {
+        ClassLoader originalCl = 
Thread.currentThread().getContextClassLoader();
+        try
+        {
+            Thread.currentThread().setContextClassLoader(appConfigClassLoader);
+
+            String typeName = "ConfigSources";
+            OpenType<?>[] types = new OpenType<?>[]{SimpleType.INTEGER, 
SimpleType.STRING};
+            String[] keys = new String[]{"Ordinal", "ConfigSource"};
+
+            CompositeType ct = new CompositeType(typeName, typeName, keys, 
keys, types);
+            TabularType type = new TabularType(typeName, typeName, ct, keys);
+            TabularDataSupport configSourceInfo = new TabularDataSupport(type);
+
+            ConfigSource[] configSources = ConfigResolver.getConfigSources();
+            for (ConfigSource configSource : configSources)
+            {
+                configSourceInfo.put(
+                    new CompositeDataSupport(ct, keys,
+                            new Object[]{configSource.getOrdinal(), 
configSource.getConfigName()}));
+            }
+
+            return configSourceInfo;
+        }
+        catch (OpenDataException e)
+        {
+            throw new RuntimeException(e);
+        }
+        finally
+        {
+            // set back the original TCCL
+            Thread.currentThread().setContextClassLoader(originalCl);
+        }
+    }
+
+    private List<ConfigEntry> calculateConfigEntries()
+    {
+        Map<String, String> allProperties = ConfigResolver.getAllProperties();
+        List<ConfigEntry> configEntries = new 
ArrayList<ConfigEntry>(allProperties.size());
+        ConfigSource[] configSources = ConfigResolver.getConfigSources();
+
+        for (Map.Entry<String, String> configEntry : allProperties.entrySet())
+        {
+            String key = configEntry.getKey();
+            String value = ConfigResolver.filterConfigValueForLog(key,
+                                    
ConfigResolver.getProjectStageAwarePropertyValue(key));
+
+            String fromConfigSource = getFromConfigSource(configSources, key);
+            configEntries.add(new ConfigEntry(key, value, fromConfigSource));
+        }
+
+        return configEntries;
+    }
+
+    private String getFromConfigSource(ConfigSource[] configSources, String 
key)
+    {
+        for (ConfigSource configSource : configSources)
+        {
+            if (configSource.getPropertyValue(key) != null)
+            {
+                return configSource.getConfigName();
+            }
+        }
+
+        return null;
+    }
+
+
+
+    private class ConfigEntry
+    {
+        private final String key;
+        private final String value;
+        private final String fromConfigSource;
+
+        ConfigEntry(String key, String value, String fromConfigSource)
+        {
+            this.key = key;
+            this.value = value;
+            this.fromConfigSource = fromConfigSource;
+        }
+
+        String getKey()
+        {
+            return key;
+        }
+
+        String getValue()
+        {
+            return value;
+        }
+
+        String getFromConfigSource()
+        {
+            return fromConfigSource;
+        }
+    }
+
+}
diff --git 
a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/DeltaSpikeConfigInfoMBean.java
 
b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/DeltaSpikeConfigInfoMBean.java
index d2d154f..277d66e 100644
--- 
a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/DeltaSpikeConfigInfoMBean.java
+++ 
b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/DeltaSpikeConfigInfoMBean.java
@@ -1,33 +1,33 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.deltaspike.core.impl.config;
-
-import javax.management.openmbean.TabularData;
-
-public interface DeltaSpikeConfigInfoMBean
-{
-    String[] getConfigSourcesAsString();
-
-    TabularData getConfigSources();
-
-    String[] getConfigEntriesAsString();
-
-    TabularData getConfigEntries();
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.core.impl.config;
+
+import javax.management.openmbean.TabularData;
+
+public interface DeltaSpikeConfigInfoMBean
+{
+    String[] getConfigSourcesAsString();
+
+    TabularData getConfigSources();
+
+    String[] getConfigEntriesAsString();
+
+    TabularData getConfigEntries();
+
+}
diff --git 
a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/converter/BeanConverterFactory.java
 
b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/converter/BeanConverterFactory.java
index de501f0..9aa3e3d 100644
--- 
a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/converter/BeanConverterFactory.java
+++ 
b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/converter/BeanConverterFactory.java
@@ -33,7 +33,7 @@ import org.apache.deltaspike.core.api.config.Config;
  */
 public final class BeanConverterFactory
 {
-    private final ConcurrentMap<Class<?>, BiFunction<Config, String, ?>> 
BEAN_CONVERTER = new ConcurrentHashMap<>();
+    private final ConcurrentMap<Class<?>, BiFunction<Config, String, ?>> 
beanConverters = new ConcurrentHashMap<>();
 
     /**
      * Determine the bean converter function to be used according to the rules 
defined in
@@ -41,7 +41,7 @@ public final class BeanConverterFactory
      */
     public <N> BiFunction<Config, String, N> detectConverter(Class<N> clazz)
     {
-        BiFunction<Config, String, N> beanConverter = (BiFunction<Config, 
String, N>) BEAN_CONVERTER.get(clazz);
+        BiFunction<Config, String, N> beanConverter = (BiFunction<Config, 
String, N>) beanConverters.get(clazz);
         if (beanConverter == null)
         {
             // class with public param ct
@@ -62,7 +62,7 @@ public final class BeanConverterFactory
                 beanConverter = new CtInjectionBeanConverter(clazz, 
paramConstructors.get(0));
             }
 
-            BEAN_CONVERTER.putIfAbsent(clazz, beanConverter);
+            beanConverters.putIfAbsent(clazz, beanConverter);
         }
 
         return beanConverter;
diff --git 
a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/BeanConfigResolverTest.java
 
b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/BeanConfigResolverTest.java
index 2b1899a..d038d62 100644
--- 
a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/BeanConfigResolverTest.java
+++ 
b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/BeanConfigResolverTest.java
@@ -21,8 +21,9 @@ package org.apache.deltaspike.test.core.api.config;
 import java.util.function.BiFunction;
 
 import org.apache.deltaspike.core.api.config.Config;
-import org.apache.deltaspike.core.api.config.ConfigProperty;
 import org.apache.deltaspike.core.api.config.ConfigResolver;
+import 
org.apache.deltaspike.test.core.api.config.beans.ServerEndpointPojoWithCt;
+import 
org.apache.deltaspike.test.core.api.config.beans.ServerEndpointPojoWithFields;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -70,38 +71,4 @@ public class BeanConfigResolverTest
     }
 
 
-    public static class ServerEndpointPojoWithCt extends 
ServerEndpointPojoWithFields
-    {
-        public ServerEndpointPojoWithCt(@ConfigProperty(name = "host") String 
host,
-                                        @ConfigProperty(name = "port") Integer 
port,
-                                        @ConfigProperty(name = "path") String 
path)
-        {
-            this.host = host;
-            this.port = port;
-            this.path = path;
-        }
-
-    }
-
-    public static class ServerEndpointPojoWithFields
-    {
-        protected String host;
-        protected Integer port;
-        protected String path;
-
-        @Override
-        public String toString()
-        {
-            StringBuilder sb = new StringBuilder();
-            if (host == null)
-            {
-                return "unknown";
-            }
-            sb.append((port != null && port.equals(443)) ? "https://"; : 
"http://";);
-            sb.append(host);
-            sb.append(port == null ? ":80" : ":" + port);
-            sb.append(path != null ? path : "");
-            return sb.toString();
-        }
-    }
 }
diff --git 
a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/DeltaSpikeConfigInfoMBean.java
 
b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/beans/ServerEndpointPojoWithCt.java
similarity index 57%
copy from 
deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/DeltaSpikeConfigInfoMBean.java
copy to 
deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/beans/ServerEndpointPojoWithCt.java
index d2d154f..2057124 100644
--- 
a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/DeltaSpikeConfigInfoMBean.java
+++ 
b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/beans/ServerEndpointPojoWithCt.java
@@ -1,33 +1,37 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.deltaspike.core.impl.config;
-
-import javax.management.openmbean.TabularData;
-
-public interface DeltaSpikeConfigInfoMBean
-{
-    String[] getConfigSourcesAsString();
-
-    TabularData getConfigSources();
-
-    String[] getConfigEntriesAsString();
-
-    TabularData getConfigEntries();
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.core.api.config.beans;
+
+import org.apache.deltaspike.core.api.config.ConfigProperty;
+
+/**
+ * @author <a href="mailto:[email protected]";>Mark Struberg</a>
+ */
+public class ServerEndpointPojoWithCt extends ServerEndpointPojoWithFields
+{
+    public ServerEndpointPojoWithCt(@ConfigProperty(name = "host") String host,
+                                    @ConfigProperty(name = "port") Integer 
port,
+                                    @ConfigProperty(name = "path") String path)
+    {
+        this.host = host;
+        this.port = port;
+        this.path = path;
+    }
+
+}
diff --git 
a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/beans/ServerEndpointPojoWithFields.java
 
b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/beans/ServerEndpointPojoWithFields.java
new file mode 100644
index 0000000..0f7ec05
--- /dev/null
+++ 
b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/beans/ServerEndpointPojoWithFields.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.core.api.config.beans;
+
+/**
+ * @author <a href="mailto:[email protected]";>Mark Struberg</a>
+ */
+public class ServerEndpointPojoWithFields
+{
+    protected String host;
+    protected Integer port;
+    protected String path;
+
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+        if (host == null)
+        {
+            return "unknown";
+        }
+        sb.append((port != null && port.equals(443)) ? "https://"; : "http://";);
+        sb.append(host);
+        sb.append(port == null ? ":80" : ":" + port);
+        sb.append(path != null ? path : "");
+        return sb.toString();
+    }
+}
diff --git 
a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/InjectableConfigPropertyTest.java
 
b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/InjectableConfigPropertyTest.java
index 2b4c8be..f7f27c0 100644
--- 
a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/InjectableConfigPropertyTest.java
+++ 
b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/InjectableConfigPropertyTest.java
@@ -18,12 +18,17 @@
  */
 package org.apache.deltaspike.test.core.api.config.injectable;
 
+import javax.inject.Inject;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.HashSet;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
 
+import org.apache.deltaspike.core.api.config.ConfigProperty;
 import org.apache.deltaspike.core.api.provider.BeanProvider;
 import org.apache.deltaspike.test.category.SeCategory;
+import 
org.apache.deltaspike.test.core.api.config.beans.ServerEndpointPojoWithCt;
 import org.apache.deltaspike.test.util.ArchiveUtils;
 import org.apache.deltaspike.test.util.FileUtils;
 import org.jboss.arquillian.container.test.api.Deployment;
@@ -32,6 +37,7 @@ import org.jboss.shrinkwrap.api.ShrinkWrap;
 import org.jboss.shrinkwrap.api.asset.EmptyAsset;
 import org.jboss.shrinkwrap.api.spec.JavaArchive;
 import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Assert;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
@@ -41,6 +47,7 @@ import 
org.apache.deltaspike.test.core.api.config.injectable.numberconfig.Number
 import static java.util.Arrays.asList;
 import static java.util.Collections.singletonList;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
 
@@ -59,6 +66,7 @@ public class InjectableConfigPropertyTest
 
         JavaArchive testJar = ShrinkWrap.create(JavaArchive.class, 
"injectableConfigPropertyTest.jar")
                 .addPackage(SettingsBean.class.getPackage())
+                .addPackage(ServerEndpointPojoWithCt.class.getPackage())
                 .addPackage(NumberConfiguredBean.class.getPackage())
                 
.addAsManifestResource(FileUtils.getFileForURL(fileUrl.toString()))
                 .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
@@ -69,6 +77,30 @@ public class InjectableConfigPropertyTest
                 .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
     }
 
+    @ConfigProperty(name = "myapp.some.server", cacheFor = 2, cacheUnit = 
TimeUnit.SECONDS)
+    private @Inject Supplier<ServerEndpointPojoWithCt> someServer;
+
+    @ConfigProperty(name = "myapp.other.server")
+    private @Inject Supplier<ServerEndpointPojoWithCt> otherServer;
+
+
+    @Test
+    public void injectBeanViaProvider() {
+        assertNotNull(someServer);
+        final ServerEndpointPojoWithCt server1 = someServer.get();
+        assertNotNull(server1);
+        Assert.assertEquals("http://myserver:80/myapp/endpoint1";, 
server1.toString());
+
+        // once again
+        final ServerEndpointPojoWithCt server2 = someServer.get();
+        assertNotNull(server2);
+        Assert.assertEquals("http://myserver:80/myapp/endpoint1";, 
server2.toString());
+        Assert.assertTrue(server1 == server2);
+
+        assertNotNull(otherServer.get());
+        Assert.assertEquals("https://otherserver:443/otherapp/endpoint2";, 
otherServer.get().toString());
+    }
+
     @Test
     public void injectionViaConfigProperty()
     {
@@ -80,8 +112,12 @@ public class InjectableConfigPropertyTest
 
         // also check the ones with defaultValue
         assertEquals("14", settingsBean.getProperty3Filled());
+
         assertEquals("myDefaultValue", settingsBean.getProperty3Defaulted());
+        assertEquals("myDefaultValue", 
settingsBean.getSupplierStringProperty3Defaulted().get());
+
         assertEquals(42, settingsBean.getProperty4Defaulted());
+        assertEquals(Integer.valueOf(42), 
settingsBean.getSupplierIntProperty4Defaulted().get());
 
         assertEquals("some setting for prodDB", settingsBean.getDbConfig());
     }
@@ -103,7 +139,7 @@ public class InjectableConfigPropertyTest
     }
 
     @Test
-    public void testNmberConfigInjection()
+    public void testNumberConfigInjection()
     {
         NumberConfiguredBean numberBean = 
BeanProvider.getContextualReference(NumberConfiguredBean.class, false);
         assertNull(numberBean.getPropertyNonexisting());
diff --git 
a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/SettingsBean.java
 
b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/SettingsBean.java
index cd582d2..55da26f 100644
--- 
a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/SettingsBean.java
+++ 
b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/SettingsBean.java
@@ -27,6 +27,8 @@ import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
 
 @ApplicationScoped
 public class SettingsBean
@@ -51,6 +53,14 @@ public class SettingsBean
     @ConfigProperty(name = "nonexistingProperty", defaultValue = "42")
     private Integer intProperty4Defaulted;
 
+    @Inject
+    @ConfigProperty(name = "nonexistingProperty", defaultValue = 
"myDefaultValue", cacheFor = 10, cacheUnit = TimeUnit.MINUTES)
+    private Supplier<String> supplierStringProperty3Defaulted;
+
+    @Inject
+    @ConfigProperty(name = "nonexistingProperty", defaultValue = "42")
+    private Supplier<Integer> supplierIntProperty4Defaulted;
+
     private Long inverseProperty2;
 
     @Inject
@@ -159,6 +169,15 @@ public class SettingsBean
         return intProperty4Defaulted;
     }
 
+    public Supplier<String> getSupplierStringProperty3Defaulted()
+    {
+        return supplierStringProperty3Defaulted;
+    }
+
+    public Supplier<Integer> getSupplierIntProperty4Defaulted()
+    {
+        return supplierIntProperty4Defaulted;
+    }
 
     public Boolean getBooleanPropertyNull()
     {

Reply via email to