Spring Boot - Environment @Autowired throws NullPointerException

imme picture imme · Oct 18, 2013 · Viewed 57.6k times · Source

I have a project setup using Spring Boot 0.5.0.M5.

In one of the configuration files I am trying to @Autowire Environment but that fails with a NullPointerException.

Here's what I have so far:

Application.java

@EnableAutoConfiguration
@Configuration
@ComponentScan
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

JpaConfig.java where I am trying to @Autowire Environment

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.ui.persistence.repository")
public class JpaConfig {
    private static final String DATABASE_DRIVER = "db.driver";
    private static final String DATABASE_PASSWORD = "db.password";
    private static final String DATABASE_URL = "db.url";
    private static final String DATABASE_USERNAME = "db.username";
    private static final String HIBERNATE_DIALECT = "hibernate.dialect";
    private static final String HIBERNATE_SHOW_SQL = "hibernate.show_sql";
    private static final String ENTITYMANAGER_PACKAGES_TO_SCAN 
        = "entitymanager.packages.to.scan";

    @Autowired
    private Environment env;

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty(DATABASE_DRIVER));
        dataSource.setUrl(env.getProperty(DATABASE_URL));
        dataSource.setUsername(env.getProperty(DATABASE_USERNAME));
        dataSource.setPassword(env.getProperty(DATABASE_PASSWORD));
        return dataSource;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean 
                = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setDataSource(dataSource());
        entityManagerFactoryBean.setPersistenceProviderClass(
                HibernatePersistence.class);
        entityManagerFactoryBean.setPackagesToScan(
                env.getProperty(ENTITYMANAGER_PACKAGES_TO_SCAN));
        entityManagerFactoryBean.setJpaProperties(hibernateProperties());
        return entityManagerFactoryBean;
    }
}

I am trying to load the database properties configured in a properties file. However, the Environment is not injected and the code fails with NullPointerException. I do not have any configuration in XML files.

For the properties file I have configured PropertySourcesPlaceholderConfigurer this way:

@Configuration
@PropertySource("classpath:database.properties")
public class PropertyConfig {
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

I have tried swapping @Autowired, @Resource and @Inject but nothing has worked so far. Would appreciate any help. Thanks.

Answer

Alex Shesterov picture Alex Shesterov · Jan 6, 2015

Though your specific problem is solved, here's how to get Environment in case Spring's autowiring happens too late.

The trick is to implement org.springframework.context.EnvironmentAware; Spring then passes environment to setEnvironment() method. This works since Spring 3.1.

An example:

@Configuration
@PropertySource("classpath:myProperties.properties")
public class MyConfiguration implements EnvironmentAware {

    private Environment environment;

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

    public void myMethod() {
        final String myPropertyValue = environment.getProperty("myProperty");
        // ...
    }

}

This is not as elegant as @Autowired or @Value, but it works as workaround in some situations.