Spring boot not reading environment specific YAML file - spring

I have developed a spring boot rest application and I am trying to read the environment specific YAML file based on the value "spring.profiles.active"
I have two files
1. application.yml
2. application-qa.yml
and I have below property in both the files
application.yml file has below property
comp:
bu:
env: local
application-qa.yml file has below property
comp:
bu:
env: QA
and I am setting spring.profiles.active=qa, given above, I was expecting that only application-qa.yml gets loaded, but in this case both application.yml and application-qa.yml are getting loaded and when my code looks for property comp.bu.env it is always getting the value
local
only
I want my code to read the comp.bu.env property from application-qa.yml file.
can some help to figure out what i am missing here?

It seems like the spring.profiles.active value is not being set correctly, and hence your app is loading the default application.yml.
Try setting the value with
-Dspring.profiles.active=qa
before the bootRun command.
e.g. If you are using gradle, you would do ./gradlew -Dspring.profiles.active=qa bootrun

Remove comp.bu.env configuration from application.properties. Create separate configuration file application-dev.yaml and place this configuration there:
comp:
bu:
env: local
Now when you work on local configure spring.profiles.active=qa.
This would effectively create development configuration profile.

Thanks for your points, I have solved it.
I have AWS profile in application-qa.yml which is causing my QA properties to be skipped because the profile name I have supplied is QA. I have moved my properties above the AWS:profile in application-qa.yml file then those properties started picking up.

Related

Spring boot application file layering

I have 3 files as below:
1. application.yml with some other configurations
2. application-default.yml with contents
apisigning:
client:
sharedKey: 'some xyz'
secretKey: 'some xyz'
proxyHost: 127.0.0.1
port: 9480
3. application-cloud.yml with contents
apisigning:
client:
sharedKey: 'some xyz'
secretKey: 'some xyz'
So when I run the application with default profile I want to use proxy host and port values from the application-default.yml file. But once its deployed in cloud it shouldn't be configuring the proxy host and port values ideally. The issue I am facing is that in cloud env its somehow getting the values for that proxyHost and port. I want to know what is going wrong here? How the layering of yml file is done based on profiles in this case.
from Spring Boot Reference
24.4 Profile-specific Properties
In addition to application.properties files, profile-specific properties can also be defined by using the following naming convention: application-{profile}.properties. The Environment has a set of default profiles (by default, [default]) that are used if no active profiles are set. In other words, if no profiles are explicitly activated, then properties from application-default.properties are loaded.
Profile-specific properties are loaded from the same locations as standard application.properties, with profile-specific files always overriding the non-specific ones, whether or not the profile-specific files are inside or outside your packaged jar.
If several profiles are specified, a last-wins strategy applies. For example, profiles specified by the spring.profiles.active property are added after those configured through the SpringApplication API and therefore take precedence.
[Note]
If you have specified any files in spring.config.location, profile-specific variants of those files are not considered. Use directories in spring.config.location if you want to also use profile-specific properties.
found here https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config-profile-specific-properties

In Spring Boot, how do you build a JAR file for a different profile even if proper environment variables have not been set?

I'm new to Spring Boot, so bear with me. Currently, I'm working on a small app just for the purposes of learning Spring Boot. My goal is to deploy it using AWS (elastic beanstalk).
So far, I've created three application properties files:
application.properties: Properties which apply to all profiles.
application-dev.properties: Properties only for development. This includes localhost connection to DB, path to self signed key store, etc.
application-prod.properties: Properties used only for prod. This includes the prod DB details, etc.
Everything works fine when running the app locally using the dev profile since everything has been hard coded in the application-dev.properties.
However, the application-prod.properties file contains references which will be resolved through OS environment variables, such as:
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}
I currently do not have the variables DB_USERNAME and DB_PASSWORD set up in my local OS, and I do not wish to do so. But when I run the following command, it obviously fails:
mvn package spring-boot:repackage -Dspring.profiles.active=prod
It fails because it's unable to find the above environment variables.
Is there any way to delay this check until I actually execute the JAR? My plan is to build the JAR locally and then copy it over to my prod server, and run it there. The prod server will definitely have these environment variables.
The workaround I found is this:
mvn package spring-boot:repackage -Dspring.profiles.active=dev
java -jar -Dspring.profiles.active=prod [jar-file-name].jar
However, this feels like a hack. And it may cause issues in the future that I can't think of right now.
You can use any value you want in those properties for prod profile. If the env varieble exists, Spring will take the value from there instead of the properties.
As explained here:
Spring Boot uses a very particular PropertySource order that is
designed to allow sensible overriding of values. Properties are
considered in the following order:
[...]
OS environment variables.
[...]
Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants).
So your application-prod.properties can look like this:
spring.datasource.username=willBeOverridenByEnvValue
spring.datasource.password=willBeOverridenByEnvValue
You have to make sure though that you set both SPRING_DATASOURCE_USERNAME and SPRING_DATASOURCE_PASSWORD env values in your prod server

