Is there anyway to use configure-server with servlet context path when register on service discovery? - spring

I have a service-discovery which register all the services. I have configure-server which maintain all the configuration. configure-server already register in service-discovery. I know by default configure-server will register with id: configserver. I know how to change the id. But when I tried to use servlet.context.path= /config all the configure-client can not pull from configure-sever through service-discovery look like can not use /config in configure-server.
configure-server:
server:
port: 0
servlet:
context-path: /config
spring:
application:
name: configserver
cloud:
config:
server:
git:
uri: https://github.com/PheaSoy/spring-completed-microservice
search-paths: config/{application}
discovery:
enabled: true
configure-client
spring:
application:
name: song-service
cloud:
config:
uri: http://configserver/config
discovery:
enabled: true
Even I added context path /path configure-client always fetched without context path.
ConfigServicePropertySourceLocator : Fetching config from server at : http://192.168.1.34:57945/
Is there any way to configure configure-client with available configure-server context path through service-discovery?

The discovery client implementations all support some kind of metadata map (for example, we have eureka.instance.metadataMap for Eureka). Some additional properties of the Config Server may need to be configured in its service registration metadata so that clients can connect correctly. If the Config Server is secured with HTTP Basic, you can configure the credentials as user and password. Also, if the Config Server has a context path, you can set configPath. For example, the following YAML file is for a Config Server that is a Eureka client:
bootstrap.yml.
eureka:
instance:
...
metadataMap:
configPath: /config
Reference:
Spring Cloud Config with Eureka - contextPath
Discovery with bootstrap

Yes, you can define your context path for your configuration server as you have done.
But doing so, you also need to take into account the alignments you need to do.
Eureka. By default will call your management API. For example, http://BASE_URI/actuator/health. But since you are adding a context path "config", it means it should be now: http://BASE_URI/config/actuator/health. You can correct following the suggestion above on eureka.instance...metadataMap.configPath: /config
Configuration Clients. In your application (client to the config server), you can add the context path in spring.cloud.config.uri. For example, if it was "http://BASE_URI", then it should be updated as "http://BASE_URI/config" now since you added a context path.
Please try and see if it helps.

Related

spring bean override with custom implementation

I want to override a spring implantation and use my own bean. For example CompositeEnvironmentRepository which is a spring bean, i want to write my own. One way is to delete this bean from the spring jar file and provide my own jar file with my custom bean. Is there any better way to do this. Please suggest.
spring:
application:
name: spring-cloud-server
profiles:
active: vault,git
cloud:
vault:
authentication: CERT
config:
server:
failOnCompositeError: false
vault:
host: hostname
port: 490
scheme: https
backend: secret
defaultKey:
kvVersion: 2
order: 2
skipSslValidation: false
authentication: CERT
git:
uri: repo-url
order: 1
skip-ssl-validation: false
force-pull: true
repos:
dev:
pattern:
- '*/dev'
uri: url
searchPaths: '${somepath}'
The documentation describes how to provide your own environment repository. You probably don't want to override the entire CompositeEnvironmentRepository, but create your own EnvironmentRepository that provides the specific properties you need. Spring will include yours as part of the "composite".
https://cloud.spring.io/spring-cloud-config/multi/multi__spring_cloud_config_server.html#_custom_composite_environment_repositories

Profile based Spring Cloud Config Server client with optional local developer properties

