I currently have a number of deployable applications that work in a distributed fashion to solve a business problem. We are currently using a number of property configuration files to provide changing configuration per environment based off a system environment variable. All these deployable application share common configuration for database and messaging. This is currently achieved by picking up property files from the class path and having both deployed apps share a common jar for each connection (db, jms) containing property files.
I am looking to start using Spring Config Server to externalize this configuration if possible. I have a question about how to share this common config.
Currently it looks something like this:-
Web1
- database
- jms
Messaging1
- database
- jms
In this situation both deployed apps share the same connections and these connections change per environment (lab, prf, prd, etc). How can I achieve the same with the Spring Configuration Server where I have app config for each deployable app?
Application.yml
Web1.yml
Web1-dev.yml
Messaging1.yml
Messaging1-dev.yml
If a connection property changed for an environment I would need to make the change to each deployable app configuration rather than making it just once.
Is there currently anyway to achieve this? Am I just missing a simple point?
I found working solution here https://cloud.spring.io/spring-cloud-config/single/spring-cloud-config.html, paragraph "2.1.5 Sharing Configuration With All Applications". It says:
With file-based (i.e. git, svn and native) repositories, resources
with file names in application* are shared between all client
applications (so application.properties, application.yml,
application-*.properties etc.). You can use resources with these file
names to configure global defaults and have them overridden by
application-specific files as necessary.
You should create application.properties or application.yml at the top level of configuration repository (if it is git or svn based). Don't forget to commit the changes.
This is how I have configured for my setup.
1 All Common properties across all services and environments will be in root->application.properties files
2 All Common properties across all environments specific to service will be root->service-X.properties files
3: Similarly, to have common properties across specific environment use env->application.properties file
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri:[git repo]
search-paths: /,/{profile}/
Finally found a solution. It's buried in the issues at github ...
https://github.com/spring-cloud/spring-cloud-config/issues/32
It worked liked described. I only noticed, that you need to put the files in a /config folder to make it work. If you put it in the root the file ist used by the configserver itself and is not included in the config requests.
application.properties/application.yml will be shared across all applications.
application-DEV.properties/application-DEV.yml will be shared across all DEV environment applications. You can replace DEV with any spring profile.
{applicationName}.properties/{applicationName}.yml will be shared across the give application.
Related
I am looking for a solution to the problem, which is that having an external Tomcat server with several different applications (war),
I would like to use application Spring Profile (dev, prod) to choose application.properties for a given profile.
To avoid keeping the database configuration in the git repository, I didn't store in the application
application.properties, but I kept them in the $catalina.base directory, where in common.loader
I indicated the path to this directory. This worked until I started deploying several different applications. Then each of them began to use
from the same datasource. One solution is to keep the application.properties in Jenkins and directly in Jobie indicating which one to use,
but I am not sure if this is a good solution.
Option 1: Create a separate instance of tomcat (using same tomcat binary) and place application.properties in instance's classpath. As classpath is separate for every instance, applications don't refer to same application.properties file. Refer to this article to see how to create multiple instances on same tomcat server.
Option 2: Create JNDI datasource on tomcat server and use it in your application to access database. This way, should you choose to, same datasource can be shared across different related applications and/or modules. For more information on how to create JNDI datasource in Tomcat, refer to this link
I want to use a common application properties file for multiple microservices which will have some common configuration like DB Source config etc..I have use the config Server with Eureka server and zull Proxy.
Issue:
When using configServer we need to provide the spring.application.name = 'xyz'
which in turn find the xyz.properties for this microservice configuration.
The same way when we register the service with zuul proxy also need the same application name for configure the service path as zuul.routes.xyz.path = /iii/*.
Now I want that multiple service will share the same property file(xyz.properties) but need to register the zuul route as well so I have to provide the different name for each service. If I will provide the different name to each service they will not be able to locate the same property file.
I am new to spring boot micro services.
spring.config.client.name supports multiple names separated by commas to load the configuration properties.
In this case, store the common properties in common.yml and xyz properties in xyz.yml. Finally, mention spring.cloud.config.name: xyz,common
spring:
cloud:
config:
uri: http://localhost:8888
name: xyz,common
Output:
Fetching config from server at : http://localhost:8888
Located environment: name=xyz,common, profiles=[default], label=null, version=91edcf96c6a88707bf39014a16ad5d301d6b4575, state=null
Located property source: CompositePropertySource {name='configService', propertySources=[MapPropertySource {name='configClient'}, MapPropertySource {name='https://github.com/BarathArivazhagan/config-server-repository/common.yml'}, MapPropertySource {name='https://github.com/BarathArivazhagan/config-server-repository/xyz.yml'}]}
I would like to point out that the provided solution leverages the "spring.config.client.name" client side property semantics to achieve a config server behavior of serving properties files from multiple files other than application[-profile].* and {appname}[-profile].*
However, note that for a simple case and considering a root dir, the config server serves properties from files defined in this root dir or under a folder with the name of the application, that the property files under it correspond to, i.e. */{appname}/application[-profile].** or */{appname}/{appname}[-profile].**
The "spring.config.client.name" environment property instructs the config server which application names the requesting app matches with. This means that given a spring.config.client.name=a,b , the config server will assume serving properties defined for app (with name) a and b to the requesting app! This is not the exact same thing as I want my properties been served from file names a and b! Therefore we are abusing the property semantics for managing our config server serving from the file names we would like it to.
However, due to the actual semantics of spring.config.client.name the config server will serve everything applicable from
/a[-profile].*
/b[-profile].*
/a/{applicable names}
/b/{applicable names}
The caveat here is that we achieve what we want only for the root directory and, moreover, if we have a configserver that serves multiple springboot apps we loose the ability to have all our properties under our application's name-folder.
Even worse, if there exists another app (or -attention!- will exist in the future) with the same name as one of our desired property file names, the config server will start serving to our app ALL the configuration defined for that other app!!! This could end up in wrong and even harmful served configuration!
(I repeat it will serve everything applicable under /{other-app-name-that-i-happened-to-use-as-filename-and-defined-it-through-spring.config.client.name}/*!!!)
So beware when pirsuiting this approach!
I have issued a pull request for spring-cloud-config-server 1.4.x, that supports defining additional file names, through a spring.cloud.config.server.searchNames environment property, in the same sense one can do for a single springboot app, as defined in the Externalized Configuration.Application Property Files section of the documentation, using the spring.config.name enviroment property. I hope they review it soon
I have a centralized configuration for spring boot service. I followed this link to make it.
I have configServer and configs two separate project. Configs have several properties files. And configServer reading it and rendering to other services.
Now I want to make configs UI based.
e.g.
application.properties of configs which is hosted at git.
logging.path=logs
logging.level.root=INFO
logging.level.org.springframework.boot.autoconfigure.security=INFO
It`s UI should be
logging.path as key text box for value( logs ).
Is there any example for it. Any help will be appreciated.
Thanks.
Since you mention using text box in your post, I'm assuming that by UI you mean GUI.
While I'm not aware of any examples (and you do not specify whether you want to have a destktop or web application) if you're using git to store configuration, your app needs to:
Checkout the git repo with configuration (using JGit for example)
Load properties files generate edit window for each file (something
similar to what IntelliJ does for environment variables in run
configurations perhaps)
Save edits to files
Commit and push changes (again using JGit or a similar library)
I understand there's multiple ways of handling application property files and profiles in Spring Boot and I've seen multiple questions and answers on how to handle each but I'm trying to find the "best" way of handling it for a new project, if there is one.
The application is hosted in Weblogic 12c on production/pre-prod (with a jndi database connection) and ran locally in tomcat (with hardcoded database details) for development. I'd like it so that when the project is built via gradle and deployed to production it uses the jndi properties file and when ran locally it defaults to the hardcoded datasource with minimal changes required.
src/main/resources/application.properties
# DEV
spring.datasource.url=
spring.datasource.username=
spring.datasource.password=
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
# DEV
# PROD
# spring.datasource.jndi-name=
# spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
# PROD
From my understanding the recommended way is to externalize the property files and place the required one in a config directory alongside the WAR file for any differing config which is then automatically picked up and used?
You should consider creating multiple profiles. This means: Either multiple properties-Files, or multiple profiles in one file:
See https://docs.spring.io/spring-boot/docs/current/reference/html/howto-properties-and-configuration.html
I would recommend to use multiple application-ENV.properties, e.g.
application-prod.properties and application-preprod.properties.
There is always one active profile and settings from the application.properties (without any profile suffix) are used as default values if not overwritten in a specific profile-file.
Depdending on your environment (local, prod etc.) you should set an environment variable (start the java-process/application server with that environment variable), e.g.:
SPRING_PROFILES_ACTIVE=prod
On your local machine you would set:
SPRING_PROFILES_ACTIVE=dev
With this variable you can control, which profile is currently active.
Also consider integrating the active profile into you Continious Integration/Deployment settings.
Please note that putting plain text passwords hardcoded into committed files is not a good idea. Consider using jasypt or a spring cloud config server for your prod database configuraiton or use any mechanism that your cloud provider provides to you if you use any. Microsoft Azure for example provides a KeyVault for sensitive data.
https://cloud.spring.io/spring-cloud-config/multi/multi_spring-cloud-config.html
http://www.jasypt.org/
If you use gradle good solution is to set application.properties and test.properties files and put into them properties for prod and preprod respectively.
Then run application with different vm arguments: -Dspring.profiles.active=test for test.properties and without arguments for application.properties
Use gradle instruments and configure them once for test and prod. For example: gradle bootWar configure without vm arguments, gradle bootWarTest with vm arguments -Dspring.profiles.active=test. Save once you configs and you will create war for different environments only selecting between two buttons in gradle.
I am using Springboot and developing web services based on those. In my services, I am keeping the configuration at git instead of with project, so that I will be able to change the properties at run-time without restarting the application.
I am using a ConfigServer to fetch the configuartion and all my services are Config Client.
But the issue is my config files are fetched from git based on
-.properties file, so for ex. if my application name is demo and active profile is testing, then the config file which is getting fetched from git is demo-testing.properties.
But the issue I want to have more than one config file. So how should I mention second config file?
Also the second config file is common to other services also?
So actually I want to use same config file for many services which is located at git?