You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by an...@apache.org on 2017/10/15 22:26:46 UTC
incubator-tamaya-extensions git commit: TAMAYA-260 Aligned
functionality with MP, added support for Provider,
Instance and Optional method injection.
Repository: incubator-tamaya-extensions
Updated Branches:
refs/heads/master 7483ab3d0 -> fe5eac609
TAMAYA-260 Aligned functionality with MP, added support for Provider,Instance and Optional method injection.
Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/commit/fe5eac60
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/tree/fe5eac60
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/diff/fe5eac60
Branch: refs/heads/master
Commit: fe5eac609a95477073fc86a908760b8d71775809
Parents: 7483ab3
Author: Anatole Tresch <an...@apache.org>
Authored: Mon Oct 16 00:26:32 2017 +0200
Committer: Anatole Tresch <an...@apache.org>
Committed: Mon Oct 16 00:26:32 2017 +0200
----------------------------------------------------------------------
modules/injection/cdi/pom.xml | 94 +++---
.../tamaya/cdi/ConfigurationExtension.java | 290 -------------------
.../tamaya/cdi/ConfigurationProducer.java | 133 +++++----
.../tamaya/cdi/TamayaCDIInjectionExtension.java | 66 ++---
...onfigurationProducerFailedInjectionTest.java | 33 ---
.../tamaya/cdi/ConfigurationProducerTest.java | 123 +++++++-
.../org/apache/tamaya/cdi/ConfiguredTest.java | 29 +-
.../apache/tamaya/cdi/NotFoundNoDefault.java | 2 +-
.../org/apache/tamaya/inject/api/Config.java | 5 +-
.../tamaya/inject/internal/InjectionHelper.java | 5 +-
10 files changed, 281 insertions(+), 499 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe5eac60/modules/injection/cdi/pom.xml
----------------------------------------------------------------------
diff --git a/modules/injection/cdi/pom.xml b/modules/injection/cdi/pom.xml
index 4f05d7d..c7ecc15 100644
--- a/modules/injection/cdi/pom.xml
+++ b/modules/injection/cdi/pom.xml
@@ -31,24 +31,41 @@ under the License.
<packaging>jar</packaging>
<properties>
- <owb.version>1.6.2</owb.version>
- <weld.version>2.2.7.Final</weld.version>
+ <deltaspike.version>1.1.0</deltaspike.version>
+ <openejb.version>4.7.1</openejb.version>
+ <weld.version>3.0.1.Final</weld.version>
<geronimo-jcdi-1.1-spec.version>1.0</geronimo-jcdi-1.1-spec.version>
<geronimo-interceptor-1.2-spec.version>1.0</geronimo-interceptor-1.2-spec.version>
<geronimo-atinject-1.0-spec.version>1.0</geronimo-atinject-1.0-spec.version>
- <bval.version>0.5</bval.version>
- <ds.version>1.1.0</ds.version>
+ <arquillian.version>1.1.13.Final</arquillian.version>
+ <arquillian-weld-embedded.version>2.0.0.Beta5</arquillian-weld-embedded.version>
+ <version.shrinkwrap.resolvers>2.2.6</version.shrinkwrap.resolvers>
+ <cdi-api.version>2.0</cdi-api.version>
<javaee-api.version>6.0-6</javaee-api.version>
- <openejb.version>4.7.1</openejb.version>
<tomee.version>1.7.1</tomee.version>
</properties>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.arquillian</groupId>
+ <artifactId>arquillian-bom</artifactId>
+ <version>${arquillian.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <version>${cdi-api.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
<dependencies>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
- <version>1.2</version>
- <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tamaya.ext</groupId>
@@ -89,66 +106,33 @@ under the License.
<version>${project.version}</version>
</dependency>
<dependency>
- <groupId>org.apache.openejb</groupId>
- <artifactId>javaee-api</artifactId>
- <version>${javaee-api.version}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.tomitribe</groupId>
- <artifactId>tomitribe-util</artifactId>
- <version>1.1.0</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.openejb</groupId>
- <artifactId>openejb-core</artifactId>
- <version>${openejb.version}</version>
- <scope>provided</scope>
+ <groupId>org.jboss.arquillian.junit</groupId>
+ <artifactId>arquillian-junit-container</artifactId>
+ <version>${arquillian.version}</version>
+ <scope>test</scope>
</dependency>
<dependency>
- <groupId>org.apache.geronimo.specs</groupId>
- <artifactId>geronimo-jcdi_1.1_spec</artifactId>
- <version>${geronimo-jcdi-1.1-spec.version}</version>
- <scope>provided</scope>
+ <groupId>org.jboss.arquillian.container</groupId>
+ <artifactId>arquillian-weld-embedded</artifactId>
+ <version>${arquillian-weld-embedded.version}</version>
+ <scope>test</scope>
</dependency>
<dependency>
- <groupId>org.apache.deltaspike.modules</groupId>
- <artifactId>deltaspike-test-control-module-api</artifactId>
- <version>${ds.version}</version>
+ <groupId>org.jboss.weld.se</groupId>
+ <artifactId>weld-se-shaded</artifactId>
+ <version>${weld.version}</version>
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.apache.deltaspike.modules</groupId>
- <artifactId>deltaspike-test-control-module-impl</artifactId>
- <version>${ds.version}</version>
+ <groupId>org.jboss.shrinkwrap.resolver</groupId>
+ <artifactId>shrinkwrap-resolver-depchain</artifactId>
+ <version>${version.shrinkwrap.resolvers}</version>
<scope>test</scope>
+ <type>pom</type>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>
</dependencies>
- <profiles>
- <profile>
- <id>Weld</id>
- <activation>
- <activeByDefault>true</activeByDefault>
- </activation>
- <dependencies>
- <dependency>
- <groupId>org.jboss.weld.se</groupId>
- <artifactId>weld-se</artifactId>
- <version>${weld.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.deltaspike.cdictrl</groupId>
- <artifactId>deltaspike-cdictrl-weld</artifactId>
- <version>${ds.version}</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
- </profile>
- </profiles>
</project>
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe5eac60/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/ConfigurationExtension.java
----------------------------------------------------------------------
diff --git a/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/ConfigurationExtension.java b/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/ConfigurationExtension.java
deleted file mode 100644
index b715b78..0000000
--- a/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/ConfigurationExtension.java
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * 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.tamaya.cdi;
-
-import org.apache.tamaya.ConfigException;
-import org.apache.tamaya.ConfigOperator;
-import org.apache.tamaya.Configuration;
-import org.apache.tamaya.ConfigurationProvider;
-import org.apache.tamaya.inject.api.Config;
-import org.apache.tamaya.inject.api.ConfigDefaultSections;
-import org.apache.tamaya.inject.api.WithConfigOperator;
-import org.apache.tamaya.inject.api.WithPropertyConverter;
-import org.apache.tamaya.spi.PropertyConverter;
-
-import javax.enterprise.context.spi.CreationalContext;
-import javax.enterprise.event.Observes;
-import javax.enterprise.inject.spi.AfterBeanDiscovery;
-import javax.enterprise.inject.spi.Bean;
-import javax.enterprise.inject.spi.BeanManager;
-import javax.enterprise.inject.spi.Extension;
-import javax.enterprise.inject.spi.InjectionPoint;
-import javax.enterprise.inject.spi.ProcessBean;
-import javax.enterprise.inject.spi.ProcessProducerMethod;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.logging.Logger;
-
-
-/**
- * CDI Extension module that adds injection mechanism for configuration.
- *
- * @see org.apache.tamaya.inject.api.Config
- * @see org.apache.tamaya.inject.api.ConfigDefaultSections
- * @see ConfigException
- */
-public class ConfigurationExtension implements Extension {
-
- private static final Logger LOG = Logger.getLogger(ConfigurationExtension.class.getName());
-
- static final Map<Class, ConfigOperator> CUSTOM_OPERATORS = new ConcurrentHashMap<>();
- static final Map<Class, PropertyConverter> CUSTOM_CONVERTERS = new ConcurrentHashMap<>();
-
- private final Set<Type> types = new HashSet<>();
- private Bean<?> convBean;
-
- /**
- * Constructor for loading logging its load.
- */
- public ConfigurationExtension(){
- LOG.finest("Loading Tamaya CDI Support...");
- }
-
- /**
- * Method that checks the configuration injection points during deployment for available configuration.
- * @param pb the bean to process.
- * @param beanManager the bean manager to notify about new injections.
- */
- public void retrieveTypes(@Observes final ProcessBean<?> pb, BeanManager beanManager) {
-
- final Set<InjectionPoint> ips = pb.getBean().getInjectionPoints();
- CDIConfiguredType configuredType = new CDIConfiguredType(pb.getBean().getBeanClass());
-
- boolean configured = false;
- boolean logged = false;
- for (InjectionPoint injectionPoint : ips) {
- if (injectionPoint.getAnnotated().isAnnotationPresent(Config.class)) {
- final Config annotation = injectionPoint.getAnnotated().getAnnotation(Config.class);
- final ConfigDefaultSections typeAnnot = injectionPoint.getAnnotated().getAnnotation(ConfigDefaultSections.class);
- final List<String> keys = evaluateKeys(injectionPoint.getMember().getName(),
- annotation!=null?annotation.value():null,
- typeAnnot!=null?typeAnnot.value():null);
-
- final WithConfigOperator withOperatorAnnot = injectionPoint.getAnnotated().getAnnotation(WithConfigOperator.class);
- if(withOperatorAnnot!=null){
- tryLoadOpererator(withOperatorAnnot.value());
- }
- final WithPropertyConverter withConverterAnnot = injectionPoint.getAnnotated().getAnnotation(WithPropertyConverter.class);
- if(withConverterAnnot!=null){
- tryLoadConverter(withConverterAnnot.value());
- }
-
- // We don't want to wait until the injection really fails at runtime.
- // If there is a non resolvable configuration, we want to know at startup.
- Configuration config = ConfigurationProvider.getConfiguration();
- String value = null;
- for(String key:keys) {
- value = config.get(key);
- if(value!=null){
- break;
- }
- }
- if(value==null && !annotation.defaultValue().isEmpty()){
- value = annotation.defaultValue();
- }
- if(value==null){
- throw new ConfigException(String.format(
- "Cannot resolve any of the possible configuration keys: %s. Please provide one of the given keys " +
- "with a value in your configuration sources.",
- keys.toString()));
- }
- types.add(injectionPoint.getType());
- if(annotation!=null){
- configured = true;
- if(!logged) {
- LOG.finest("Enabling Tamaya CDI Configuration on bean: " + configuredType.getName());
- }
- configuredType.addConfiguredMember(injectionPoint, keys);
- }
- }
- }
- if(configured) {
- beanManager.fireEvent(configuredType);
- }
- }
-
-
- public void captureConvertBean(@Observes final ProcessProducerMethod<?, ?> ppm) {
- if (ppm.getAnnotated().isAnnotationPresent(Config.class)) {
- convBean = ppm.getBean();
- }
-
- }
-
- public void addConverter(@Observes final AfterBeanDiscovery abd, final BeanManager bm) {
- if(!types.isEmpty()) {
- abd.addBean(new ConverterBean(convBean, types));
- }
- }
-
- private void tryLoadOpererator(Class<? extends ConfigOperator> operatorClass) {
- Objects.requireNonNull(operatorClass);
- if(ConfigOperator.class == operatorClass){
- return;
- }
- try{
- if(!CUSTOM_OPERATORS.containsKey(operatorClass)) {
- CUSTOM_OPERATORS.put(operatorClass, operatorClass.newInstance());
- }
- } catch(Exception e){
- throw new ConfigException("Custom ConfigOperator could not be loaded: " + operatorClass.getName(), e);
- }
- }
-
- private void tryLoadConverter(Class<? extends PropertyConverter> converterClass) {
- Objects.requireNonNull(converterClass);
- if(PropertyConverter.class == converterClass){
- return;
- }
- try{
- if(!CUSTOM_CONVERTERS.containsKey(converterClass)) {
- CUSTOM_CONVERTERS.put(converterClass, converterClass.newInstance());
- }
- } catch(Exception e){
- throw new ConfigException("Custom PropertyConverter could not be loaded: " + converterClass.getName(), e);
- }
- }
-
- /**
- * Evaluates the effective keys to be used. if no {@code keys} are defined, {@code memberName} is used.
- * The effective keys are then combined with the sections given (if any) and only, if the given keys are not
- * absolute keys (surrounded by brackets).
- * @param memberName the default member name, not null.
- * @param keys the keys, may be empty, or null.
- * @param sections the default sections, may be empty. May also be null.
- * @return the list of keys to be finally used for configuration resolution in order of
- * precedence. The first keys in the list that could be successfully resolved define the final
- * configuration value.
- */
- public static List<String> evaluateKeys(String memberName, String[] keys, String[] sections) {
- List<String> effKeys = new ArrayList<>();
- if(keys!=null){
- effKeys.addAll(Arrays.asList(keys));
- }
- if (effKeys.isEmpty()) {
- effKeys.add(memberName);
- }
- ListIterator<String> iterator = effKeys.listIterator();
- while (iterator.hasNext()) {
- String next = iterator.next();
- if (next.startsWith("[") && next.endsWith("]")) {
- // absolute key, strip away brackets, take key as is
- iterator.set(next.substring(1, next.length() - 1));
- } else {
- if (sections != null && sections.length>0) {
- // Remove original entry, since it will be replaced with prefixed entries
- iterator.remove();
- // Add prefixed entries, including absolute (root) entry for "" area keys.
- for (String area : sections) {
- iterator.add(area.isEmpty() ? next : area + '.' + next);
- }
- }
- }
- }
- return effKeys;
- }
-
-
- /**
- * Internally used conversion bean.
- */
- private static class ConverterBean implements Bean<Object> {
-
- private final Bean<Object> delegate;
- private final Set<Type> types;
-
- public ConverterBean(final Bean convBean, final Set<Type> types) {
- this.types = types;
- this.delegate = convBean;
- }
-
- @Override
- public Set<Type> getTypes() {
- return types;
- }
-
- @Override
- public Class<?> getBeanClass() {
- return delegate.getBeanClass();
- }
-
- @Override
- public Set<InjectionPoint> getInjectionPoints() {
- return delegate.getInjectionPoints();
- }
-
- @Override
- public String getName() {
- return delegate.getName();
- }
-
- @Override
- public Set<Annotation> getQualifiers() {
- return delegate.getQualifiers();
- }
-
- @Override
- public Class<? extends Annotation> getScope() {
- return delegate.getScope();
- }
-
- @Override
- public Set<Class<? extends Annotation>> getStereotypes() {
- return delegate.getStereotypes();
- }
-
- @Override
- public boolean isAlternative() {
- return delegate.isAlternative();
- }
-
- @Override
- public boolean isNullable() {
- return delegate.isNullable();
- }
-
- @Override
- public Object create(CreationalContext<Object> creationalContext) {
- return delegate.create(creationalContext);
- }
-
- @Override
- public void destroy(Object instance, CreationalContext<Object> creationalContext) {
- delegate.destroy(instance, creationalContext);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe5eac60/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/ConfigurationProducer.java
----------------------------------------------------------------------
diff --git a/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/ConfigurationProducer.java b/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/ConfigurationProducer.java
index 1d07c98..ac6a4f9 100644
--- a/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/ConfigurationProducer.java
+++ b/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/ConfigurationProducer.java
@@ -24,18 +24,11 @@ import org.apache.tamaya.spi.ConversionContext;
import org.apache.tamaya.spi.PropertyConverter;
import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Instance;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;
-import java.io.File;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
+import javax.inject.Provider;
+import java.lang.reflect.*;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -65,7 +58,7 @@ public class ConfigurationProducer {
return createDynamicValue(injectionPoint);
}
final Config annotation = injectionPoint.getAnnotated().getAnnotation(Config.class);
- final ConfigDefaultSections typeAnnot = injectionPoint.getAnnotated().getAnnotation(ConfigDefaultSections.class);
+ final ConfigDefaultSections typeAnnot = injectionPoint.getMember().getDeclaringClass().getAnnotation(ConfigDefaultSections.class);
final List<String> keys = TamayaCDIInjectionExtension.evaluateKeys(injectionPoint.getMember().getName(),
annotation != null ? annotation.value() : null,
typeAnnot != null ? typeAnnot.value() : null);
@@ -83,64 +76,98 @@ public class ConfigurationProducer {
// unless the extension is not installed, this should never happen because the extension
// enforces the resolvability of the config
+
+ String defaultTextValue = annotation.defaultValue().equals(Config.UNCONFIGURED_VALUE) ? null : annotation.defaultValue();
+ String textValue = null;
Configuration config = ConfigurationProvider.getConfiguration();
- if (operator != null) {
- config = operator.operate(config);
+ if(operator!=null) {
+ config = config.with(operator);
}
- final Class<?> toType = (Class<?>) injectionPoint.getAnnotated().getBaseType();
- String textValue = null;
- String defaultTextValue = annotation.defaultValue().isEmpty() ? "" : annotation.defaultValue();
String keyFound = null;
- for (String key : keys) {
+ for(String key:keys) {
textValue = config.get(key);
- if (textValue != null) {
+ if(textValue!=null) {
keyFound = key;
break;
}
}
- ConversionContext.Builder builder = new ConversionContext.Builder(config,
- ConfigurationProvider.getConfiguration().getContext(), keyFound, TypeLiteral.of(toType));
- if (injectionPoint.getMember() instanceof AnnotatedElement) {
- builder.setAnnotatedElement((AnnotatedElement) injectionPoint.getMember());
+ if(textValue==null) {
+ textValue = defaultTextValue;
}
- ConversionContext conversionContext = builder.build();
- Object value = null;
- if (keyFound != null) {
- if (customConverter != null) {
- value = customConverter.convert(textValue, conversionContext);
- }
- if (value == null) {
- value = config.get(keyFound, toType);
+ ConversionContext conversionContext = createConversionContext(keyFound, keys, injectionPoint);
+ Object value = convertValue(textValue, conversionContext, injectionPoint, customConverter);
+ if (value == null) {
+ throw new ConfigException(String.format(
+ "Can't resolve any of the possible config keys: %s to the required target type: %s, supported formats: %s",
+ keys, conversionContext.getTargetType(), conversionContext.getSupportedFormats().toString()));
+ }
+ LOGGER.finest(String.format("Injecting %s for key %s in class %s", keyFound, value.toString(), injectionPoint.toString()));
+ return value;
+ }
+
+ static ConversionContext createConversionContext(String key, List<String> keys, InjectionPoint injectionPoint) {
+ final Type targetType = injectionPoint.getAnnotated().getBaseType();
+ Configuration config = ConfigurationProvider.getConfiguration();
+ ConversionContext.Builder builder = new ConversionContext.Builder(config,
+ ConfigurationProvider.getConfiguration().getContext(), key, TypeLiteral.of(targetType));
+ // builder.setKeys(keys);
+ if(targetType instanceof ParameterizedType){
+ ParameterizedType pt = (ParameterizedType)targetType;
+ if(pt.getRawType().equals(Provider.class)) {
+ builder.setTargetType(
+ TypeLiteral.of(pt.getActualTypeArguments()[0]));
}
- } else if (defaultTextValue != null) {
- value = defaultTextValue;
- if (customConverter != null) {
- value = customConverter.convert((String)value, conversionContext);
+ }
+ if (injectionPoint.getMember() instanceof Field) {
+ Field annotated = (Field)injectionPoint.getMember();
+ if(annotated.isAnnotationPresent(Config.class)) {
+ builder.setAnnotatedElement(annotated);
}
- if (value != null) {
- List<PropertyConverter<Object>> converters = ConfigurationProvider.getConfiguration().getContext()
- .getPropertyConverters(TypeLiteral.of(toType));
- for (PropertyConverter<Object> converter : converters) {
- try {
- value = converter.convert(defaultTextValue, conversionContext);
- if (value != null) {
- LOGGER.log(Level.FINEST, "Parsed default value from '" + defaultTextValue + "' into " +
- injectionPoint);
- break;
- }
- } catch (Exception e) {
- LOGGER.log(Level.FINEST, "Failed to convert default value '" + defaultTextValue + "' for " +
- injectionPoint, e);
+ }else if(injectionPoint.getMember() instanceof Method){
+ Method method = (Method)injectionPoint.getMember();
+ for(Type type:method.getParameterTypes()){
+ if(type instanceof AnnotatedElement){
+ AnnotatedElement annotated = (AnnotatedElement)type;
+ if(annotated.isAnnotationPresent(Config.class)) {
+ builder.setAnnotatedElement(annotated);
}
}
}
}
- if (value == null) {
- throw new ConfigException(String.format(
- "Can't resolve any of the possible config keys: %s to the required target type: %s, supported formats: %s",
- keys.toString(), toType.getName(), conversionContext.getSupportedFormats().toString()));
+ return builder.build();
+ }
+
+ static Object convertValue(String textValue, ConversionContext conversionContext, InjectionPoint injectionPoint,
+ PropertyConverter customConverter) {
+ if (customConverter != null) {
+ return customConverter.convert(textValue, conversionContext);
+ }
+ if(String.class.equals(conversionContext.getTargetType().getRawType())){
+ return textValue;
+ }
+ Object value = null;
+ Type toType = injectionPoint.getAnnotated().getBaseType();
+ if(toType instanceof ParameterizedType){
+ ParameterizedType pt = (ParameterizedType)toType;
+ if(Provider.class.equals(pt.getRawType()) || Instance.class.equals(pt.getRawType())){
+ toType = pt.getActualTypeArguments()[0];
+ }
+ }
+ List<PropertyConverter<Object>> converters = ConfigurationProvider.getConfiguration().getContext()
+ .getPropertyConverters(TypeLiteral.of(toType));
+ for (PropertyConverter<Object> converter : converters) {
+ try {
+ value = converter.convert(textValue, conversionContext);
+ if (value != null) {
+ LOGGER.log(Level.FINEST, "Parsed value from '" + textValue + "' into " +
+ injectionPoint);
+ break;
+ }
+ } catch (Exception e) {
+ LOGGER.log(Level.FINEST, "Failed to convert value '" + textValue + "' for " +
+ injectionPoint, e);
+ }
}
- LOGGER.finest(String.format("Injecting %s for key %s in class %s", keyFound, value.toString(), injectionPoint.toString()));
return value;
}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe5eac60/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/TamayaCDIInjectionExtension.java
----------------------------------------------------------------------
diff --git a/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/TamayaCDIInjectionExtension.java b/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/TamayaCDIInjectionExtension.java
index 749c9b0..2485f05 100644
--- a/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/TamayaCDIInjectionExtension.java
+++ b/modules/injection/cdi/src/main/java/org/apache/tamaya/cdi/TamayaCDIInjectionExtension.java
@@ -18,8 +18,6 @@ package org.apache.tamaya.cdi;
import org.apache.tamaya.ConfigException;
import org.apache.tamaya.ConfigOperator;
-import org.apache.tamaya.Configuration;
-import org.apache.tamaya.ConfigurationProvider;
import org.apache.tamaya.inject.api.Config;
import org.apache.tamaya.inject.api.ConfigDefaultSections;
import org.apache.tamaya.inject.api.WithConfigOperator;
@@ -28,9 +26,11 @@ import org.apache.tamaya.spi.PropertyConverter;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.event.Observes;
+import javax.enterprise.inject.Instance;
import javax.enterprise.inject.spi.*;
+import javax.inject.Provider;
import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
+import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
@@ -51,7 +51,7 @@ public class TamayaCDIInjectionExtension implements Extension {
static final Map<Class, PropertyConverter> CUSTOM_CONVERTERS = new ConcurrentHashMap<>();
private final Set<Type> types = new HashSet<>();
- private Bean<?> convBean;
+ private Bean<?> tamayaProducerBean;
/**
* Constructor for loading logging its load.
@@ -71,15 +71,14 @@ public class TamayaCDIInjectionExtension implements Extension {
CDIConfiguredType configuredType = new CDIConfiguredType(pb.getBean().getBeanClass());
boolean configured = false;
- boolean logged = false;
for (InjectionPoint injectionPoint : ips) {
if (injectionPoint.getAnnotated().isAnnotationPresent(Config.class)) {
+ LOG.fine("Configuring: " + injectionPoint);
final Config annotation = injectionPoint.getAnnotated().getAnnotation(Config.class);
- final ConfigDefaultSections typeAnnot = injectionPoint.getAnnotated().getAnnotation(ConfigDefaultSections.class);
+ final ConfigDefaultSections typeAnnot = injectionPoint.getMember().getDeclaringClass().getAnnotation(ConfigDefaultSections.class);
final List<String> keys = evaluateKeys(injectionPoint.getMember().getName(),
annotation!=null?annotation.value():null,
typeAnnot!=null?typeAnnot.value():null);
-
final WithConfigOperator withOperatorAnnot = injectionPoint.getAnnotated().getAnnotation(WithConfigOperator.class);
if(withOperatorAnnot!=null){
tryLoadOpererator(withOperatorAnnot.value());
@@ -88,34 +87,12 @@ public class TamayaCDIInjectionExtension implements Extension {
if(withConverterAnnot!=null){
tryLoadConverter(withConverterAnnot.value());
}
-
- // We don't want to wait until the injection really fails at runtime.
- // If there is a non resolvable configuration, we want to know at startup.
- Configuration config = ConfigurationProvider.getConfiguration();
- String value = null;
- for(String key:keys) {
- value = config.get(key);
- if(value!=null){
- break;
- }
- }
- if(value==null && !annotation.defaultValue().isEmpty()){
- value = annotation.defaultValue();
- }
- if(value==null){
- throw new ConfigException(String.format(
- "Cannot resolve any of the possible configuration keys: %s. Please provide one of the given keys " +
- "with a value in your configuration sources.",
- keys.toString()));
- }
- types.add(injectionPoint.getType());
- if(annotation!=null){
- configured = true;
- if(!logged) {
- LOG.finest("Enabling Tamaya CDI Configuration on bean: " + configuredType.getName());
- }
- configuredType.addConfiguredMember(injectionPoint, keys);
- }
+ Type originalType = injectionPoint.getAnnotated().getBaseType();
+ Type convertedType = unwrapType(originalType);
+ types.add(convertedType);
+ configured = true;
+ LOG.finest("Enabling Tamaya CDI Configuration on bean: " + configuredType.getName());
+ configuredType.addConfiguredMember(injectionPoint, keys);
}
}
if(configured) {
@@ -126,15 +103,24 @@ public class TamayaCDIInjectionExtension implements Extension {
public void captureConvertBean(@Observes final ProcessProducerMethod<?, ?> ppm) {
if (ppm.getAnnotated().isAnnotationPresent(Config.class)) {
- convBean = ppm.getBean();
+ tamayaProducerBean = ppm.getBean();
}
-
}
public void addConverter(@Observes final AfterBeanDiscovery abd, final BeanManager bm) {
- if(!types.isEmpty()) {
- abd.addBean(new ConverterBean(convBean, types));
+ if(!types.isEmpty()&& tamayaProducerBean!=null) {
+ abd.addBean(new ConverterBean(tamayaProducerBean, types));
+ }
+ }
+
+ private Type unwrapType(Type type) {
+ if(type instanceof ParameterizedType) {
+ Type rawType = ((ParameterizedType) type).getRawType();
+ if(rawType == Provider.class || rawType == Instance.class) {
+ return ((ParameterizedType) type).getActualTypeArguments()[0];
+ }
}
+ return type;
}
private void tryLoadOpererator(Class<? extends ConfigOperator> operatorClass) {
@@ -215,7 +201,7 @@ public class TamayaCDIInjectionExtension implements Extension {
public ConverterBean(final Bean convBean, final Set<Type> types) {
this.types = types;
- this.delegate = convBean;
+ this.delegate = Objects.requireNonNull(convBean);
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe5eac60/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/ConfigurationProducerFailedInjectionTest.java
----------------------------------------------------------------------
diff --git a/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/ConfigurationProducerFailedInjectionTest.java b/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/ConfigurationProducerFailedInjectionTest.java
deleted file mode 100644
index a590c0d..0000000
--- a/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/ConfigurationProducerFailedInjectionTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.tamaya.cdi;
-
-import org.apache.openejb.OpenEjbContainer;
-import org.junit.Test;
-
-import javax.ejb.embeddable.EJBContainer;
-
-public class ConfigurationProducerFailedInjectionTest {
-
- @Test(expected = OpenEjbContainer.AssembleApplicationException.class)
- public void notFoundShouldNotDeploy() {
- // this explicitly tests that a non resolvable config makes
- // the deployment fail and we won't have any failure at runtime
- EJBContainer.createEJBContainer();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe5eac60/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/ConfigurationProducerTest.java
----------------------------------------------------------------------
diff --git a/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/ConfigurationProducerTest.java b/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/ConfigurationProducerTest.java
index b62eb66..138a83d 100644
--- a/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/ConfigurationProducerTest.java
+++ b/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/ConfigurationProducerTest.java
@@ -16,34 +16,39 @@
*/
package org.apache.tamaya.cdi;
-import org.apache.openejb.jee.EjbJar;
-import org.apache.openejb.junit.ApplicationComposer;
-import org.apache.openejb.testing.Classes;
-import org.apache.openejb.testing.Module;
-import org.apache.tamaya.cdi.ConfigurationProducer;
-import org.apache.tamaya.cdi.TamayaCDIAccessor;
-import org.apache.tamaya.cdi.TamayaCDIInjectionExtension;
import org.apache.tamaya.inject.api.Config;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.model.InitializationError;
+import javax.enterprise.inject.spi.Extension;
import javax.inject.Inject;
+import javax.inject.Provider;
import java.io.File;
+import java.util.Optional;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
-@RunWith(ApplicationComposer.class)
+@RunWith(Arquillian.class)
public class ConfigurationProducerTest {
- @Module
- @Classes(cdi = true, value = {
- AllTypes.class,
- TamayaCDIInjectionExtension.class, TamayaCDIAccessor.class,
- ConfigurationProducer.class
- })
- public EjbJar jar() {
- return new EjbJar("config");
+ @Deployment
+ public static Archive deployment() {
+ return ShrinkWrap.create(WebArchive.class)
+ .addClasses(ConfiguredClass.class, InjectedClass.class,
+ TamayaCDIInjectionExtension.class, TamayaCDIAccessor.class,
+ ConfigurationProducer.class)
+ .addAsServiceProvider(Extension.class, TamayaCDIInjectionExtension.class)
+ .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
+ .addAsWebInfResource("META-INF/javaconfiguration.properties", "META-INF/javaconfiguration.properties");
}
@Inject
@@ -69,13 +74,60 @@ public class ConfigurationProducerTest {
assertEquals(123, (int) allTypes.getInteger());
}
+ @Test
+ public void optionalStringFieldIsSet() {
+ assertNotNull(allTypes);
+ assertNotNull(allTypes.optionalString);
+ assertTrue(allTypes.optionalString.isPresent());
+ assertEquals("hello", allTypes.optionalString.get());
+ }
+
+ @Test
+ public void optionalIntegerFieldIsSet() {
+ assertNotNull(allTypes);
+ assertNotNull(allTypes.optionalInteger);
+ assertTrue(allTypes.optionalInteger.isPresent());
+ assertEquals(123, allTypes.optionalInteger.get().longValue());
+ }
+
+ @Test
+ public void providerStringFieldIsSet() {
+ assertNotNull(allTypes);
+ assertNotNull(allTypes.providerString);
+ assertEquals("hello", allTypes.providerString.get());
+ assertEquals("hello", allTypes.providerString.get());
+ }
+
+ @Test
+ public void providerIntegerFieldIsSet() {
+ assertNotNull(allTypes);
+ assertNotNull(allTypes.providerInteger);
+ assertEquals(123, allTypes.providerInteger.get().longValue());
+ assertEquals(123, allTypes.providerInteger.get().longValue());
+ }
+
static class AllTypes {
+ private String stringAsMethodParam;
+ private Integer integerAsMethodParam;
+ private Optional<String> optionalStringAsMethodParam;
+ private Optional<Integer> optionalIntegerAsMethodParam;
+ private Provider<String> providerStringAsMethodParam;
+ private Provider<Integer> providerIntegerAsMethodParam;
+
@Inject
@Config(value = "string.value", defaultValue = "defaultString")
private String string;
@Inject
+ @Config(value = "string.value", defaultValue = "defaultString")
+ private Optional<String> optionalString;
+
+ @Inject
+ @Config(value = "string.value", defaultValue = "defaultString")
+ private Provider<String> providerString;
+
+ @Inject
@Config(value = "defaultString.value", defaultValue = "defaultString")
private String defaultString;
@@ -103,6 +155,14 @@ public class ConfigurationProducerTest {
@Config(value = "defaultInteger.value", defaultValue = "45")
private Integer defaultInteger;
+ @Inject
+ @Config(value = "integer.value", defaultValue = "45")
+ private Optional<Integer> optionalInteger;
+
+ @Inject
+ @Config(value = "integer.value", defaultValue = "45")
+ private Provider<Integer> providerInteger;
+
public String getString() {
return string;
}
@@ -135,6 +195,37 @@ public class ConfigurationProducerTest {
return defaultInteger;
}
+
+ @Inject
+ public void setStringAsMethodParam(@Config(value = "string.value", defaultValue = "defaultString") String stringAsMethodParam) {
+ this.stringAsMethodParam = stringAsMethodParam;
+ }
+
+ @Inject
+ public void setIntegerAsMethodParam(@Config(value = "integer.value", defaultValue = "45")Integer integerAsMethodParam) {
+ this.integerAsMethodParam = integerAsMethodParam;
+ }
+
+ @Inject
+ public void setOptionalStringAsMethodParam(@Config(value = "string.value", defaultValue = "defaultString") Optional<String> optionalStringAsMethodParam) {
+ this.optionalStringAsMethodParam = optionalStringAsMethodParam;
+ }
+
+ @Inject
+ public void setOptionalIntegerAsMethodParam(@Config(value = "integer.value", defaultValue = "45") Optional<Integer> optionalIntegerAsMethodParam) {
+ this.optionalIntegerAsMethodParam = optionalIntegerAsMethodParam;
+ }
+
+ @Inject
+ public void setProviderStringAsMethodParam(@Config(value = "string.value", defaultValue = "defaultString") Provider<String> providerStringAsMethodParam) {
+ this.providerStringAsMethodParam = providerStringAsMethodParam;
+ }
+
+ @Inject
+ public void setProviderIntegerAsMethodParam(@Config(value = "integer.value", defaultValue = "45") Provider<Integer> providerIntegerAsMethodParam) {
+ this.providerIntegerAsMethodParam = providerIntegerAsMethodParam;
+ }
+
@Override
public String toString() {
return "AllTypes{" +
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe5eac60/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/ConfiguredTest.java
----------------------------------------------------------------------
diff --git a/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/ConfiguredTest.java b/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/ConfiguredTest.java
index f45f445..f50a9c6 100644
--- a/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/ConfiguredTest.java
+++ b/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/ConfiguredTest.java
@@ -19,15 +19,20 @@
*/
package org.apache.tamaya.cdi;
-import org.apache.deltaspike.testcontrol.api.TestControl;
-import org.apache.deltaspike.testcontrol.api.junit.CdiTestRunner;
import org.hamcrest.MatcherAssert;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.model.InitializationError;
+import org.mockito.AdditionalMatchers;
-import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.spi.CDI;
-import javax.inject.Singleton;
+import javax.enterprise.inject.spi.Extension;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertNotNull;
@@ -36,9 +41,19 @@ import static org.junit.Assert.assertTrue;
/**
* Tests for CDI integration.
*/
-@RunWith(CdiTestRunner.class)
-@TestControl(startScopes = {ApplicationScoped.class, Singleton.class})
-public class ConfiguredTest{
+@RunWith(Arquillian.class)
+public class ConfiguredTest {
+
+ @Deployment
+ public static Archive deployment() {
+ return ShrinkWrap.create(WebArchive.class)
+ .addClasses(ConfiguredTest.class, ConfiguredClass.class, InjectedClass.class,
+ AdditionalMatchers.class, NotFoundNoDefault.class,
+ ConfigurationProducer.class)
+ .addAsServiceProvider(Extension.class, TamayaCDIInjectionExtension.class)
+ .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
+ .addAsWebInfResource("META-INF/javaconfiguration.properties", "META-INF/javaconfiguration.properties");
+ }
@Test
public void test_Configuration_is_injected_correctly(){
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe5eac60/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/NotFoundNoDefault.java
----------------------------------------------------------------------
diff --git a/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/NotFoundNoDefault.java b/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/NotFoundNoDefault.java
index e08dac3..6e4e50e 100644
--- a/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/NotFoundNoDefault.java
+++ b/modules/injection/cdi/src/test/java/org/apache/tamaya/cdi/NotFoundNoDefault.java
@@ -17,11 +17,11 @@
package org.apache.tamaya.cdi;
import org.apache.tamaya.inject.api.Config;
-import org.tomitribe.util.Duration;
import javax.enterprise.inject.Alternative;
import javax.inject.Inject;
import java.io.File;
+import java.time.Duration;
@Alternative
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe5eac60/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/api/Config.java
----------------------------------------------------------------------
diff --git a/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/api/Config.java b/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/api/Config.java
index 67a3bfc..10ba0c8 100644
--- a/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/api/Config.java
+++ b/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/api/Config.java
@@ -89,6 +89,9 @@ import java.lang.annotation.Target;
@Target(value = { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
public @interface Config {
+ /** Value that is set by default as default, so it is possible to use empty Strings as default values. */
+ String UNCONFIGURED_VALUE = "org.apache.tamaya.config.configproperty.unconfigureddvalue";
+
/**
* Defines the configuration property keys to be used. Hereby the first non null value evaluated is injected as
* property value.
@@ -109,7 +112,7 @@ public @interface Config {
* @return default value used in case resolution fails.
*/
@Nonbinding
- String defaultValue() default "";
+ String defaultValue() default UNCONFIGURED_VALUE;
/**
* Flag that defines if a configuration property is required. If a required
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe5eac60/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/InjectionHelper.java
----------------------------------------------------------------------
diff --git a/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/InjectionHelper.java b/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/InjectionHelper.java
index f34393d..07a0431 100644
--- a/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/InjectionHelper.java
+++ b/modules/injection/standalone/src/main/java/org/apache/tamaya/inject/internal/InjectionHelper.java
@@ -134,10 +134,9 @@ final class InjectionHelper {
}
String configValue = evaluteConfigValue(keys, retKey, config);
if (configValue == null) {
- if(prop==null || prop.defaultValue().isEmpty()){
- return null;
+ if(prop!=null && !prop.defaultValue().equals(Config.UNCONFIGURED_VALUE)){
+ return prop.defaultValue();
}
- return prop.defaultValue();
}
return configValue;
}