My Goal:
Having the Spring Cloud Config Server import active and provide a way for developers to have an optional property file on their machine.
My Config Server is up and running using org.springframework.cloud:spring-cloud-config-server:3.1.3 and #EnableConfigServer on the main class. Http requests to the concrete endpoint yield the expected result. This server should provide important environment configurations for a developer for his/her local setup.
$ curl http://localhost:8888/test-application/dev
{"name":"test-application","profiles":["dev"],"label":null,"version":null,"state":null,"propertySources":[{"name":"classpath:/cfg/test-application/application-dev.yml","source":{"server.port":1111}},{"name":"classpath:/cfg/test-application/application.yml","source":{"server.port":8000}}]}
Where localhost:8888 is my Config Server and test-application ist the name of the client application (defined via spring.application.name). The provided dev is the currently active profile on the client (The dev profile indicates a locally running software, there is no dev environment).
Clients configuration:
application.yml
spring:
application:
name: test-application
config:
import:
- configserver:http://localhost:8888 # <- pull the configuration from the configserver
- optional:file:/absolute/path/to/the/project/root/ # <- if there are any additional configuration files, use them
The client uses the following dependencies:
org.springframework.boot:spring-boot-starter-web:2.7.0
org.springframework.cloud:spring-cloud-starter-bootstrap:3.1.3
org.springframework.cloud:spring-cloud-starter:3.1.3
org.springframework.cloud:spring-cloud-starter-config:3.1.3
As shown above, the "base" application.yml configured server.port=8000 where the profile specific is set to server.port=1111. When reading the documentation this behaviour is correct. But my local developer configuration contains server.port=2222. This was ignored.
Here comes the problem:
When starting the client application, i can see the following log statements:
Fetching config from server at : http://localhost:8888
Located environment: name=test-application, profiles=[default], label=null, version=null, state=null
Located property source: [BootstrapPropertySource {name='bootstrapProperties-configClient'}, BootstrapPropertySource {name='bootstrapProperties-classpath:/cfg/test-application/application-dev.yml'}, BootstrapPropertySource {name='bootstrapProperties-classpath:/cfg/test-application/application.yml'}]
The following 1 profile is active: "dev"
Tomcat initialized with port(s): 1111 (http)
Initializing Spring embedded WebApplicationContext
Tomcat started on port(s): 1111 (http) with context path ''
Started TestApplicationKt in 2.234 seconds (JVM running for 2.762)
The configuration evaluation result from spring was to choose port 1111 instead of the wanted 2222 within the application-dev.yml located in the project root (developer config).
Wrapped up:
Three config files:
config server application.yml (port: 8000)
config server application-dev.yml (port: 1111)
project root developer config application-dev.yml (port: 2222) <- I want this file to have precedence over the other two.
When running the debugger, i see these found property sources within the injected Environment bean. The wanted developer file is within this list and the property source content is correct (server.port=2222).
Does anyone have an idea how to solve this problem?
I have created a project that reproduces this exact behaviour. Link to GitHub.
Thanks in advance!
Is the dev profile active when application is running in dev environment or it's also active when running locally?
Ideally you should have 2 different profiles for dev and local and you can enable config server only when dev profile is active.
You can rename your local property file as application-local.yml and disable spring cloud config when profile local is active.
You can put below code in bootstrap.yml(create new file beside application.yml) and remove config server configurations from application.yml
---
spring:
application:
name: test-application
config:
activate:
on-profile: dev
import:
- configserver:http://localhost:8888 # <- pull the configuration from the configserver
- optional:file:/absolute/path/to/the/project/root/ # <- if there are any additional configuration files, use them
---
spring:
application:
name: test-application
config:
activate:
on-profile: local
cloud:
config:
enabled: false
EDIT: Actual fix
Thanks for sharing reproducible example.
All you need to do is remove local application-dev.yml location reference from client application.yml and add it to configServer application.yml as shown in belolow screenshots.
/client/src/main/resources/application.yml
And put it in configServer application.yml at the end of search-locations. Order matters so please make sure you put overriding location/s at the end.
/configServer/src/main/resources/application.yml
Build and start both the applications and you will see client application server started on port 2222

Read values from consul while bootstrap spring boot

I have question is there any way to retrieve certain values and inject them to bootstrap.yml while application is coming up.
I have configuration file like this:
spring:
application:
name: myApp
cloud:
consul:
enabled: true
host: localhost
port: 8500
config:
enabled: true
datasource:
url: jdbc:oracle:thin:#localhost:1111:XXXX
username: ${nameOfVariable1}
password: ${nameOfVariable1}
driver-class-name: oracle.jdbc.OracleDriver
For example, I need to configure embedded tomcat port, or DB credentials, I don't want to put it hardcoded in .yml properties file, instead I want to put some variable name in .yml so Spring will go and bring value from Consul. Is it possible?
You can use Spring Cloud Consul Config project that helps to load configuration into the Spring Environment during the special "bootstrap" phase.
3 steps:
add pom dependency: spring-cloud-starter-consul-config
enable consul config: spring.cloud.consul.config.enabled=true
add some config in consul kv in specific folder, such as key: config/testConsulApp/server.port, value:8081
and then start the sample web app, it will listen 8081.
more detail at spring cloud consul doc.
and demo code here

How to create Spring Cloud Config Client with env specific configuration?

