user672009
user672009

Reputation: 4585

Properties and env always null

I have a hard time loading properties from my properties file. I'm trying to load a property into my configuration class which is listed below.

package dk.fitfit.budget.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.Environment;


@Configuration
@PropertySource("classpath:application.properties")
public class ApplicationConfig {
    private static final Logger logger = LoggerFactory.getLogger(ApplicationConfig.class);

    @Autowired
    private Environment env;

    @Value("${snot:test}")
    private String snot;

    public ApplicationConfig() {
        logger.info("Application config loaded!");  // Displays as expected
        logger.info("snot: {}", snot);              // snot: null
        logger.info("env: {}", env);                // env: null
    }

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

}

If I change the name of the file (application.properties) or "@PropertySource("classpath:application.properties")" I get an error about the file not being present. So clearly it's being loaded (to some extend anyway).

I was at least expecting to see the default string "test" injected into the variable snot. But not even that is done. I'm not able to autowire Environment either... not sure if there is a relation.

The content of my application.properties is as below.

snot=snog

My application.properties file is placed in src/main/resources/.

Anyone got a clue about what I'm doing wrong?

Upvotes: 4

Views: 6915

Answers (2)

Spring (and all dependency-injection tools) can't inject fields before the instance is created with new, which is one reason why constructor injection should be preferred to field injection. Generally, you can use @Value on constructor parameters, but there are certain issues with @Configuration classes that make constructor injection impractical.

However, there's a solution meant for exactly this situation: @PostConstruct. This method will be called after the DI framework has done all its magic to the bean:

@PostConstruct
public void log() {
    logger.info("Application config loaded!");  // Displays as expected
    logger.info("snot: {}", snot);              // snot: null
    logger.info("env: {}", env);                // env: null
}

Upvotes: 4

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279950

The purpose of a constructor is to initialize a class instance. You have to construct and initialize the class instance before Spring can do anything to it. As such, you cannot expect the env and snot fields to have anything other than the default null value within the constructor.

Upvotes: 5

Related Questions