Spring Cloud Config client doesn't get values from server - spring

I have been following this tutorial from Baeldung in setting up a Spring Cloud Config server and client. I believe I have set up the server correctly since going to http://localhost:8888/service-config/development/master will seemingly correctly show the json with the user.role defined:
{"name":"service-config","profiles":["development"],"label":"master","version":"d30a6015a6b8cb1925f6e61cee22721f331e5783","state":null,"propertySources":[{"name":"file:///C:.../git/service-config-data/service-config-development.properties","source":{"user.role":"Developer"}},{"name":"file:///C:.../git/service-config-data/service-config.properties","source":{"user.role":"Developer"}}]}
However, I cannot seem to correctly connect the Spring Cloud Config client to the server - the client fails to run with cannot resolve placeholder errors on the #Value("${user.role}") annotation. I've tried adding a default value to the annotation and then manually refreshing the values (using the #refreshscope annotation), but to no avail.
I've looked at the debug and trace logs by running the tools with --debug --trace flags but I cannot find when/if the client is making the call to the server and which config-data .properties file the server is actually looking for. I am a bit lost on how to proceed.
Here is my server application.properties:
spring.application.name=service-config
server.port=8888
spring.cloud.config.server.git.uri=file:///${user.home}/git/service-config-data
spring.cloud.config.server.git.clone-on-start=false
spring.security.user.name=root
spring.security.user.password=toor
And inside the service-config-data folder, there are files with this inside:
user.role=Developer
I have tried files called service-config.properties, service-config-client.properties, service-config-development.properties, and service-config-client-development.properties, and none of them seem to pull through the user.role.
Here is my client:
#SpringBootApplication
#RestController
#RefreshScope
public class ServiceConfigClient {
#Value("${user.role:unknown}")
private String role;
#RequestMapping(
value = "/whoami/{username}",
method = RequestMethod.GET,
produces = MediaType.TEXT_PLAIN_VALUE)
public String whoami(#PathVariable("username") String username) {
return String.format("Hello! You're %s and you'll become a(n) %s...\n", username, role);
}
}
And my client bootstrap.properties:
spring.application.name=service-config-client
spring.profiles.active=development
spring.cloud.config.uri=http://localhost:8888
spring.cloud.config.username=root
spring.cloud.config.password=toor
management.endpoints.web.exposure.include=*
How do I correctly connect the client to the server so that it can successfully pull the config data? Thank you.

My problem was fixed by adding spring.cloud.config.name=service-config to the bootstrap.properties of the service-config-client as well as adding spring-cloud-config-client to and removing spring-cloud-config-server from my pom.xml

There is confusion about client service name and corresponding property sources in config server.
You need to do one of the following:
Change client service name:
//client bootstrap.properties
spring.application.name=service-config
Change folder name in git repo from service-config to service-config-client

Related

Spring Cloud Config Client with #RefreshScope not applying

I have a config server and client up and running by means of Spring Cloud. However I am not able to dynamically update the properties on my #Component
#Component
#ConfigurationProperties("threads-config")
#RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
internal class ThreadConfig {
var numThreads = 1
var pollInterval = 1
}
My application.properties look like the following:
spring.application.name=my-backend
spring.config.import =optional:configserver:hhtp://localhost:8888
management.endpoints.web.exposure.include=*
You need to create a properties file or yml file with you clint app name to be able to refresh configuration files.
For example, if your client application has name test-client like
spring.application.name=test-client
Then you need to create a configuration file with the same name. test-client or test-client.yml

How to consume spring cloud config server Jdbc backend configs from Spring cloud Client server?

I went through lots of tutorials regarding this but could not get this done.
Here is my table structure for this.
Application Profile Label prop_key value
masking dev latest test-property message
I have a cloud config server which should integrate with JDBC backend. Here is my application.properties in config server
server.port=8082
spring.application.name=masking
management.endpoints.web.exposure.include=*
spring.datasource.url=jdbc:postgresql://localhost:8000/finos?currentSchema=xlabs
spring.datasource.username=mufgdev
spring.datasource.password=XXX
spring.profiles.active=XXX
spring.cloud.config.server.jdbc.sql=SELECT prop_key,value from xlabs.properties where application=? and profile=? and label=?
spring.cloud.config.server.jdbc.order=1
With this configs if I enter http://localhost:8082/masking/dev/latest response will show the results as I want.
I want to consume properties in client side with the following configs in bootstrap.properties
spring.application.name=masking
spring.cloud.config.uri=http://localhost:8082
spring.cloud.config.label=latest
spring.cloud.config.profile=dev
And in my client side
#RestController
#RefreshScope
public class TestController {
#Value("${test-property}")
private String aConf;
#GetMapping("/message")
String message() {
String name =aConf ;
return name;
}
}
This gives java.lang.IllegalArgumentException: Could not resolve placeholder 'test-property' in value "${test-property}"
Can anyone comment on this?
Thanks.
This issue comes with the latest Spring boot release, All the above code segments steps all okay, But by default Spring has disabled bootstrap. So you have to enable them by adding
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
No need add for older versions of the Spring boot projects.

