1

I'm writing a Spring Boot application and am trying to load some values from a properties file using the @Value annotation. However, the variables with this annotation remain null even though I believe they should get a value.

The files are located in src/main/resources/custom.propertes and src/main/java/MyClass.java.

(I have removed parts of the code that I believe are irrelevant from the snippets below)

MyClass.java

@Component
@PropertySource("classpath:custom.properties")
public class MyClass {
    @Value("${my.property:default}")
    private String myProperty;

    public MyClass() {
        System.out.println(myProperty); // throws NullPointerException
    }
}

custom.properties

my.property=hello, world!

What should I do to ensure I can read the values from my property file?

Thanks!

Cas
  • 758
  • 14
  • 36
  • 5
    How are you getting an instance of `MyClass`? If you're instantiating it yourself with `new MyClass()` then this is not going to work. It needs to be a bean managed by Spring; you have to look it up in the Spring context, or autowire the instance at the place you are using it. Similar to this: [Why is my Spring @Autowired field null?](https://stackoverflow.com/questions/19896870/why-is-my-spring-autowired-field-null) – Jesper Jul 05 '19 at 11:41
  • 4
    @value will be invoked after the object is created. Since you are using the property inside the constructor hence it is not available. – dassum Jul 05 '19 at 11:43
  • Is custom.properties file under main/resources folder ? – Dmitri Algazin Jul 05 '19 at 11:44
  • @dassum Please post your comment as answer. Thank you – Simon Martinelli Jul 05 '19 at 11:45

2 Answers2

10

@value will be invoked after the object is created. Since you are using the property inside the constructor hence it is not available.

You should be using constructor injection anyway. It makes testing your class easier.

public MyClass(@Value("${my.property:default}") String myProperty) {
    System.out.println(myProperty); // doesn't throw NullPointerException
}
Michael
  • 41,989
  • 11
  • 82
  • 128
dassum
  • 4,727
  • 2
  • 25
  • 38
1

You are getting this error because you are initializing the class with new keyword. To solve this, first you need to create the configuration class and under this class you need to create the bean of this class. When you will call it by using bean then it will work..

My code:

        @Component
        @PropertySource("db.properties")
        public class ConnectionFactory {
            @Value("${jdbc.user}")
            private String user;
            @Value("${jdbc.password}")
            private String password;
            @Value("${jdbc.url}")
            private String url;
            Connection connection;

            @Bean
            public String init(){

                return ("the value is: "+user);
            }

        My Config.class:

        @Configuration
        @ComponentScan
        public class Config {

            @Bean
            public Testing testing() {
                return new Testing();
            }

            @Bean
            public ConnectionFactory connectionFactory() {
                return new ConnectionFactory();
            }
        }

        Calling it:

        public static void main(String[] args) {
                AnnotationConfigApplicationContext context= new AnnotationConfigApplicationContext(Config.class);
                ConnectionFactory connectionFactory= context.getBean(ConnectionFactory.class);
                System.out.println(connectionFactory.init());
            }








        



        


        
Maninder
  • 1,539
  • 1
  • 10
  • 12