Spring Cloud Config server inside a Spring Boot app with MVC - java

I'm inserting a Spring Cloud Config server directly into my existing Spring Boot App, by adding the module dependency and #EnableConfigServer. Everything works as expected except I just realized that the config server URL mapping is hijacking some of my existing API endpoints due to they are sharing the same server.port
For example, I had an existing page at v1/docs/index.html, and this will be now mapped automatically to org.springframework.cloud.config.server.environment.EnvironmentController#labelled which has
#RequestMapping("/{name}/{profiles}/{label:.*}")
public Environment labelled(#PathVariable String name, #PathVariable String profiles,
Wondering is there anyway I can separate config server to a different port? Or add a special prefix to it to avoid URL mapping conflicts? Or given the current configurability it's just a bad idea to utilizing existing API servers as a config server?

Found the answer I need after reading the document more carefully:)
https://cloud.spring.io/spring-cloud-config/spring-cloud-config.html#_spring_cloud_config_server
To change the location of the server endpoints you can (optionally) set spring.cloud.config.server.prefix, e.g. "/config", to serve the resources under a prefix. The prefix should start but not end with a "/". It is applied to the #RequestMappings in the Config Server (i.e. underneath the Spring Boot prefixes server.servletPath and server.contextPath).

Related

Can't Discovery-Locate Config Upon Transition to Spring 2.4

