19

I would like to use a value from application.properties file in order to pass it in the method in another class. The problem is that the value returns always NULL. What could be the problem? Thanks in advance.

application.properties

filesystem.directory=temp

FileSystem.java

@Value("${filesystem.directory}")
private static String directory;
Jonathan Williams
  • 237
  • 1
  • 4
  • 12

6 Answers6

31

You can't use @Value on static variables. You'll have to either mark it as non static or have a look here at a way to inject values into static variables:

https://www.mkyong.com/spring/spring-inject-a-value-into-static-variables/

EDIT: Just in case the link breaks in the future. You can do this by making a non static setter for your static variable:

@Component
public class MyComponent {

    private static String directory;

    @Value("${filesystem.directory}")
    public void setDirectory(String value) {
        this.directory = value;
    }
}

The class needs to be a Spring bean though or else it won't be instantiated and the setter will be not be accessible by Spring.

Plog
  • 9,164
  • 5
  • 41
  • 66
  • 1
    Thanks for the answer, but it still prints null value. – Jonathan Williams Sep 04 '17 at 08:14
  • @JonathanWilliams is the member variable in a Spring bean? The `@Value` annotation only works on Spring beans, not on arbitrary other Java classes. – Jesper Sep 04 '17 at 08:15
  • I made some edits. Is your class a Spring bean? i.e. is it annotated with @Component? – Plog Sep 04 '17 at 08:15
  • Yes, exactly, it is annotated with @Component. – Jonathan Williams Sep 04 '17 at 08:16
  • 1
    this should not be available here? static vaiables aren't related to this because they are a Singleton used by every instance of this class. MyComponent.directory=value should work – FishingIsLife Dec 27 '18 at 08:36
  • @medTech this is available because the setDirectory method is non static so you can still reference the static variable using this as the reference point. You could of course replace this with MyComponent.directory if you wanted though. – Plog Jan 02 '19 at 11:33
15

For the ones still facing the issue after all the preceding suggestions, make sure you are not accessing that variable before the bean has been constructed.

That is:

Instead of doing this:

@Component
public MyBean {
   @Value("${properties.my-var}")
   private String myVar;

   private String anotherVar = foo(myVar); // <-- myVar here is still null!!!
}

do this:

@Component
public MyBean {
   @Value("${properties.my-var}")
   private String myVar;

   private String anotherVar;

   @PostConstruct  
   public void postConstruct(){

      anotherVar = foo(myVar); // <-- using myVar after the bean construction
   }
}

Hope this will help someone avoid wasting hours.

Philippe Simo
  • 1,353
  • 1
  • 15
  • 28
  • 3
    This was the solution for me. I had been using the properties within a constructor. So I moved the init stuff into a @PostConstruct and initialized them there. – cbmeeks Jul 15 '20 at 15:22
  • Finally an answer that makes sense. Works as explained – Dave Oct 28 '20 at 20:18
  • oh my gosh this was the answer! ty – notacorn Mar 02 '22 at 00:08
  • This helped me finally and defienately saved hours of Googling! Thank you so much! very essential thing when using Auth tokens. – Guy_g23 Dec 19 '22 at 12:12
7

Few things for you to cross check apart from @Plog's answer.

static variables can't be injected with value. Check @Plog's answer.

  • Make sure the class is annotated with @Component or @Service
  • The component scan should scan the enclosing package for registering the beans. Check your XML if xml enabled configuration.
  • Check if the property file's path is correct or in classpath.
Karthik R
  • 5,523
  • 2
  • 18
  • 30
7

The other answers are probably correct for the OP.

However, I ran into the same symptoms (@Value-annotated fields being null) but with a different underlying issue:

import com.google.api.client.util.Value;

Ensure that you are importing the correct @Value annotation class! Especially with the convenience of IDEs nowadays, this is a VERY easy mistake to make (I am using IntelliJ, and if you auto-import too quickly without reading WHAT you are auto-importing, you might waste a few hours like I did).

Of course, the correct class to import is:

import org.springframework.beans.factory.annotation.Value;

scottysseus
  • 1,922
  • 3
  • 25
  • 50
1

Spring uses dependency injection to populate the specific value when it finds the @Value annotation. However, instead of handing the value to the instance variable, it's handed to the implicit setter instead. This setter then handles the population of our NAME_STATIC value.

    @RestController 
//or if you want to declare some specific use of the properties file then use
//@Configuration
//@PropertySource({"classpath:application-${youeEnvironment}.properties"})
public class PropertyController {

    @Value("${name}")//not necessary
    private String name;//not necessary

    private static String NAME_STATIC;

    @Value("${name}")
    public void setNameStatic(String name){
        PropertyController.NAME_STATIC = name;
    }
}
-3

You can make use of this. reference to assess the value of (private String myVar)

this.myVar