Kosz
Kosz

Reputation: 169

Trouble configuring SpringBootApplication to read from properties

I'm struggling to load my configuration in my simple SpringBootApplication. When I attempt to print out the variables in my configuratrion class, they are always null.

Initially I had my configurable variables in WatchApplication.java. However, all of the variables I thought would be read from configuration were still null. The configuration was at /main/resources/application.properties. I've since added a class just to hold the configuration that I plan to read in WatchApplication called WatchConfiguration.

I'm new to Spring and am feeling terminally stupid

The Structure of my classes is:

-main
   |--java
   |   |--WatchApplication.java
   |   |--WatchConfiguration.java
   |
   |--resources
       |--application.properties 

Here's WatchApplication.java

@SpringBootApplication
public class WatchApplication {

    private WatchConfiguration configuration;

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

    /**
     * Initialize the application
     */
    @PostConstruct
    public void initialize()
    {
        configuration = new WatchConfiguration();
        System.out.println(configuration.getVideoDirectory());
    }
}

Here is what my WatchConfiguration.java looks like

@Configuration
public class WatchConfiguration {
    @Value("${video.output.directory}")
    private String videoDirectory;

    @Value("${target.sites}")
    private List<String> targetSites;

    public WatchConfiguration getWatchConfiguration ()
    {
        return new WatchConfiguration();
    }

    public String getVideoDirectory() {
        return videoDirectory;
    }

    public void setVideoDirectory(String videoDirectory) {
        this.videoDirectory = videoDirectory;
    }

    public List<String> getTargetSites() {
        return targetSites;
    }

    public void setTargetSites(List<String> targetSites) {
        this.targetSites = targetSites;
    }
}

And my application.properties

video.output.directory = C:\\Users\\Alex\\Desktop\\output

# Target Sites
target.sites[0] = https://youtube.com
target.sites[1] = https://bing.com

Here is the output. Note the 'null' in the console that is supposed to be the video.output.directory property value.

[2019-09-04 20:09:00.752] - 16812 INFO [restartedMain] --- com.pirate.baywatch.BaywatchApplication: Starting BaywatchApplication on DESKTOP-ULP9VBQ with PID 16812 (C:\Users\Alex\IdeaProjects\baywatch\target\classes started by Alex in C:\Users\Alex\IdeaProjects\baywatch)
[2019-09-04 20:09:00.765] - 16812 INFO [restartedMain] --- com.pirate.baywatch.BaywatchApplication: No active profile set, falling back to default profiles: default
[2019-09-04 20:09:00.792] - 16812 INFO [restartedMain] --- org.springframework.boot.devtools.env.DevToolsPropertyDefaultsPostProcessor: Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
null
[2019-09-04 20:09:01.142] - 16812 WARNING [restartedMain] --- org.springframework.context.annotation.AnnotationConfigApplicationContext: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'baywatchConfiguration': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'target.sites' in value "${target.sites}"
[2019-09-04 20:09:01.148] - 16812 INFO [restartedMain] --- org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener: 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
[2019-09-04 20:09:01.154] - 16812 SEVERE [restartedMain] --- org.springframework.boot.SpringApplication: Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'baywatchConfiguration': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'target.sites' in value "${target.sites}"
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:380)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1411)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:845)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:743)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:390)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1214)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1203)
    at com.pirate.baywatch.BaywatchApplication.main(BaywatchApplication.java:16)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'target.sites' in value "${target.sites}"
    at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:178)
    at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:124)
    at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:237)
    at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:211)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:175)
    at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:851)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1192)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1171)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
    ... 21 more

Solution Solved by adding @Autowired to the member variable and removing the initialization of the configuration class from the initialize method

@SpringBootApplication
public class WatchApplication {

    @Autowired
    private WatchConfiguration configuration;

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

    /**
     * Initialize the application
     */
    @PostConstruct
    public void initialize()
    {
        System.out.println(configuration.getVideoDirectory());
    }
}

Upvotes: 0

Views: 244

Answers (1)

Alexander.Furer
Alexander.Furer

Reputation: 1869

The problem is that you are creating configuration by yourself, with new. You should @Autowired it from context in to your application class.

Remove this line configuration = new Watch Configuration and add @Autowired to definition of configuration. I would also suggest you to use configuration properties instead.

Upvotes: 2

Related Questions