Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring changing the properties file in runtime

I'm using Spring Boot and I have a properties file p.properties:

p1 = some val1
p2 = some val2

Configuration class:

@Configuration
@PropertySource("classpath:p.properties")
public class myProperties {

    public myProperties () {
        super();
    }

    @Bean
    public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

And I'm using this in order to access the property:

@Value("${p1}")
private String mProperty;

Everything works great. I want to change p1 in p.properties file from outside of the app and the next time that I'll use mProperty, it will contains the new value without restarting the app. Is it possible?

Thanks, Avi

like image 340
Avi Elgal Avatar asked Apr 23 '18 09:04

Avi Elgal


People also ask

Do we need to restart server after changing properties file?

I'm afraid that is not possible. The main reason you can't do this is because many of the components have a special lifecycle , so even if you change the values in properties file you would need to stop and start the respective components so all the previous resources are released and new ones acquired.

How do I refresh application properties in spring boot?

For Reloading properties, spring cloud has introduced @RefreshScope annotation which can be used for refreshing beans. Spring Actuator provides different endpoints for health, metrics. but spring cloud will add extra end point /refresh to reload all the properties.

Can we update application properties in spring boot?

You can do something like reading the properties file using FileInputStream into a Properties object. Then you will be able to update the properties.


3 Answers

You can simply use spring boot actuator. Just add the actuator dependency in your maven/gradle config and you should be seeing live reloads when you update the property file.

Note: You won't have to restart the app but actuator will do live reloads on its own.

like image 150
Shanu Gupta Avatar answered Oct 16 '22 13:10

Shanu Gupta


If you want to change the properties at runtime and don't want to restart the server then follow the below steps:

  1. Application.properties

    app.name= xyz

    management.endpoints.web.exposure.include=*

  2. Add below dependencies in pom.xml

    org.springframework.boot spring-boot-starter-actuator org.springframework.cloud spring-cloud-context 2.0.1.RELEASE

    3)Place application.properties in config folder . The config folder must be in the location from where you will run the jar.

  3. Add ApplcationProperties.java

    @RefreshScope @Component @ConfigurationProperties(prefix = "app") public class ApplcationProperties { private String name; //getter and setter }

  4. Write ApplicationController.java and inject ApplcationProperties

    @Autowired ApplcationProperties applcationProperties;

    @RestController public Class ApplicationController { @GetMapping("/find") String getValue() { return applicationProperties.getName(); } }

  5. Run the spring boot application

  6. Call localhost:XXXX/find from your browser

    Output : xyz

  7. Change the value in application.properties from xyz to abc

  8. Using postman send a put /options request to localhost:XXXX/actuator/refresh --Note this request should be either PUT/OPTIONS

  9. Call localhost:XXXX/find from your browser

    Output : abc

like image 21
Umesh Sanwal Avatar answered Oct 16 '22 11:10

Umesh Sanwal


I think, in this case, it is advisable to keep it in the database so that, it can be changed & accessed seamlessly. We have a similar scenario where we keep the encrypted password for database in the properties file. While connecting to db, it needs to be decrypted. We do that by extending PropertyPlaceholderConfigurer as follows.

public class MyPropertyConfigurer extends PropertyPlaceholderConfigurer{
  protected void convertProperties(Properties props){
        Enumeration<?> propertyNames = props.propertyNames();
        while (propertyNames.hasMoreElements()) {
            String propertyName = (String) propertyNames.nextElement();
            String propertyValue = props.getProperty(propertyName);
            if(propertyName.indexOf("db.password") != -1){
                decryptAndSetPropValue(props,propertyName,propertyValue);
            }
        }
    }
}

But, this is done only once while loading the properties file.

like image 25
amdg Avatar answered Oct 16 '22 13:10

amdg