Versions
Spring Parent: 2.7.4, Spring Cloud Version: 2021.0.4, Java Version: 11
Issue
My Spring service has been using Eureka to connect to the config server for a long time, but I want to upgrade to Spring 2.7.4. I understand that as of Spring 2.4, the bootstrap context has been deprecated (source) and I need to make some adjustments to the old bootstrap properties and move them over to application.properties.
The documentation for Spring Cloud specifies that in order for me to continue to use discovery-first config lookup, I need to define a spring.config.import property with an optional configserver entry (source). Since I'm also using Vault, I define the property as follows:
spring.config.import = optional:configserver:placeholder,vault://<my-generic-backend>/dev
Next, I need to define the following properties (source). These properties were already defined in my old bootstrap.properties, so all I need to do is copy and paste.
spring.cloud.config.discovery.enabled = true
spring.cloud.config.discovery.serviceId = config-server
eureka.client.serviceUrl.defaultZone = <my-eureka-url>
Unless I'm missing something, these are all the steps I need to take in order to upgrade to 2.7.4. However, when I run the Spring service, it complains that it can't find the config server (via Eureka, or via URL), then it registers successfully with Eureka, and then continues trying and failing to find the config server.
Here is some of the output of the program:
> Running with Spring Boot v2.7.4, Spring v5.3.23
> Could not locate configserver via discovery: No instances found of configserver (config-server)
> Could not locate PropertySource ([ConfigServerConfigDataResource#2aa6311a uris = array<String>['placeholder'], optional = true, profiles = list['local']]): Invalid URL: placeholder
...
> DiscoveryClient_<my-project-name>/local - registration status: 204
I understand why it's failing to find a config server at URL: placeholder since that's not a valid URL, but I don't understand how the service can successfully register with Eureka yet not be able to find the config server. I know the service is registered because the output of the program says it registered correctly (and I can see it in the registry), and I know that the config server has the correct entity ID (config-server) because it was copied and pasted from the old bootstrap (and I can see config-server in the registry).
Workaround with Hardcoded URL
When I hardcode the config server URL like this (and set spring.cloud.config.discovery.enabled to false), the config is loaded properly from the server:
spring.config.import=configserver:https://<my-hardcoded-config-url>.com,vault://<my-generic-backend>/dev
Workaround with Bootstrap
It's possible to return to using the bootstrap context and still use Spring 2.7.4 with discovery-first config lookup by adding the "spring-cloud-starter-bootstrap" dependency. So I added the dependency to my POM and moved these properties back to bootstrap.properties from application.properties.
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=config-server
I moved the Vault and Eureka properties back into bootstrap.properties as well. The new application.properties now contains no values relating to Eureka, Vault, and Cloud Config.
When I run the service, it does indeed find the address for the config server through Eureka, as expected (although it fails to connect because it's the internal address and I'm running locally).
Conclusion
While these are valid workarounds, it's frustrating to not be able to have a dynamic URL for the config server (as is the entire point of using Eureka). Right now, it looks like my choices are either to use a hard-coded URL and risk having to change every property file, or use a deprecated behavior that Spring documentation specifically disfavors (source).
I would appreciate any guidance you have on the issue, and I thank you in advance.

How to configure multiple spring cloud config servers in spring boot

I am using spring boot 2.4 and application related properties are stored in spring cloud config server. It works fine and I am able to read all properties in the application. Below properties have been configured in application.properties for this purpose.
spring.application.name=app-prop-config
spring.cloud.config.label=61465
spring.cloud.config.enable=true
spring.config.import=configserver:https://vmcloud-configsvc.farm-dev.ab.com
The above properties translates to: https://vmcloud-configsvc.farm-dev.ab.com/61465/app-prop-config-dev.properties
Per my requirement, I need to read few more properties as well and these properties are already available in another spring cloud config server which can be accessed using:
spring.application.name=common-prop-config
spring.cloud.config.label=61468
spring.cloud.config.enable=true
spring.config.import=configserver:https://vmcloud-common-configsvc.farm.ab.com
The above properties translates to: https://vmcloud-common-configsvc.farm.ab.com/61468/common-prop-config-dev.properties
The above config server(https://vmcloud-common-configsvc.farm.ab.com) properties have been used by multiple applications and duplicating properties into my config server(https://vmcloud-configsvc.farm-dev.ab.com) would cause maintenance issue in future as any change in properties have to get updated in 2 servers.
Is it possible to use above 2 spring cloud config servers in spring boot app so that I don't have to copy required properties into my existing config server?
Hi it's working for me when i use bootstrap first config. You can put multiple config name that you want to load. For example if you want to retreive user-service.properties et data-rest.properties in the same app your bootstrap.properties should be like:
spring.cloud.config.uri= http://config-server-host
spring.cloud.config.name= user-service, data-rest

External URL configuration in microservice

I have multiple microservices which communicates with each other through REST calls.
I have used spring boot and spring rest and have configured the URLS of the rest end points in application.properties file.
Now the problems is if the URL for one end point changes then I to have to manually modify all the property files of the services which are calling that particular end point which has got changed.
Is there a workaround for this so that the URLS can be somehow placed in a centralized location so that any modification does not impacts the other services which are using it.
You can use spring-cloud to achieve this. Usual way used in spring-cloud is by configuring the required properties in a git repo. And then those properties can be accessed by any micro-service you want with minimal configurations. You can refer projects in this repo
limits-services acts as a client that needs certain properties those are configured in spring-cloud-config-server. Hope this helps.
In case with microservices you can use Spring Cloud Config (Spring Cloud Config, Spring Cloud Config Server). It's very usefull and you can update your configuration at runtime.
Spring Cloud Config provides server and client-side support for externalized configuration in a distributed system. With the Config Server you have a central place to manage external properties for applications across all environments. The concepts on both client and server map identically to the Spring Environment and PropertySource abstractions, so they fit very well with Spring applications, but can be used with any application running in any language. As an application moves through the deployment pipeline from dev to test and into production you can manage the configuration between those environments and be certain that applications have everything they need to run when they migrate.
As others have mentioned you can use Spring Cloud Config Server to remotly load your application configuration. All you need is git repository containing your configuration.
Spring cloud configuration supporst Git, database as your store for configuration.
Idea is to create an spring-boot app that can provide configuration to other applications.
#SpringBootApplication
#EnableConfigServer
public class ConfigServer {
public static void main(String[] args) {
SpringApplication.run(ConfigServer.class, args);
}
}
You can configurae port and provide your git repository using key spring.cloud.config.server
server.port: 8888
spring.cloud.config.server.git.uri: file://${user.home}/config-repo
At client side, if you have spring-config in your classpath, application will try to connect to an application runnign at port 8888 to retrieve configuration.
More information can be found here.
may put configuration inside a database.
after that need have one centralize cache service that used by other services, can be .jar service,
then the values can be load inside a cache class in this service,
then in the front end side need have update button for updating the cache after modify the URL value in the database, so then all impacted services can use new value.
and also to be easier may have stand alone UI for update those configuration rather than updating database directly.
You can use Microconfig.IO to manage your service configuration and it's placeholders functionality to reference configuration values of certain services from others. So in your case you configure your deploy url in your server and put placeholders on it in your clients. This allows you to edit value only in one place and then everyone who depend on it will get it automatically.

Dynamic scheduling with properties in spring boot

I am using Spring Boot and have an issue related #Scheduled.
#Scheduled(fixedRateString = "${timeRate}")
public void SaveStatisticData() {
System.out.println("save Info per "+timeRate+"msec");
...
}
this is a part of my code. this method will run by timeRate value from properties and Properties File is connected with web API.
That means someone can request to change timeRate in Properties File.
I want to know how to reload spring boot on client request which change Properties File.
AFAIK, I can use Hot Swapping in spring boot.
But I think this solution is not good to service.
Because The service have to reload whenever a client request changing timeRate.
In other words, is there another way to apply this client request in real time?

how to change spring cloud config server url pattern to have path inside

I am using spring cloud config server to save all the configuration in various environments,upto now, it worked great, but now, I suddenly met an issue, don't knwo how to change it.
By default, the url pattern is: http://xxx.xx.xx:8888/{appName}/{environemnt}
But now I need to deploy multiple service together, and I can no longer use path to the root, and I need to use this one:
http://xxx.xxx.xx/pathToConfig/{appName}/{env}
But I noticed that spring config server will consider as appName instead there.
May I ask if there are any configuration I can change to make sure spring config server be able to consider url only after some path after the root?
Thanks
spring.cloud.config.server.prefix: /<path> only changes the prefix for the config server api, not the whole application.
You can specify server.contextPath: /pathToConfig in your application.yml of other configuration.
Then it will prefix all the mappings with the specified path.

Categories