spring-cloud-consul: Spring Config Client + Consul Discovery First Bootstrap - Encountering `Binder has not been registered` error when accessing `/actuator/refresh`
Hi All,
I am encountering the below error upon calling /actuator/refresh on Config Client using Discovery First Bootstrap approach with Consul.
Using Spring Boot v2.4.1 with Spring Cloud Config Dependencies v3.0.1
2021-02-07 11:42:11.759 INFO 22516 --- [nio-8082-exec-1] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://192.168.0.147:8800/
2021-02-07 11:42:12.654 INFO 22516 --- [nio-8082-exec-1] c.c.c.ConfigServicePropertySourceLocator : Located environment: name=common, service-b, profiles=[dev], label=null, version=f505ce9985c13881051c59bec644ef490a6c5d15, state=null
2021-02-07 11:42:12.655 INFO 22516 --- [nio-8082-exec-1] b.c.PropertySourceBootstrapConfiguration : Located property source: [BootstrapPropertySource {name='bootstrapProperties-configClient'}, BootstrapPropertySource {name='bootstrapProperties-https://github.com/2much2learn/article_2021_jan_spring-cloud-config-configfirst_discoveryfirst/Config resource 'file [C:\Users\narra\AppData\Local\Temp\config-repo-5281483341513251368\git-config-store\service-b.yaml' via location 'git-config-store/' (document spring-cloud/spring-cloud-config#1)'}, BootstrapPropertySource {name='bootstrapProperties-https://github.com/2much2learn/article_2021_jan_spring-cloud-config-configfirst_discoveryfirst/Config resource 'file [C:\Users\narra\AppData\Local\Temp\config-repo-5281483341513251368\git-config-store\service-b.yaml' via location 'git-config-store/' (document #0)'}, BootstrapPropertySource {name='bootstrapProperties-https://github.com/2much2learn/article_2021_jan_spring-cloud-config-configfirst_discoveryfirst/file:C:\Users\narra\AppData\Local\Temp\config-repo-5281483341513251368\git-config-store\common.yaml'}]
2021-02-07 11:42:12.699 ERROR 22516 --- [nio-8082-exec-1] o.s.boot.SpringApplication : Application run failed
java.lang.IllegalStateException: org.springframework.boot.context.properties.bind.Binder has not been registered
at org.springframework.boot.DefaultBootstrapContext.lambda$get$1(DefaultBootstrapContext.java:88) ~[spring-boot-2.4.1.jar!/:2.4.1]
at org.springframework.boot.DefaultBootstrapContext.getOrElseThrow(DefaultBootstrapContext.java:109) ~[spring-boot-2.4.1.jar!/:2.4.1]
at org.springframework.boot.DefaultBootstrapContext.get(DefaultBootstrapContext.java:88) ~[spring-boot-2.4.1.jar!/:2.4.1]
at org.springframework.cloud.consul.discovery.configclient.ConsulConfigServerBootstrapper.lambda$intitialize$3(ConsulConfigServerBootstrapper.java:54) ~[spring-cloud-consul-discovery-3.0.0.jar!/:3.0.0]
at org.springframework.boot.DefaultBootstrapContext.getInstance(DefaultBootstrapContext.java:119) ~[spring-boot-2.4.1.jar!/:2.4.1]
at org.springframework.boot.DefaultBootstrapContext.getOrElseThrow(DefaultBootstrapContext.java:111) ~[spring-boot-2.4.1.jar!/:2.4.1]
at org.springframework.boot.DefaultBootstrapContext.get(DefaultBootstrapContext.java:88) ~[spring-boot-2.4.1.jar!/:2.4.1]
at org.springframework.cloud.consul.discovery.configclient.ConsulConfigServerBootstrapper.lambda$intitialize$4(ConsulConfigServerBootstrapper.java:67) ~[spring-cloud-consul-discovery-3.0.0.jar!/:3.0.0
I tried the same with Config First Bootstrap approach and can see /actuator/refresh working as expected by reloading the configs from config-server
Sample Code is available in git repo - https://github.com/2much2learn/article_2021_jan_spring-cloud-config-configfirst_discoveryfirst
Run the below series of commands to replicate the issue
-- Run Consul Container
$ docker run -d --name consul-server -p 8500:8500 -e CONSUL_BIND_INTERFACE=eth0 consul
-- Clone and build the packages
$ git clone https://github.com/2much2learn/article_2021_jan_spring-cloud-config-configfirst_discoveryfirst.git
$ cd article_2021_jan_spring-cloud-config-configfirst_discoveryfirst
$ cd spring-multi-module-cloud-config-consul-discovery
$ mvn clean package
-- Start config-server
$ java -jar -Dspring.profiles.active=git config-server\target\config-server-0.0.1-SNAPSHOT.jar
-- Start spring boot service
$ java -jar service-b\target\service-b-0.0.1-SNAPSHOT.jar
-- Access service endpoint
$ curl http://localhost:8082/greeting
-- refresh service to reload configs
$ curl -H "Content-Type: application/json" -d {} http://localhost:8082/actuator/refresh
Any help would be appriciated.
Thanks, Madan N
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 16 (3 by maintainers)
@spencergibb thanks for fixing this.
Thanks @pcoates33. This works for us.
The problem occurs when you use actuator/refresh and have both of the following dependencies
The bootstrap starter means that refresh will be performed by org.springframework.cloud.context.refresh.LegacyContextRefresher this runs a SpringApplication with a reduced set of listeners
The consul discovery adds org.springframework.cloud.consul.discovery.configclient.ConsulConfigServerBootstrapper to the SpringApplication run bootstrap process. This adds the closeListener for the bootstrapContext close event which throws the exception when no Binder is present.
On application start, the Binder is added by org.springframework.boot.context.config.ConfigDataEnvironment, which is called from ConfigDataEnvironmentPostProcessor, which is called from EnvironmentPostProcessorApplicationListener.
However, on a refresh, the LegacyContextRefresher does not add the EnvironmentPostProcessorApplicationListener, which means no Binder is registered. So, the “Binder has not been registered” exception occurs when the close listener in ConsulConfigServerBootstrapper is called.
Adding the EnvironmentPostProcessorApplicationListener to LegacyContextRefresher makes the refresh work OK.
@royremi I did, but I’ve already removed it.