Spring Boot embedded jar and application.properties location

I thought I had this working because in my IDE the correct environment properties file was being used, and a local application.properties was being correctly used. I am trying to use profile specific properties to determine various values throughout my Spring-Boot 1.3.5 app.
My src/main/resources/application.properties is:
spring.profiles.active=test
server.port=8080
deploy.server=http://localhost
liquibase.change-log:classpath:/db/changelog/db.changelog-master.xml
liquibase.check-change-log-location=true
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
logging.file=myapp.log
spring.jackson.serialization.write_dates_as_timestamps=false
And I have a src/main/resources/application-test.properties:
server.port=8081
deploy.server=https://test.myapp.com
logging.level.liquibase:TRACE
logging.level.org.springframework.security:DEBUG
Now I apparently have two problems:
After I run "gradle clean build" I get my jar and trying to run via:
java -jar build/libs/app.jar -Dspring.profiles.active=local
I see the message:
The following profiles are active: test
So it picking that up from the application.properties file and I can't seem to override it, which I think is causing my second problem:
My Jenkins build fails when I try to use a parameterized build with the values:
spring.profiles.active set to "test".
The error I get is Tomcat in a failed state. If I take that parameter out of the build, it works. But that build will not run from the command line unless I copy the application-{env}.properties to the run directory (which might be best practice anyway?).
I am not sure if the problem is the location of the properties files or the way I am trying to build them.

Spring Boot external properties file (with profiles)?

What I am trying to accomplish, is to specify a directory on my application.yml file located directly on the classpath (under /resources). I would like to be able to have something like:
spring:
datasource:
driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
profiles:
active: dev
config:
location: C:\\app\\configs\\
Then under the c:\settings\configs\ location, I would like to have multiple config files based on the profile being loaded, such as:
c:\app\configs:
application-dev.yml
application-staging.yml
application-production.yml
Using this approach, the IDE would always default to application-dev.yml. When I build the app via gradle, and run it while passing in the command line arguments, I can specify the profile, thus loading the appropriate file. Ideally, being able to do just this:
java -jar -Dspring.profiles.active=staging appliation.jar
All the examples or answers I've seen have shown how to pass this all these config options from the command line only, not using
spring.config.location
and
spring.profiles.active
from within a default config file (eg: application.yml). Preference is to set this up as described above for minimal deployment.
Thank you for any suggestions / help!
You could give it a try and provide your base configuration as "bootstrap.yml" instead of "application.yml". Afterwards, spring boot should choose the right config depending on the chosen profile from your configuration path.
To me, this seems to be the closest solution to your use case, if you do not want to make use of command line arguments.

Build Spring project for run on another system

I Successfully create a spring boot project on my own local system. I want to build a jar file so I can install it on remote server. so I had to configure server address and mySql address of remote server but I can not Build and it have many errors, and they all right cause my system can not see the remote server address and database.
this is my .properties file:
spring.datasource.url=jdbc:mysql://localhost:8081/aths
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto=create
server.address=192.168.24.250
server.port=8080
how can handle it for running on another configurations? ( another IP, datasource, and ...)
Am I doing it right or not? thanks
You can use spring profiles here :
Create different property files for different profiles using application-{profile}.properties format, e.g. application-dev.properties for dev, and application-prod.properties for production put your profile specific configurations in them. Then when you're running the spring boot application, activate your intended profile using the SPRING_PROFILES_ACTIVE environment variable or spring.profiles.active system property.
and at the end, you will run your jar file with command
java -jar -Dspring.profiles.active=prod application.jar
You can have different application.properties within your resources folder and use spring profiles for example application-{profile}.properties and run the application with the specified profile. However this still limits the configuration items to what has been hard coded within the properties files. When running the application, if it was to be distributed to other people, where non of the profiles are supported you can provide a properties file at start up.
So in the same directory for example as the .jar file create a file named application.properties with empty place holders for all the variables required for the application so the admin can enter the details correct for them. Then they will be required to start the application with the following command
java -jar 'applicaitonname.jar -Dspring.config.name="file:/path/to/application.properties"
Or springboot will load properties from application.properties files in the following locations:
A /config subdirectory of the current directory.
The current directory
Failing that the default application.properties from the resources folder will be loaded.

Resources