Spring: Config Server
For a spring application to do it’s work, it typically needs some configurations. These configurations would get saved on to the config server.
Config server
This is a separate independent application.
It needs the following dependency.
implementation 'org.springframework.cloud:spring-cloud-config-server'Config server acts as a facade for a directory managed by Git that holds all the configuration data.
- Github
- Gitlab
- Local file system
Anything that is Git based can be used to hold the config data, and can be managed through the config server.
EnableConfigServer
The source code that was downloaded from start.spring.io would have the Application class. This class needs to be annotated with @EnableConfigServer
@EnableConfigServer
@SpringBootApplication
public class ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
}
}Config data
Once the @EnableConfigServer annotation has been provided, the next logical step is to configure the config server. That is, the config server needs to be told where to look to see the configuration data of the applications this config server is going to manage the configuration data for.
This would be specified in the standard application.properties file in the confg-server application codebase.
spring.application.name=config
spring.cloud.config.server.git.uri=${HOME}/code/configdata
server.port=8888How the clients would interact with the config server
Now, we need to look at the source code of the client project.
Specifically, we have to specify in the application.properties of the project to import config from the config server we just initialized.
spring.application.name=adoptions
spring.config.import=configserver:Note that the port is not mentioned because config server by default is assumed to run on port 8888 and that is where the config server is running.
Accesssing configs from the config server from the browser
To access the configuration data from the config server, go to the following URL.
http://localhost:8888/service/defaultResponse as below
{
"name": "service",
"profiles": [
"default"
],
"label": null,
"version": "f96b8b7df3152acd9754ac70ff5bcaad98d8f6c6",
"state": "",
"propertySources": [
{
"name": "/Users/cinish/code/configdata2/application.properties",
"source": {
"info.foo": "barchanged"
}
}
]
}Making changes to the configuration data
Inorder to see the config data changes reflected, I had gone to the application.properties and had made additional property entries. None of these reflected in the response.
- Restarting the config service did not help
- Clean, rebuild, restart the config service did not help
- Using actuator to force a refresh of config did not help
curl -X POST http://localhost:8888/actuator/refresh
That is when I realized that the whole thing in Git based, and so the changed need to be checked in.
Once the changes were checked in, the property changes got reflected right away.
{
"name": "service",
"profiles": [
"default"
],
"label": null,
"version": "cc8492ab88f8e736e3b611f478cf63ee3145f43b",
"state": "",
"propertySources": [
{
"name": "/Users/cinish/code/configdata2/application.properties",
"source": {
"info.foo": "barchanged",
"newprop.one": "valueone",
"newprop.two": "valuetwo"
}
}
]
}Seeing these properties from a service that is a client to the config service
A service by name abc would have access to the properties defined in abc.properties , and a fallback in the properties defined in application.properties that is available to all the services that rely on the config service.
Get Learn’s stories in your inbox
Join Medium for free to get updates from this writer.
URL to access the properties from the client service
The <service name> gets embedded in the URL
http://localhost:8888/adoptions/defaultOn printing the configuration data for the adoptions service, following content gets displayed.
{
"name": "adoptions",
"profiles": [
"default"
],
"label": null,
"version": "d7901b1df62a29272e35eba7c26522b96804f363",
"state": "",
"propertySources": [
{
"name": "/Users/cinish/code/configdata2/adoptions.properties",
"source": {
"adoptions.info.foo": "barchanged",
"adoptions.newprop.one": "valueone",
"adoptions.newprop.two": "valuetwo"
}
},
{
"name": "/Users/cinish/code/configdata2/application.properties",
"source": {
"info.foo": "barchanged",
"newprop.one": "valueone",
"newprop.two": "valuetwo"
}
}
]
}Note that there are two sections
service specific properties
{
"name": "/Users/cinish/code/configdata2/adoptions.properties",
"source": {
"adoptions.info.foo": "barchanged",
"adoptions.newprop.one": "valueone",
"adoptions.newprop.two": "valuetwo"
}
}common properties from application.properties
{
"name": "/Users/cinish/code/configdata2/application.properties",
"source": {
"info.foo": "barchanged",
"newprop.one": "valueone",
"newprop.two": "valuetwo"
}
}Isolating properties between services
When service one looks up the config using localhost:8888/serviceone/default , only the content from application.properties and serviceone.properties are displayed.
Similarly, when service two looks up the config using localhost:8888/servicetwo/default , only the content from application.properties and servicetwo.properties are displayed.
http://localhost:8888/servicetwo/defaultOutput
{
"name": "servicetwo",
"profiles": [
"default"
],
"label": null,
"version": "38803aac1be75200dd3eff98810c816ecf5ffe6d",
"state": "",
"propertySources": [
{
"name": "/Users/cinish/code/configdata2/servicetwo.properties",
"source": {
"servicetwo.info.foo": "barchanged",
"servicetwo.newprop.one": "valueone",
"servicetwo.newprop.two": "valuetwo"
}
},
{
"name": "/Users/cinish/code/configdata2/application.properties",
"source": {
"info.foo": "barchanged",
"newprop.one": "valueone",
"newprop.two": "valuetwo"
}
}
]
}For service one,
http://localhost:8888/serviceone/defaultthe output is
{
"name": "serviceone",
"profiles": [
"default"
],
"label": null,
"version": "38803aac1be75200dd3eff98810c816ecf5ffe6d",
"state": "",
"propertySources": [
{
"name": "/Users/cinish/code/configdata2/application.properties",
"source": {
"info.foo": "barchanged",
"newprop.one": "valueone",
"newprop.two": "valuetwo"
}
}
]
}Note that it only has the application.properties. This is because, there is no configuration data for a service named serviceone . We do have configuration data against the service adoptions . Let us see the data for that service.
http://localhost:8888/adoptions/defaultThe data is as below
{
"name": "adoptions",
"profiles": [
"default"
],
"label": null,
"version": "38803aac1be75200dd3eff98810c816ecf5ffe6d",
"state": "",
"propertySources": [
{
"name": "/Users/cinish/code/configdata2/adoptions.properties",
"source": {
"adoptions.info.foo": "barchanged",
"adoptions.newprop.one": "valueone",
"adoptions.newprop.two": "valuetwo"
}
},
{
"name": "/Users/cinish/code/configdata2/application.properties",
"source": {
"info.foo": "barchanged",
"newprop.one": "valueone",
"newprop.two": "valuetwo"
}
}
]
}





