I have a problem with the refreshing of a ConfigurationProperties object. The Properties includes a Map<String, MyObject>
object. My problem is that when I remove from the configuration one entry of this map, the map in the Properties object still includes this entry. I guess my issue could be similar like #183.
I prepared a sample project for you. https://github.com/tommyziegler/spring-cloud-prototype.
You can clone the project and follow my sample and see my issue.
Sample
Clone the sample repo
$ git clone https://github.com/tommyziegler/spring-cloud-prototype.git
$ cd spring-cloud-prototype
Start the Server with 2 Rel's and see the Rel's in the interface
Following two Rels 'rel1' and 'rel2' are in the config file "config-server/config-server.yml" defined. - config-server/config-server.yml
com:
tommyziegler:
server01: http://localhost:8083
cloud-server:
links:
rel1:
href: ${com.tommyziegler.server01}/rel1
method: GET
rel2:
href: ${com.tommyziegler.server01}/rel2
method: GET
# rel3:
# href: ${com.tommyziegler.server01}/rel3
# method: GET
Start the Server
$ mvn spring-boot:run
Curl the RootRestInterface
$ curl http://localhost:8080/rest
{
"links" : [ {
"rel" : "rel1",
"href" : "http://localhost:8083/rel1",
"method" : "GET"
}, {
"rel" : "rel2",
"href" : "http://localhost:8083/rel2",
"method" : "GET"
} ]
}
Enable the 3rd Rel, refresh the Properties to see the Rel's in the interface
Extend one Rel 'rel3' in the config file "config-server/config-server.yml" defined. - config-server/config-server.yml
com:
tommyziegler:
server01: http://localhost:8083
cloud-server:
links:
rel1:
href: ${com.tommyziegler.server01}/rel1
method: GET
rel2:
href: ${com.tommyziegler.server01}/rel2
method: GET
rel3:
href: ${com.tommyziegler.server01}/rel3
method: GET
Commit the 3rd Rel into the local Git repo for Spring-Cloud.
$ git commit config-server/config-server.yml -m "Activate 3rd rel"
Refresh the Scope to reload the changed configuration file.
$ curl -X POST http://localhost:8080/actuator-endpoint/refresh
Curl the RootRestInterface
$ curl http://localhost:8080/rest
{
"links" : [ {
"rel" : "rel1",
"href" : "http://localhost:8083/rel1",
"method" : "GET"
}, {
"rel" : "rel2",
"href" : "http://localhost:8083/rel2",
"method" : "GET"
}, {
"rel" : "rel3",
"href" : "http://localhost:8083/rel3",
"method" : "GET"
} ]
}
Deactivate the 3rd Rel, refresh the Properties to see the Rel's in the interface
Deactivate the 3rd Rel 'rel3' in the config file "config-server/config-server.yml" which we defined in the previous step. - config-server/config-server.yml
com:
tommyziegler:
server01: http://localhost:8083
cloud-server:
links:
rel1:
href: ${com.tommyziegler.server01}/rel1
method: GET
rel2:
href: ${com.tommyziegler.server01}/rel2
method: GET
#rel3:
#href: ${com.tommyziegler.server01}/rel3
#method: GET
Commit the deactivation of the 3rd Rel into the local Git repo for Spring-Cloud.
$ git commit config-server/config-server.yml -m "Deactivate 3rd rel"
Refresh the Scope to reload the changed configuration file.
$ curl -X POST http://localhost:8080/actuator-endpoint/refresh
Curl the RootRestInterface
$ curl http://localhost:8080/rest
{
"links" : [ {
"rel" : "rel1",
"href" : "http://localhost:8083/rel1",
"method" : "GET"
}, {
"rel" : "rel2",
"href" : "http://localhost:8083/rel2",
"method" : "GET"
}, {
"rel" : "rel3",
"href" : "http://localhost:8083/rel3",
"method" : "GET"
} ]
}
Doesn't look for me like expected.
Conclusion / Question
After deactivating the 3rd Rel my interface still returns it. Is that like expected!? Do I still need maybe an annotation to build up the whole PropertiesObject? Is that even a Spring-Cloud problem, or more an ConfigurationProperties issue?
I would appreciate if you could give some hint how I could solve this issue, as we would like to take such an service online, where we can specify which Rel's on an RootRest Interface are included via a Git Repository.
Thx a lot
Tommy
Comment From: dsyer
Your problem is that your @ConfgurationProperties
bean is not in @RefreshScope
. You can put it in the right scope by explicitly marking it as a @Component
instead of using @EnableConfigurationProperties
to define the bean.
P.S. you don't need a config server to test it. Just the app and some local config files.
Comment From: abhisheksarkar30
I too faced this same issue. Here is the solution that worked for me:
- Keep the variable name as linksConfig(which is different than the java binding variable i.e. links) along with it's getter.
- Create just a setter of links(not linksConfig by the above variable name) with body :
public void setLinks(Map<String, HrefAndMethod> links) {
this.linksConfig = links;
}
Alternative simpler solution: 1. Considering your variable name is 'links', you need to keep the setter name as 'setLinks' ofcourse, but don't keep the getter name as 'getLinks'. Keep some other name for getter like 'getLinksConfig' which you'll use internally in your code.
Let me know if you still face an issue.