Autowired Environment is null
Asked Answered
B

5

59

I have an issue with connecting environment to my Spring project. In this class

@Configuration
@ComponentScan(basePackages = "my.pack.offer.*")
@PropertySource("classpath:OfferService.properties")
public class PropertiesUtil {
    @Autowired
    private Environment environment;



    @Bean
    public String load(String propertyName)
    {
        return environment.getRequiredProperty(propertyName);
    }
}

environment always is null.

Belicia answered 17/10, 2013 at 7:53 Comment(5)
Try to use @Resource instead of @Autowired. See if that helps.Sprage
@PauliusMatulionis, Nope, nothing changedBelicia
@Belicia Is it the only code you have in the PropertiesUtil ? Do you have a PropertySourcesPlaceholderConfigurer or something like that ?Portland
And how are you using this PropertyUtil...Harv
Using @Autowired Environment and @Bean PropertyPlaceholderConfigurer in same java-based configuration results to environment == null. Implementing EnvironmentAware interface solved this problem. I don`t know if it is a bug. (Spring 4.2.2)Malik
A
42

Autowiring happens later than load() is called (for some reason).

A workaround is to implement EnvironmentAware and rely on Spring calling setEnvironment() method:

@Configuration
@ComponentScan(basePackages = "my.pack.offer.*")
@PropertySource("classpath:OfferService.properties")
public class PropertiesUtil implements EnvironmentAware {
    private Environment environment;

    @Override
    public void setEnvironment(final Environment environment) {
        this.environment = environment;
    }

    @Bean
    public String load(String propertyName)
    {
        return environment.getRequiredProperty(propertyName);
    }
}
Annulet answered 6/1, 2015 at 15:8 Comment(1)
In a test environment with Groovy and Spock, Spring is somehow unable to inject the environment no matter how I annotated it (Autowires, Inject, Resource). Implementing EnvironmentAware as suggested by Alex was the only was to get this working.Pox
M
16

Change @Autowired for @Resource (from javax.annotation) and make it public e.g.:

@Configuration
@PropertySource("classpath:database.properties")
public class HibernateConfigurer {

    @Resource
    public Environment env;

    @Bean
    public DataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(env.getProperty("database.driverClassName"));
        dataSource.setUrl(env.getProperty("database.url"));
        dataSource.setUsername(env.getProperty("database.username"));
        dataSource.setPassword(env.getProperty("database.password"));
        dataSource.setValidationQuery(env.getProperty("database.validationQuery"));

        return dataSource;
    }
}

And you must register your configurer class in WebApplicationInitializer this way

AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(ApplicationConfigurer.class); //ApplicationConfigurer imports HibernateConfigurer

It's working for me! You may want to check a test project I made.

Metathesis answered 29/7, 2014 at 17:42 Comment(1)
I had to move the @PropertySource from my test to my configuration class..Gave
P
5

I solved the same problem with constructor injection:

@Configuration
@PropertySource("classpath:my.properties")
public class MyConfig {
    private Environment environment;

    public MyConfig(Environment environment) {
        this.environment = environment
    }

    @Bean
    public MyBean myBean() {
        return new MyBean(environment.getRequiredProperty("srv.name"))
    }
}

later, I simplified it to this form (to make properties injected properly):

@Configuration
@PropertySource("classpath:my.properties")
public class MyConfig {
    private String serviceName;

    public MyConfig(Environment ignored) {
        /* No-op */
    }

    @Value("${srv.name}")
    public void setServiceName(String serviceName) {
        this.serviceName = serviceName;
    }

    @Bean
    public MyBean myBean() {
        return new MyBean(requireNonNull(serviceName)); // NPE without environment in constructor
    }
}
Prone answered 15/9, 2020 at 17:26 Comment(0)
U
1

Clean and easy: It also can be called in @PostConstruct method:

@Autowired
private Environment env;

private String appPropertyValue;

@PostConstruct
private void postConstruct() {
    this.appPropertyValue = env.getProperty("myProperty");
}
Urena answered 16/5, 2022 at 21:9 Comment(0)
M
0

Please put this code inside the class where you are trying to autowire the Environment

@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
}

It solved my issue. Below I give you my class.

@Configuration
@EnableTransactionManagement
public class DatabaseConfig {   
/**
 * DataSource definition for database connection. Settings are read from the
 * application.properties file (using the env object).
 */
@Bean
public DataSource dataSource() {

    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(env.getProperty("db.driver"));
    dataSource.setUrl(env.getProperty("db.url"));
    dataSource.setUsername(env.getProperty("db.username"));
    dataSource.setPassword(env.getProperty("db.password"));
    return dataSource;
}

@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
}

  @Autowired
  private Environment env;

}
Misdemeanor answered 20/9, 2017 at 11:0 Comment(1)
no, this doesn't resolve the issue at allLadle

© 2022 - 2024 — McMap. All rights reserved.