Search in sources :

Example 1 with BeansException

use of cn.taketoday.beans.BeansException in project today-infrastructure by TAKETODAY.

the class ConstructorResolver method createArgumentArray.

/**
 * Create an array of arguments to invoke a constructor or factory method,
 * given the resolved constructor argument values.
 */
private ArgumentsHolder createArgumentArray(String beanName, RootBeanDefinition merged, @Nullable ConstructorArgumentValues resolvedValues, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable, BeanWrapper wrapper, boolean autowiring, boolean fallback) throws UnsatisfiedDependencyException {
    TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
    TypeConverter converter = customConverter != null ? customConverter : wrapper;
    ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
    HashSet<ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
    LinkedHashSet<String> autowiredBeanNames = new LinkedHashSet<>(4);
    for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
        Class<?> paramType = paramTypes[paramIndex];
        String paramName = paramNames != null ? paramNames[paramIndex] : "";
        // Try to find matching constructor argument value, either indexed or generic.
        ValueHolder valueHolder = null;
        if (resolvedValues != null) {
            valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
            // it could match after type conversion (for example, String -> int).
            if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
                valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
            }
        }
        if (valueHolder != null) {
            // We found a potential match - let's give it a try.
            // Do not consider the same value definition multiple times!
            usedValueHolders.add(valueHolder);
            Object originalValue = valueHolder.getValue();
            Object convertedValue;
            if (valueHolder.isConverted()) {
                convertedValue = valueHolder.getConvertedValue();
                args.preparedArguments[paramIndex] = convertedValue;
            } else {
                MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
                try {
                    convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
                } catch (TypeMismatchException ex) {
                    throw new UnsatisfiedDependencyException(merged.getResourceDescription(), beanName, new InjectionPoint(methodParam), "Could not convert argument value of type [" + ObjectUtils.nullSafeClassName(valueHolder.getValue()) + "] to required type [" + paramType.getName() + "]: " + ex.getMessage());
                }
                Object sourceHolder = valueHolder.getSource();
                if (sourceHolder instanceof ValueHolder) {
                    Object sourceValue = ((ValueHolder) sourceHolder).getValue();
                    args.resolveNecessary = true;
                    args.preparedArguments[paramIndex] = sourceValue;
                }
            }
            args.arguments[paramIndex] = convertedValue;
            args.rawArguments[paramIndex] = originalValue;
        } else {
            MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
            // have to fail creating an argument array for the given constructor.
            if (!autowiring) {
                throw new UnsatisfiedDependencyException(merged.getResourceDescription(), beanName, new InjectionPoint(methodParam), "Ambiguous argument values for parameter of type [" + paramType.getName() + "] - did you specify the correct bean references as arguments?");
            }
            try {
                Object autowiredArgument = resolveAutowiredArgument(methodParam, beanName, autowiredBeanNames, converter, fallback);
                args.resolveNecessary = true;
                args.arguments[paramIndex] = autowiredArgument;
                args.rawArguments[paramIndex] = autowiredArgument;
                args.preparedArguments[paramIndex] = autowiredArgumentMarker;
            } catch (BeansException ex) {
                throw new UnsatisfiedDependencyException(merged.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
            }
        }
    }
    for (String autowiredBeanName : autowiredBeanNames) {
        beanFactory.registerDependentBean(autowiredBeanName, beanName);
        if (log.isDebugEnabled()) {
            log.debug("Autowiring by type from bean name '{}' via {} to bean named '{}'", beanName, (executable instanceof Constructor ? "constructor" : "factory method"), autowiredBeanName);
        }
    }
    return args;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) InjectionPoint(cn.taketoday.beans.factory.InjectionPoint) Constructor(java.lang.reflect.Constructor) TypeMismatchException(cn.taketoday.beans.TypeMismatchException) ValueHolder(cn.taketoday.beans.factory.config.ConstructorArgumentValues.ValueHolder) InjectionPoint(cn.taketoday.beans.factory.InjectionPoint) TypeConverter(cn.taketoday.beans.TypeConverter) UnsatisfiedDependencyException(cn.taketoday.beans.factory.UnsatisfiedDependencyException) MethodParameter(cn.taketoday.core.MethodParameter) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) BeansException(cn.taketoday.beans.BeansException)

Example 2 with BeansException

use of cn.taketoday.beans.BeansException in project today-infrastructure by TAKETODAY.

the class TestContextTransactionUtils method retrieveDataSource.

