Springboot application in pivotal Cloud with different environments - spring-boot

I am using a Pivotal Cloud foundry with different testing environments (test, QA, UAT, PROD) Spring boot application
I have created multiple properties files(Each pointing to different db) like
application-dev.properties
application-test.properties
application-qa.properties
application-uat.properties
application-prod.properties
if it is in local i am running by seting -Dspring.progiles.active=test/qa/uat/prod
mvn clean compile springboot:run -Dspring.progiles.active=test
How can I make it customize my application to use the specific properties file based on the environment in the cloud?
What all the configurations do I need to change? Below is my application.properties file.
spring.profiles.active=test
spring.datasource.url=
spring.datasource.username=
spring.datasource.password=
spring.datasource.driver-class =org.hibernate.dialect.TeradataDialect
spring.jpa.database-platform=org.hibernate.dialect.TeradataDialect
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = none
spring.jpa.properties.hibernate.default_schema=
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.TeradataDialect
server.port=9090
logging.level.org.springframework.web=INFO
logging.level.org.hibernate=INFO
logging.file=myapplication.log
or do I need to change whenever I move to higher environments?
Thanks in advance.

You can have one applicaiton.yml file for all of your environments and separate environment-specific manifest file. Use spring profile feature to add environment-specific properties. Spring will auto pick the properties based on the active environment profile and manifest file.
Example application.yml can have
spring:
profiles: default
username: xyz
spring:
profiles: development
username: abc
And in an environment-specific manifest file you can have:
env:
SPRING_PROFILES_ACTIVE: development

You've to move all your property files to GIT by leveraging Spring Cloud Config Server. From your application, use bootstrap.yml file to connect with Config Server and you'll be providing the environment name like prod, dev, qa.

Related

Spring Boot Configuration File Location From Tomcat

I'm trying to setup backend application so it gets different configuration files depending on env.
On dev env I would like to load default application.yml from classpath. This should be the case when I'm running the app via: mvn spring-boot:run or java -jar ./target/myapp.war
But when this app is running on Tomcat it should load application.yml from server specific file e.g. /etc/apps/myapp/application.yml (not default one from classpath) because server has different mongodb credentials etc...
I don't want to use profiles because this mean I need to put server credentials in project on github in application.yml. I just want that this is known by server administrator and developer don't know anything about it.
Is there any way how can I tell this application inside tomcat to load different configuration file.
In this Tomcat I have other applications that are using spring boot so I need some solution that is independent. Setting globally spring.config.location is not the case because all apps will load this one file.
You can use #PropertyResource annotation with context xml.
NOTE: ignoreResourceNotFound will help not throw exception when file not found, say for Dev env.
#Configuration
#PropertySources({
#PropertySource("classpath:application.properties"),
#PropertySource(value = "file:${config.file}", ignoreResourceNotFound=true)
})
public class AppConfig {
//...
}
/META-INF/context.xml
<Context>
<Parameter name="config.file" value="/yourpath/application.properties"/>
</Context>
If you don't want to save path in context.xml inside your project, there are other ways to define application level context depending on your tomcat version. Please refer here for details for tomcat 9.
If you want to read properties from external location then write bootstrap.yml in your application and delete application.yml.
bootstrap.yml:
spring:
config:
location: file:/home/external/properties/location/
name: application
profiles:
active: dev
file location: /home/external/properties/location/
suppose you need dev and prod environment.Then keep this 3 properties file in this location.
application.yml
application-dev.yml
application-prod.yml
Spring boot read application.yml properties first. If set active profile dev in bootstrap.yml then application.yml value overwirte by application-dev.yml.
Or you can use config server
Look at this

How to detect dev and production environment in Gradle based Spring Boot 2.0.0 app?

This question is in the context running app as war deployed to tomcat. It is not quite clear to me how can I specify parameters in application.properties or application.yml that have different values depending if the app is running in production or in dev? Like below
if env == dev then myparam1 = devvalue
if env == prod then myparam1 = prodvalue
Note that I am using Gradle and not Maven.
As refered to in the comments you could use Spring profiles for the different environments and provide separate configuration files for these profiles.
On production:
Add a file application-prod.yml with the production settings.
Start the application with option --spring.profiles.active=prod or environment variable SPRING_PROFILES_ACTIVE=prod.
On dev environment:
Add a file application-dev.yml with the development settings.
Start the application with option --spring.profiles.active=dev or environment variable SPRING_PROFILES_ACTIVE=dev.
Note that you can keep some common settings suitable for all environments in your application.yml and only override some specific keys in the environment config files.
EDIT:
In order to activate a certain Spring profile for your application in a Tomcat servlet context you can add a context parameter with the name spring.profiles.active to the <Context> element. See: https://tomcat.apache.org/tomcat-9.0-doc/config/context.html#Context_Parameters

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.

Spring boot not reading environment specific YAML file

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.

How do I set the default Spring Boot profile for running tests (without using environment variables)?

I have a Spring Boot project, using gradle, with three Spring profiles:
"development" (for when I'm developing)
"test" (for when I'm running tests)
"production" (for when it is deployed in production [to heroku])
I therefore have four application*.yml files:
application.yml (contains all the shared defaults)
application-development.yml
application-test.yml
application-production.yml
These environments all work fine. The problem is that when I deploy the code to heroku, heroku runs 'gradle build' (which in turn runs 'gradle test'), and heroku does not have an option of setting an environment variable. Therefore I cannot set an active profile. So when it runs the tests it is using application.yml without the overrides in application-test.yml. So therefore the tests obviously fail.
My only solution so far is to put all the application-test.yml defaults into application.yml, and then override them again in the other profiles, but this is obviously far from ideal.
Is there a way to:
set the active Spring profile from within gradle (note that I don't have edit access to the 'test' or 'build' tasks as they come from the 'spring boot gradle plugin')?
or is there a way in Spring Boot to set the default active Spring profile when tests are run?
Think joshiste's answer is the correct one.
Anyway I'd guess you also could set the SPRING_PROFILES_ACTIVE environment variable like so:
$ heroku config:set SPRING_PROFILES_ACTIVE=test
Adding config vars and restarting myapp... done, v12
SPRING_PROFILES_ACTIVE: test
$ heroku config
SPRING_PROFILES_ACTIVE: test
$ heroku config:get SPRING_PROFILES_ACTIVE
test
$ heroku config:unset SPRING_PROFILES_ACTIVE
Unsetting SPRING_PROFILES_ACTIVE and restarting myapp... done, v13
In case you are using the #WebIntegrationTest or #IntegrationTest you can set the profiles as property value with the annotation.
Looks like this:
#RunWith(SpringJUnit4ClassRunner.class)
#WebIntegrationTest({"spring.profiles.active=test"})
public class MyWebIntegrationTests {
// ...
}

Resources