Home > Back-end >  how to populate the environment before component scanning takes place
how to populate the environment before component scanning takes place

Time:07-23

I am desperately attempting to populate the Environment with properties necessary to resolve bean properties in one of the scanned in components. What follows is a simple demonstration of two failed attempts to populate the environment.

This is the class whose bean property fails to get resolved during construction of the application context.

package com.enterprise.samples.email;

import ...

@Component
public class EmailBean {

    @Value("mail.retry.count")
    private int retryCount;

    public int getRetryCount() {
        return retryCount;
    }
}

This is the java configuration class.

package com.enterprise.samples.configuration;

import ...

@Configuration
@PropertySource(value="classpath:aux.properties")
@ComponentScan(basePackages={ "com.enterprise.samples.email" })
public class Conf {

    @Autowired
    private ConfigurableEnvironment env;

    // failed attempt #1
    @PostConstruct
    public void after() {
        final MutablePropertySources mutablePropertySources = env.getPropertySources();
        final HashMap<String, Object> emailProperties = new HashMap<>();
        emailProperties.put("mail.retry.count", 3);

        final MapPropertySource emailPropertiesSource =
                new MapPropertySource("emailProperties", emailProperties);

        mutablePropertySources.addFirst(emailPropertiesSource);
    }

    // failed attempt #2
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {

        final HashMap<String, Object> emailProperties = new HashMap<>();
        emailProperties.put("mail.retry.count", 3);

        final MapPropertySource emailPropertiesSource =
                new MapPropertySource("emailProperties", emailProperties);
        final MutablePropertySources mutablePropertySources = new MutablePropertySources();
        mutablePropertySources.addFirst(emailPropertiesSource);

        final PropertySourcesPlaceholderConfigurer result = new PropertySourcesPlaceholderConfigurer();
        result.setPropertySources(mutablePropertySources);

        return result;
    }
}

Finally, this is the test class.

package com.enterprise.samples.tests;

import ...

public class BeanPropertyResolutionTest {

    @Test
    public void test() {

        final AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Conf.class);

        try {
            final EmailBean emailBean = applicationContext.getBean(EmailBean.class, "emailBean");
            Assert.assertEquals(3, emailBean.getRetryCount());
        } finally {
            applicationContext.close();
        }
    }
}

The following exception results:

WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'emailBean': Unsatisfied dependency expressed through field 'retryCount'; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'int'; nested exception is java.lang.NumberFormatException: For input string: "mail.retry.count"

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'emailBean': Unsatisfied dependency expressed through field 'retryCount'; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'int'; nested exception is java.lang.NumberFormatException: For input string: "mail.retry.count"

Can anyone tell me what I am doing incorrectly?

CodePudding user response:

I assume your problem is here: @Value("mail.retry.count"). You almost got it right. You should've written this @Value("${mail.retry.count}"). And you don't need those attempt#1 and attempt#2.

  • Related