javaspringspring-boot

Spring boot application.properties not working


I'm having trouble getting spring boot (3.4.1) to read some parameters from a properties file. I was trying to use the default mechanism, naming my file application.properties and putting it in the resources folder. But since I couldn't get it to work, I decided to go the way of externalizing the properties file. So my code looks like this:

@PropertySource("file:/home/user/myapp/myapp.properties")
@SpringBootApplication
public class MyApplication {
    public static void main(String... args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

This seems to be correct because, if I delete (or rename) the myapp.properties file, when I try to initialize the application, it generates an error: APPLICATION FAILED TO START Config data resource 'file [/home/user/myapp/myapp.properties]' via location 'file:///home/user/myapp/myapp.properties' does not exist

So, assuming that spring is able to find the file, I configured my component to read a parameter like this:

@RestController
public class MyAppController {

    @Value("${staticRepo}")
    private String staticRepo;

    @GetMapping(value = "/api/myapp")
    List<Foo> getFoo() {
        if (staticRepo== null || staticRepo.trim().isEmpty()) {
            throw new InternalServerErrorException("MyApp is not configured properlly. Missing 'staticRepo' parameter in 'myapp.properties'");
        }
        return FooUtils.load(staticRepo);
    }

I double checked the myapp.properties and it does have a staticRepo parameter (the file contains only 1 line: staticRepo=/home/user/myapp/repo/)

I found several posts with the same problem, but none solved my issue. From one of those posts, I tried to specify the properties file into the command line as follows, but without luck...

java -jar /home/user/myapp/myapp.jar --spring.config.location=file:///home/user/myapp/myapp.properties

So my question is: what am i doing wrong?

EDIT

As suggested, I renamed the variable to repo and it still didn't work and I also verified the the @Value annotation. I'm using org.springframework.beans.factory.annotation.Value.

And no, it isn't a dumbed down version. Yes, I changed the path and renamed the app, but the application is just what I posted. To be sure, using the VS Code (v1.96.2) wizard (Spring Initializr Java Support v0.11.2) I generated a new application from scratch. The wizard itself created an application.properties file and placed it into /src/main/resources with the property spring.application.name=demo. And yes, it prints null to the System.out... So probably my setup is messed up... By the way, it is an Ubuntu 24.04.2 LTS with openjdk 21.0.6.

@SpringBootApplication
public class DemoApplication {

    @Value("${spring.application.name}")
    private String name;

    public static void main(String[] args) {
        DemoApplication demo = new DemoApplication();
        System.out.println(demo.getName());

        SpringApplication.run(DemoApplication.class, args);
    }

    public String getName() {
        return name;
    }
}

Solution

  • This:

    DemoApplication demo = new DemoApplication();
    System.out.println(demo.getName());
    

    does NOT start a Spring application, nor does it autowire any dependencies or inject configuration values into the object instance.

    The call that initializes the application context is:

    SpringApplication.run(DemoApplication.class, args);
    

    And if you do that and let Spring manage your beans, you will see that the config properties are properly picked up.

    Here's a minimal, fully working example:

    @SpringBootApplication
    public class DemoApplication {
    
        private final String name;
    
        public DemoApplication(@Value("${spring.application.name}") final String name) {
          this.name = name;
    
          System.out.println("name=" + name);
        }
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    
        public String getName() {
            return name;
        }
    }
    

    (It's generally a good idea to favor constructor injection of dependencies and values, unless there's a very good reason not to do so)