ZooKeeper latest value is not reloaded without restarting server

I am using ZooKeeper with spring boot. And In application.properties file I am using below properties as shown below.
minio.url=${minio.connection-string}
minio.access.key=${minio.accesskey}
where minio.connection-string and minio.accesskey value will be came from ZooKeeper znode data. I am using minio.url and minio.access.key in other Spring boot bean as shown below.
#Configuration
#RefreshScope
public class MinioClientConf
{
#Value("${minio.url}")
private String minioUrl;
#Value("${minio.access.key}")
private String minioKey;
.
.
When I start my spring boot application then all stuff works but when I change ZooKeeper node value then it is not reflecting in bean value without re-starting server.
My problem is that I want to reload latest zookeeper value without re-starting server. I have also tried with refresh scope annotation but it didn't work.
Instead of that use #ConfigurationProperties
#ConfigurationProperties("minio")
public class MinioClientConf
{
private String minioUrl;
private String minioKey;
.
.
For more details click here

Why spring client cannot obtain spring config server properties?

I've got a #SpringBootApplication, running with the production profile, and a spring config server,
{"name":"config-client","profiles":["production"],"label":null,"version":"97611975e6ddb87c7213e18ddbe203ab6ae5485d","state":null,"propertySources":[{"name":"http://git/scm/abm/abm-settings.git/application-production.yml","source":{"my.pretty.property.id":21}}]}
I cannot load property my.pretty.property.id from server (they are always null), I am using
#Getter
#Setter
#Component
#ConfigurationProperties(prefix = "my.pretty.property")
public class MyProperties {
private String id;
}
and my bootstrap.yml is
spring.cloud:
config:
uri: http://${SERVICE_HOST}/${PROJECT_KEY}-config-server
enabled: false
failFast: true
build.gradle contains this:
"org.springframework.cloud:spring-cloud-starter-consul-all",
"org.springframework.cloud:spring-cloud-consul-core",
"org.springframework.cloud:spring-cloud-starter-hystrix",
"org.springframework.cloud:spring-cloud-starter-hystrix-dashboard",
"org.springframework.cloud:spring-cloud-starter-zipkin",
"org.springframework.cloud:spring-cloud-config-client"
My client application is normally built and deployed, what am I missing?
From Spring Cloud Config:
The HTTP service has resources in the form:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
As you mentioned your application is running under production profile - hence Spring will try to find file: <cloud-config-server-url>/application-production.yml and load it, besides application.properties. But your properties are located in application-integration.yml and you don't use integration profile.
So the solution is to use an integration profile or to create an application-production.yml on your config. server.
The following config is right, but spring.cloud.config.enabled should be true, I didn't overrride it in my production environment

Unable to get /refresh to work with spring-cloud-client when server.port and management.port are different

Below is the application.properties for a spring-boot application
spring.application.name=test-service
server.port=8080
management.port=8081
management.context-path=/admin
spring.cloud.config.uri=http://localhost:8888
endpoints.refresh.enabled=true
endpoints.restart.enabled=true
When I start the application, it contacts the config-server and loads the properties as expected.
I modify the properties on the config server and trigger a refresh on the application using
curl -X POST http://localhost:8081/admin/refresh
the API prints the name of the property that was changed.
When I do a get on the property, I still see the old value
curl -X GET http://localhost:8081/admin/env/{property_name}
I trigger a restart and it picks up the the new property value
curl -X POST http://localhost:8081/admin/restart
See the same behavior when I try to change the property value using
curl -X POST http://localhost:8081/admin/env -d property1=123
When I try to get the property value I still see the old value
curl -X GET http://localhost:8081/admin/env/property1
When I change the management.port to 8080 (the same as the server.port) everything works as expected.
Is this behavior expected? Looks to me that it is modifying 2 different environments one for the server running on 8080 and the other running on 8081.
Could you please share your pom.xml and application main(Entry) file.No matter we can use different port. If you are able to get the changed properties in "/refresh" call then it should work in your application also. Are you sure you are using #RefreshScope in your bean?
Note : #RefreshScope will not work on #Configuration annotation.for further details please follow the documentation https://cloud.spring.io/spring-cloud-config/spring-cloud-config.html.
Looks to be an issue with spring-boot.
EnvironmentEndpoint and EnvironmentMVCEndpoint are injected with 2 different Environments when the server.port and management.port are different.
The application environment has the updated value but when I get the value of a specific property EnviromentMVCEndpoint it does not reflect the right value in its Environment
#GetMapping(value = "/{name:.*}", produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
#HypermediaDisabled
public Object value(#PathVariable String name) {
if (!getDelegate().isEnabled()) {
// Shouldn't happen - MVC endpoint shouldn't be registered when delegate's
// disabled
return getDisabledResponse();
}
return new NamePatternEnvironmentFilter(this.environment).getResults(name);
}
#Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}

Resources