How to assign a value from application.properties to a static variable?

Viewed 146899

I am using Spring MVC. I have a UserService class annotated with @Service that has a lot of static variables. I would like to instantiate them with values from the application.properties file.

For example in application.properties I have: SVN_URL = http://some.url/repositories

Then in the class there is: @Value("${SVN_URL}") private static String SVN_URL

I get the Instantiation of bean failed; nested exception is java.lang.ExceptionInInitializerError

I have also tried @Autowired private static Environment env;

And then: private static String SVN_URL=env.getProperty("SVN_URL");

It gives the same error.

6 Answers

Accessing application.properties in static member functions is not allowed but here is a work around,

application.properties

server.ip = 127.0.0.1

PropertiesExtractor.java

public class PropertiesExtractor {
     private static Properties properties;
     static {
        properties = new Properties();
        URL url = new PropertiesExtractor().getClass().getClassLoader().getResource("application.properties");
        try{
            properties.load(new FileInputStream(url.getPath()));
           } catch (FileNotFoundException e) {
                e.printStackTrace();
           }
        }

        public static String getProperty(String key){
            return properties.getProperty(key);
        }
}

Main.class

public class Main {
    private static PropertiesExtractor propertiesExtractor;
    static{
         try {
             propertiesExtractor = new PropertiesExtractor();
         } catch (UnknownHostException e) {
               e.printStackTrace();
           }
    }

    public static getServerIP(){
        System.out.println(propertiesExtractor.getProperty("server.ip")
    }
}
static String profile;

@Value("${spring.profiles.active:Unknown}")
private void activeProfile(String newprofile) {
    profile = newprofile;
};

In order to gain static access to Spring Boot properties you can create a Properties Holder Component which implements the Command Line Runner interface. The command line runner interface executes run() upon component instantiation by Spring Boot.

Since we have autowired access to our properties object in the PropertiesHolder component, it is possible to assign the autowired properties to a static Properties class variable upon CommandLineRunner execution of the run() method.

At this point any class can statically call PropertiesHolder.getProperties() to access the contents of Spring Boot properties values.

PropertiesHolder.class:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class PropertiesHolder implements CommandLineRunner {

    //Spring Boot Autowired Properties Object
    @Autowired MyProperties myAutowiredProperties;

    //Statically assigned Properties Object
    private static MyProperties properties;

    //Hide constructor (optional)
    private PropertiesHolder(){}

    public static MyProperties getProperties() throws NullPointerException{
        if(PropertiesHolder.properties == null)
            throw new NullPointerException("Properites have not been initialized by Spring Application before call.");

        return PropertiesHolder.properties;
    }

    //Use to assign autowired properties to statically allocated properties
    public static void makeAvailable(MyProperties myAutowiredProperties){
        PropertiesHolder.properties = myAutowiredProperties;
    }

    //Spring Boot command line runner autoexecuted upon component creation
    //which initializes the static properties access
    public void run(String... args) {
        PropertiesHolder.makeAvailable(myAutowiredProperties);
    }
}

MyProperties.class

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

//Example: your_properties_file_prefix.properties 
@ConfigurationProperties(prefix = "YOUR_PROPERTIES_FILE_PREFIX") 
@Component
@Data
public class MyProperties {

    private String property1;
    private String property2;
    private String property3;
}

At least one more simple solution with configuration file:

@Configuration
public class YourStaticPropertyConfiuration {
  public static String PROPERTY_NAME;

  @Value("${propertyName}")
  public void setProperty(final String propertyName) {
    PROPERTY_NAME = propertyName;
  }
}

Use PROPERTY_NAME anywhere as static variable

Related