How to desgin the spring boot profile active arugment? - spring-boot

As we known that, we have some methods to set the profile, the priortity order is javaCode > commondline argument > jvm variable > os variable > config...
If I have 500 or more spring-boot-micro-services, what is the right way to set the profile variable?
The profile may be has 10 or more values such as prod/prod,sg/prod,us and others.
Thanks for your practical advise very much.
Maybe we can use template + os variable?

We can externalize the properties file in springboot app and make use of Springboot config server.
Here, we need to create one springboot application which will act as config server. On main class give #EnableConfigServer #SpringBootApplication.
Refer to https://spring.io/guides/gs/centralized-configuration/
You can create git repo for this, make branching based on your environments and give data/properties likewise. And deploy that particular branch on particular env, like config_UAT on UAT env.

Related

How can we set different environment profile in spring boot?

I am working on microservices using spring boot. i have around 5 microservices. so I configured spring cloud config server to centralized configuration. its perfectly working fine.
config server configuretion
spring.profiles.active=native
spring.cloud.config.server.native.search-locations=classpath:/common-config
server.port=8888
now the problem is I have two environment dev and test and i created application-test.properties and application-dev.properties as per the spring documented i need to set profile like
Spring profile
spring.profiles.active=test
but its already set as a native then how can i load multiple profile.
please help me ..
You can pass in the active profile name as an environment variable at run time of each of the apps. This will take priority over the active profile listed in your properties file. You can do this with any property actually. If you're using docker to launch your apps, you can pass it in from your Dockerfile or from your docker-compose.yml
You can set spring.profiles.active=$ACTIVE_SPRING_PROFILE and set OS environment ACTIVE_SPRING_PROFILE = test
You can use multiple profiles in Spring. Try:
spring.profiles.active=dev,native
See more: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html#boot-features-profiles

Spring Boot application profiles

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.

What is best practice management properties for me?

What can I do for best practice management properties?
I want to set different properties each deployed environment.
Some of my developer cannot detect my real server properties.
I want to build project using same command (using maven. not want to -P dev, -P production options)
I don't want to too many source code to load my properties.(like implements db access)
Can be continue my service without restart when some properties has been changed.
My service developed using spring-web.
You have 2 issues:
1) How to have your properties outside of the war file, I would suggest you do the following:
#PropertySource(value={"classpath:/config.properties", "file:${configRoot}/config.properties"}, ignoreResourceNotFound = true)
Then when you start your app you can specify configRoot as a system property to the JVM i.e -DconfigRoot=/var/config. You can then specify a default config which will be pulled from inside the war. Using the ignoreResourceNotFound if the file:${configRoot}/config.properties"} can not be found the first one will be used. i.e. you can have a default inside the war and override it at runtime with the JVM system parameter.
2) How to automatically refresh
Look at this answer to tell spring to refresh it's properties on a schedule:

Environment specific properties from user home in springboot

I am working on a spring boot application in which i have to set Environment specific properties from user home folder.
i dig Google for the same & found we can put different properties file (dev, test, production) under resources and then we have to tell spring boot which environment we want to use using spring.profiles.active=dev OR prod.
however, my requirement is quite different. i will put a file in user home in my system & want to read properties form that file. how can i do that, need guidance.
Helping hands will be highly appreciated.
From the Spring Boot docs:
You can also refer to an explicit location using the spring.config.location environment property (comma-separated list of directory locations, or file paths).
As the docs go on to state, this must be specified on the command line or as an environment variable.
$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
We explain that use case in a Devoxx presentation using EnvironmentPostProcessor, please refer to this section of the presentation for more details. You can also find the code sample online.
Well, it seems in your case you dont need environment variable. For production server your property file will be staying in and in staging machine it is also staying at same place. So where ever you deploy it will pick from . IMO you don't need to set environment, you just have to point property file to
Now to define this path you have 2 ways..
- You can put static path in your code
- You can set environment variable like Property_Path and read it in spring boot application..
However If you want to go one step ahead, you can use spring cloud configuration manager, by passing application+profile name to it, CM can fetch property file from directly from git or file system for you ...

No plain text passwords in Spring Boot’s application.properties

Having something like
security.user.password = plainTextPassword
inside Spring Boot’s application.properties is obviously an anti-pattern as it prevents the code from being pushed to a public SCM. In my non-Spring Boot projects I use
security.user.password = ${myPasswordFromMavenSettingsXML}
and put a corresponding <properties/> reference inside my pom.xml.
Using Maven’s resource filter plugin the passwords are replaced at build time so the application have access to actual plain text passwords after it has been build and deployed.
For some reason Maven’s resource filter plugin does not work in this case. Is there a way to not commit plain text passwords to an SCM and let Spring Boot to insert them at build time?
Spring boot has multiple mechanisms to provided externalized configuration. Some examples are command line arguments, environment variables and also application properties outside of your packaged JAR.
What I usually do:
Locally we configured several environment variables. Most (if not all) IDE's allow you to configure environment variables from within the run configuration.
For example if you don't want to expose the spring.datasource.password property you could set an environment variable called SPRING_DATASOURCE_PASSWORD.
When we deploy on another environment, we usually choose to add another application.properties or application.yml file within the same folder as the application JAR/WAR, since Spring boot picks that up as well.
Another solution is to use Spring cloud since it has a config service which can be used as a microservice to provide configuration. The configuration can be versioned using SCM as well, but you can put it on a separate system that is not connected to your source code.

Resources