I have facing an issue with Spring Cloud Config Server and Eureka Server Profiling.
Let's say I have 3 services with their name ("spring.application.name") as :
myapp-svc
myapp-spring-cloud-config-svc
myapp-spring-eureka-svc
I want to deploy each service in 2 regions ( dev and prod ). In Dev region, each service will run on localhost and in prod it will have some different url. 'myapp-spring-cloud-config-svc' in dev region will point to local git repo, while in prod region it will point to remote git repo.I can have 2 configurations:
1) When I start 'myapp-svc' service in local, it should connect to 'myapp-spring-cloud-config-svc' in dev.
I can do this by setting spring.cloud.config.uri = .
But the issue with this set up is that the property needs to be defined in bootstrap.properties.
So, If deploy 'myapp-svc' to prod, I will have to change config uri there to point it to prod config service which in turn would need another build creation.
This doesn't seem like a good solution, what if I have 50 app related services, I can't change this property in each one of them before prod deployment.
I tried setting spring.cloud.config.uri in application-dev.properties of 'myapp-svc' but it doesn't work. As per docs, it must be changed in bootstrap.
So, how do I implement this without having to create new build for prod ?
2) I can first call eureka and then using eureka I can call config service here.
The problem here is also same.
If I use eureka to look up config then "eureka.client.serviceUrl.defaultZone" must be defined in "bootstrap.yml".
See this:https://cloud.spring.io/spring-cloud-config/multi/multi__spring_cloud_config_client.html
So, in this case too, I need to change eureka url before deploying this service to prod.
Please help me on this...!!
Here is how, the properties, yml looks like for each of the above mentioned services:
1) myapp-svc:
1.1)bootstrap.yml
spring:
application:
name: myapp-svc
cloud:
config:
discovery:
enabled: true
serviceId: myapp-spring-cloud-config-svc
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8762/eureka/
server:
port: 8082
2) myapp-spring-cloud-config-svc:
2.1)application-dev.properties:
spring.cloud.config.server.git.uri=file:///C:/config-repo
eureka.client.serviceUrl.defaultZone=http://localhost:8762/eureka
2.2)application-prod.properties:
spring.cloud.config.server.git.uri=https://github.com/<mygit Repo>
2.3)bootstrap.proerties:
spring.application.name=myapp-spring-cloud-config-svc
server.port=8888
3) myapp-spring-eureka-svc
3.1)bootstrap.proerties
spring.application.name=myapp-spring-eureka-svc
server.port=8762
1) You can have profile specific bootstrap-<profile>.properties (like for application-<profile>.properties) for each supported profile to avoid rebuilding your application for each env. Then just pass application profile using to your application during start-up. Spring will load correct bootstrap-<profile>.properties and will connect to proper configuration server (or eureka, etc). Example:
java -jar your-app.jar --spring.profiles.active=dev
2) You can pass your URLs externally as custom properties (same as with profile above) and have smth like this in bootstrap.properties. Example:
spring.cloud.config.uri=${config.server.url}
then pass --config.server.url= ... during start-up.
3) You can pass Spring properties in the same way during start-up. Example:
java -jar your-app.jar --spring.cloud.config.uri= ...
4) You can use system env variables. Example:
spring.cloud.config.uri=${SYSTEM_ENV_CLOUD_CONFIG_URI}

how to make spring boot client's application.yml get value from config server

Is there anyway to make spring cloud config client's application.yml read values from spring config server?
For example,
on my spring cloud config client, the application.yml is like this
spring:
application:
name: clienttest
mvc:
view:
prefix: /jsp/
suffix: .jsp
server:
port: 8080
context-path: /clienttest
tomcat:
uri-encoding: UTF-8
eureka:
client:
service-url: {"defaultZone":"http://dev.euraka01.app.com:8769/eureka/,http://dev.euraka02.app.com:8770/eureka/"}
instance:
prefer-ip-address: true
and my bootstrap.yml file is as below
spring:
application:
name: clienttest
cloud:
config:
name: clienttest
uri: http://192.168.2.101:9000
enabled: true
profile: out_test
label: master
now for the service-url value, for different environment, I have to config different eureka url values, my question is that, is there anyway that I can config the service-url value in the config server? like I set the value as ${service-url} in the application.yml, and when I start the config client server, it get the value from the config server according the profile and label which I set in the bootstrap.yml.
You can look up properties on the config server by both profile and label, where label is either either a branch, tag.
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
In your example above your config server will try and find a file named
clienttest-out_test.properties
In the git repo on the master branch.
spring:
application:
name: clienttest
cloud:
config:
profile: out_test
label: master
See the example and also a good doc here
Essex Boy,
Thank you very much for your help, and I was able to read the value from different config profile before.
My question is how to make application.yml get the value from config server, and now I've solve it by myself, the answer is quite easy, in the application, set value like ${service-url}, the full answer is as below:
in my application.yml, the content is as below:
spring:
application:
name: clienttest
server:
port: 8080
context-path: /clienttest
tomcat:
uri-encoding: UTF-8
eureka:
client:
service-url: {"defaultZone":"${service-url}"}
instance:
prefer-ip-address: true
Please note the service-url value, now the value is set as {"defaultZone":"${service-url}"}, and in my application.properties file which on the config server, the properties file content is as below:
service-url=http://192.168.2.101:8769/eureka/,http://192.168.2.101:8770/eureka/
then when I start the mocroservice, it could resist it self on the http://192.168.2.101:8769/eureka/ and http://192.168.2.101:8770/eureka/
which is what result I want.

Resources