/**
 * Retrieve the {@link DataSource} to use for the supplied {@linkplain TestContext
 * test context}.
 * <p>The following algorithm is used to retrieve the {@code DataSource} from
 * the {@link cn.taketoday.context.ApplicationContext ApplicationContext}
 * of the supplied test context:
 * <ol>
 * <li>Look up the {@code DataSource} by type and name, if the supplied
 * {@code name} is non-empty, throwing a {@link BeansException} if the named
 * {@code DataSource} does not exist.
 * <li>Attempt to look up the single {@code DataSource} by type.
 * <li>Attempt to look up the <em>primary</em> {@code DataSource} by type.
 * <li>Attempt to look up the {@code DataSource} by type and the
 * {@linkplain #DEFAULT_DATA_SOURCE_NAME default data source name}.
 * </ol>
 *
 * @param testContext the test context for which the {@code DataSource}
 * should be retrieved; never {@code null}
 * @param name the name of the {@code DataSource} to retrieve
 * (may be {@code null} or <em>empty</em>)
 * @return the {@code DataSource} to use, or {@code null} if not found
 * @throws BeansException if an error occurs while retrieving an explicitly
 * named {@code DataSource}
 */
@Nullable
public static DataSource retrieveDataSource(TestContext testContext, @Nullable String name) {
    Assert.notNull(testContext, "TestContext must not be null");
    BeanFactory bf = testContext.getApplicationContext().getAutowireCapableBeanFactory();
    try {
        // Look up by type and explicit name
        if (StringUtils.hasText(name)) {
            return bf.getBean(name, DataSource.class);
        }
    } catch (BeansException ex) {
        logger.error(String.format("Failed to retrieve DataSource named '%s' for test context %s", name, testContext), ex);
        throw ex;
    }
    try {
        // Look up single bean by type
        Map<String, DataSource> dataSources = BeanFactoryUtils.beansOfTypeIncludingAncestors(bf, DataSource.class);
        if (dataSources.size() == 1) {
            return dataSources.values().iterator().next();
        }
        try {
            // look up single bean by type, with support for 'primary' beans
            return bf.getBean(DataSource.class);
        } catch (BeansException ex) {
            logBeansException(testContext, ex, PlatformTransactionManager.class);
        }
        // look up by type and default name
        return bf.getBean(DEFAULT_DATA_SOURCE_NAME, DataSource.class);
    } catch (BeansException ex) {
        logBeansException(testContext, ex, DataSource.class);
        return null;
    }
}
Also used : BeanFactory(cn.taketoday.beans.factory.BeanFactory) PlatformTransactionManager(cn.taketoday.transaction.PlatformTransactionManager) BeansException(cn.taketoday.beans.BeansException) DataSource(javax.sql.DataSource) Nullable(cn.taketoday.lang.Nullable)

Example 3 with BeansException

use of cn.taketoday.beans.BeansException in project today-framework by TAKETODAY.

the class TestContextTransactionUtils method retrieveDataSource.

/**
 * Retrieve the {@link DataSource} to use for the supplied {@linkplain TestContext
 * test context}.
 * <p>The following algorithm is used to retrieve the {@code DataSource} from
 * the {@link cn.taketoday.context.ApplicationContext ApplicationContext}
 * of the supplied test context:
 * <ol>
 * <li>Look up the {@code DataSource} by type and name, if the supplied
 * {@code name} is non-empty, throwing a {@link BeansException} if the named
 * {@code DataSource} does not exist.
 * <li>Attempt to look up the single {@code DataSource} by type.
 * <li>Attempt to look up the <em>primary</em> {@code DataSource} by type.
 * <li>Attempt to look up the {@code DataSource} by type and the
 * {@linkplain #DEFAULT_DATA_SOURCE_NAME default data source name}.
 * </ol>
 *
 * @param testContext the test context for which the {@code DataSource}
 * should be retrieved; never {@code null}
 * @param name the name of the {@code DataSource} to retrieve
 * (may be {@code null} or <em>empty</em>)
 * @return the {@code DataSource} to use, or {@code null} if not found
 * @throws BeansException if an error occurs while retrieving an explicitly
 * named {@code DataSource}
 */
