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() {
