1. Introduction
In real world applications, most often the requirement is to change the configuration properties. New changes can be committed to the Git repository supporting the Config service. In our earlier tutorial, we discussed how to read configuration properties from GitHub. Whenever properties are changed in Git, Spring Cloud Config Server can read the updated values. But the client can not read the updated values.
In a typical Spring Boot application, modifying a property will require a restart. Restarting the client applications will work but it is not a viable solution. There can be several clients, to get the latest configuration values we’ll need to restart the client applications. We can agree that restarting the applications is not a good approach.
Spring Cloud Config introduces the capability to dynamically refresh the configuration in client applications during runtime.
An approach to refresh configurations at runtime is to send a POST request to a running instance of microservice. This request will initiate the reloading of the modified configuration data, enabling a hot reload of the application. In this tutorial, we’ll discuss this approach.
In this tutorial, we’ll discuss the steps to refresh configurations at runtime using refresh actuator.
2. Step 1: Add actuator dependency in the Config client services
Add Spring Boot Actuator dependency spring-boot-starter-actuator
in the pom.xml
of the individual microservice. This will expose the /refresh
endpoint.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
3. Step 2: Enable /refresh endpoint
The Spring Boot Actuator provides a management endpoint /actuator/refresh
that can trigger a refresh event. By default this event is not exposed. You need to explicitly enable this endpoint in your configuration file.
In our earlier example, we’ll add the management
endpoint setting.
management: endpoints: web: exposure: include: "*"
Note, here we have used ‘*’ to expose all endpoints. You can specify the individual endpoints also.
Here is an example of application.yml
:
spring: application: name: service1 profiles: active: prod config: import: "optional:configserver:http://localhost:8085?fail-fast=true&max-attempts=10&max-interval=1500&multiplier=1.2&initial-interval=1100" management: endpoints: web: exposure: include: "*"
4. Step 3: Test your changes
To test your changes, commit a new change in the Git. In our case, we’ll change in the service1-prod.yaml
file and commit in Git.
build: version: 1.1 service1: message: Service1 application message - Production environment contactDetails: name: "John" email: "John@gmail.com" phoneNumbers: - 123456 - 678901
To reload the updated properties, call the /refresh
endpoint.
POST http://localhost:8080/actuator/refresh
Now, you can validate by logging the properties in the individual microservice. The microservice should have the updated properties. We have created a class AppProperties
to map the configuration properties.
import java.util.List; import java.util.Map; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @Configuration @ConfigurationProperties(prefix = "service1") public class AppProperties { private String message; private Map<String, String> contactDetails; private List<String> phoneNumbers; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public Map<String, String> getContactDetails() { return contactDetails; } public void setContactDetails(Map<String, String> contactDetails) { this.contactDetails = contactDetails; } public List<String> getPhoneNumbers() { return phoneNumbers; } public void setPhoneNumbers(List<String> phoneNumbers) { this.phoneNumbers = phoneNumbers; } }
5. Drawback of using /refresh
The limitation of this approach is evident. We have to manually hit the /refresh
endpoint for each individual microservice in order to refresh the configuration properties for each microservice. There is a better way to do this using Spring Cloud Bus. In the upcoming tutorial, we’ll discuss this approach.
6. Conclusion
In this tutorial, we’ve explored how to refresh configurations at runtime using the Spring Boot Actuator’s /refresh
endpoint. By leveraging this capability, we can dynamically update our application’s configuration properties without requiring a restart, ensuring greater flexibility and responsiveness to changes in the environment. This approach is particularly useful in cloud-native applications where configurations may frequently change due to scaling, dynamic infrastructure, or external system updates.
By following the steps outlined, you’ve learned how to:
- Enable the Spring Boot Actuator in your project.
- Securely expose the
/refresh
endpoint. - Update your configuration properties dynamically at runtime.
This method enhances the manageability and robustness of your applications, allowing for smoother operations and quicker adaptation to changing requirements. Remember to handle the refresh process with care, especially in production environments, to avoid unintended disruptions.