@Nullable
public static DataSource retrieveDataSource(TestContext testContext, @Nullable String name) {
    Assert.notNull(testContext, "TestContext must not be null");
    BeanFactory bf = testContext.getApplicationContext().getAutowireCapableBeanFactory();
    try {
        // Look up by type and explicit name
        if (StringUtils.hasText(name)) {
            return bf.getBean(name, DataSource.class);
        }
    } catch (BeansException ex) {
        logger.error(String.format("Failed to retrieve DataSource named '%s' for test context %s", name, testContext), ex);
        throw ex;
    }
    try {
        // Look up single bean by type
        Map<String, DataSource> dataSources = BeanFactoryUtils.beansOfTypeIncludingAncestors(bf, DataSource.class);
        if (dataSources.size() == 1) {
            return dataSources.values().iterator().next();
        }
        try {
            // look up single bean by type, with support for 'primary' beans
            return bf.getBean(DataSource.class);
        } catch (BeansException ex) {
            logBeansException(testContext, ex, PlatformTransactionManager.class);
        }
        // look up by type and default name
        return bf.getBean(DEFAULT_DATA_SOURCE_NAME, DataSource.class);
    } catch (BeansException ex) {
        logBeansException(testContext, ex, DataSource.class);
        return null;
    }
}
Also used : BeanFactory(cn.taketoday.beans.factory.BeanFactory) PlatformTransactionManager(cn.taketoday.transaction.PlatformTransactionManager) BeansException(cn.taketoday.beans.BeansException) DataSource(javax.sql.DataSource) Nullable(cn.taketoday.lang.Nullable)

Example 4 with BeansException

use of cn.taketoday.beans.BeansException in project today-framework by TAKETODAY.

the class XmlListableBeanFactoryTests method setup.

@BeforeEach
public void setup() {
    parent = new StandardBeanFactory();
    Map map = new HashMap();
    map.put("name", "Albert");
    RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
    bd1.setPropertyValues(new PropertyValues(map));
    parent.registerBeanDefinition("father", bd1);
    map = new HashMap();
    map.put("name", "Roderick");
    RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
    bd2.setPropertyValues(new PropertyValues(map));
    parent.registerBeanDefinition("rod", bd2);
    this.factory = new StandardBeanFactory(parent);
    new XmlBeanDefinitionReader(this.factory).loadBeanDefinitions(new ClassPathResource("test.xml", getClass()));
    this.factory.addBeanPostProcessor(new InitializationBeanPostProcessor() {

        @Override
        public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
            if (bean instanceof TestBean) {
                ((TestBean) bean).setPostProcessed(true);
            }
            if (bean instanceof DummyFactory) {
                ((DummyFactory) bean).setPostProcessed(true);
            }
            return bean;
        }

        @Override
        public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
            return bean;
        }
    });
    this.factory.addBeanPostProcessor(new LifecycleBean.PostProcessor());
    this.factory.addBeanPostProcessor(new ProtectedLifecycleBean.PostProcessor());
// this.factory.preInstantiateSingletons();
}
Also used : PropertyValues(cn.taketoday.beans.PropertyValues) HashMap(java.util.HashMap) InitializationBeanPostProcessor(cn.taketoday.beans.factory.InitializationBeanPostProcessor) ClassPathResource(cn.taketoday.core.io.ClassPathResource) DummyFactory(cn.taketoday.beans.testfixture.beans.factory.DummyFactory) TestBean(cn.taketoday.beans.testfixture.beans.TestBean) ITestBean(cn.taketoday.beans.testfixture.beans.ITestBean) RootBeanDefinition(cn.taketoday.beans.factory.support.RootBeanDefinition) LifecycleBean(cn.taketoday.beans.testfixture.beans.LifecycleBean) StandardBeanFactory(cn.taketoday.beans.factory.support.StandardBeanFactory) HashMap(java.util.HashMap) Map(java.util.Map) BeansException(cn.taketoday.beans.BeansException) BeforeEach(org.junit.jupiter.api.BeforeEach)

Example 5 with BeansException

use of cn.taketoday.beans.BeansException in project today-framework by TAKETODAY.

the class ConstructorResolver method createArgumentArray.

/**
 * Create an array of arguments to invoke a constructor or factory method,
 * given the resolved constructor argument values.
 */
private ArgumentsHolder createArgumentArray(String beanName, RootBeanDefinition merged, @Nullable ConstructorArgumentValues resolvedValues, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable, BeanWrapper wrapper, boolean autowiring, boolean fallback) throws UnsatisfiedDependencyException {
    TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
    TypeConverter converter = customConverter != null ? customConverter : wrapper;
    ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
    HashSet<ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
    LinkedHashSet<String> autowiredBeanNames = new LinkedHashSet<>(4);
    for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
        Class<?> paramType = paramTypes[paramIndex];
        String paramName = paramNames != null ? paramNames[paramIndex] : "";
        // Try to find matching constructor argument value, either indexed or generic.
        ValueHolder valueHolder = null;
        if (resolvedValues != null) {
            valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
            // it could match after type conversion (for example, String -> int).
            if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
                valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
            }
        }
        if (valueHolder != null) {
            // We found a potential match - let's give it a try.
            // Do not consider the same value definition multiple times!
            usedValueHolders.add(valueHolder);
            Object originalValue = valueHolder.getValue();
            Object convertedValue;
            if (valueHolder.isConverted()) {
                convertedValue = valueHolder.getConvertedValue();
                args.preparedArguments[paramIndex] = convertedValue;
            } else {
                MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
                try {
                    convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
                } catch (TypeMismatchException ex) {
                    throw new UnsatisfiedDependencyException(merged.getResourceDescription(), beanName, new InjectionPoint(methodParam), "Could not convert argument value of type [" + ObjectUtils.nullSafeClassName(valueHolder.getValue()) + "] to required type [" + paramType.getName() + "]: " + ex.getMessage());
                }
                Object sourceHolder = valueHolder.getSource();
                if (sourceHolder instanceof ValueHolder) {
                    Object sourceValue = ((ValueHolder) sourceHolder).getValue();
                    args.resolveNecessary = true;
                    args.preparedArguments[paramIndex] = sourceValue;
                }
            }
            args.arguments[paramIndex] = convertedValue;
            args.rawArguments[paramIndex] = originalValue;
        } else {
            MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
            // have to fail creating an argument array for the given constructor.
            if (!autowiring) {
                throw new UnsatisfiedDependencyException(merged.getResourceDescription(), beanName, new InjectionPoint(methodParam), "Ambiguous argument values for parameter of type [" + paramType.getName() + "] - did you specify the correct bean references as arguments?");
            }
            try {
                Object autowiredArgument = resolveAutowiredArgument(methodParam, beanName, autowiredBeanNames, converter, fallback);
                args.resolveNecessary = true;
                args.arguments[paramIndex] = autowiredArgument;
                args.rawArguments[paramIndex] = autowiredArgument;
                args.preparedArguments[paramIndex] = autowiredArgumentMarker;
            } catch (BeansException ex) {
                throw new UnsatisfiedDependencyException(merged.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
            }
        }
    }
    for (String autowiredBeanName : autowiredBeanNames) {
        beanFactory.registerDependentBean(autowiredBeanName, beanName);
        if (log.isDebugEnabled()) {
            log.debug("Autowiring by type from bean name '{}' via {} to bean named '{}'", beanName, (executable instanceof Constructor ? "constructor" : "factory method"), autowiredBeanName);
        }
    }
    return args;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) InjectionPoint(cn.taketoday.beans.factory.InjectionPoint) Constructor(java.lang.reflect.Constructor) TypeMismatchException(cn.taketoday.beans.TypeMismatchException) ValueHolder(cn.taketoday.beans.factory.config.ConstructorArgumentValues.ValueHolder) InjectionPoint(cn.taketoday.beans.factory.InjectionPoint) TypeConverter(cn.taketoday.beans.TypeConverter) UnsatisfiedDependencyException(cn.taketoday.beans.factory.UnsatisfiedDependencyException) MethodParameter(cn.taketoday.core.MethodParameter) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) BeansException(cn.taketoday.beans.BeansException)

Aggregations

BeansException (cn.taketoday.beans.BeansException)11 PropertyValues (cn.taketoday.beans.PropertyValues)4 BeanFactory (cn.taketoday.beans.factory.BeanFactory)4 Nullable (cn.taketoday.lang.Nullable)4 PlatformTransactionManager (cn.taketoday.transaction.PlatformTransactionManager)4 TypeConverter (cn.taketoday.beans.TypeConverter)3 TypeMismatchException (cn.taketoday.beans.TypeMismatchException)3 InjectionPoint (cn.taketoday.beans.factory.InjectionPoint)3 UnsatisfiedDependencyException (cn.taketoday.beans.factory.UnsatisfiedDependencyException)3 ValueHolder (cn.taketoday.beans.factory.config.ConstructorArgumentValues.ValueHolder)3 MethodParameter (cn.taketoday.core.MethodParameter)3 Constructor (java.lang.reflect.Constructor)3 HashSet (java.util.HashSet)3 LinkedHashSet (java.util.LinkedHashSet)3 BeanWrapper (cn.taketoday.beans.BeanWrapper)2 InitializationBeanPostProcessor (cn.taketoday.beans.factory.InitializationBeanPostProcessor)2 RootBeanDefinition (cn.taketoday.beans.factory.support.RootBeanDefinition)2 StandardBeanFactory (cn.taketoday.beans.factory.support.StandardBeanFactory)2 ITestBean (cn.taketoday.beans.testfixture.beans.ITestBean)2 LifecycleBean (cn.taketoday.beans.testfixture.beans.LifecycleBean)2