Any changes to make to use the qa.db.properties file while deploying the WAR file on to the Tomcat server running on unix based QA server? - spring

There are 3 environments: Dev, QA and Prod. And in Github, 3 environment-specific-properties-files namely dev.db.properties, qa.db.properties and prod.db.properties are available in the spring based application code base.
There in the code base, inside the context.xml file, the url and passwords are mentioned in such a way to use the db properties from the environment specific properties file, during or after the deployment of the app.war file on the apache tomcat server running on each of the environments. Below, is the abstract view of context.xml and the env. specific properties files:
context.xml- url="jdbc:oracle:thin:##dbhost##:##dbport##/##dbservicename##" password=##dbpassword##
dev.db.properties and qa.db.properties are having their own dbhost, dbport, dbservicename respectively.
My question is, during or after the deployment onto the individual environments, how would the tomcat server, running on each of the environment, decides which environment specific file to pick. For e.g. suppose one need to deploy the app.war file, which consists of both the properties files, onto the QA environment, then how would the Tomcat server which is running on the QA environment decides that it need to pick the qa.db.properties file and not the dev.db.properties file?
Is it a case that the tomcat server's context.xml file in QA environment is configured in such a way to pick the qa.db.properties file only?
Thanks in advance!

Related

How to change some java variables before deploying on a remote server?

I am currently building a java web application (with netbeans).
I use Jenkins to create a release version with the following pipeline (for Jenkins):
Build -> Test -> Deploy (to a remote test webserver)
Build and Test are OK but I have a question about the deploy job.
The deploy job is currently taking my previously generated .war file and simply transfer it to a remote web server (with the "Deploy to container" plugin).
But I would like to change the database parameters of my web application first ! (in order to use another remote test database).
I would be glad to modify the java file with shell command but I can't because my .war is only composed of the compiled .class java.
So how could I change some of my web application java code (for database credentials) from the .war file before deploying it to the remote web server ?
If you have multiple environments which have different databases, then the best way to handle this would be application with command line parameters. You can modify your java application to read the command line parameters and use these parameters in application.
For example --dburl = <database url> --dbusername= <db username>
And the another way will be take these paramters from environment variable. And define these variables in the system where you are deploying the applications.

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

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

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.

Jenkins CI: Where and how store configuration files?

I am in process of moving configuration parameters out of Java application. I discover that the best approach is to extend your classpath and use .properties files (leave ZooKeeper alone for another requirement).
So my WAR file no longer have any hosts/IPs/URLs, users/passwords.
DevOps distribute configs manually across test, stage, stable installations.
Now time for Jenkins to run tests. But they fail as there are no required .propeties files in classpath.
How can I load this config files to Jenkins and how to make in available in test classpath?
maven-surefire-plugin allow extending classpath and passing system-properties.
So only question how to get separate directory in Jenkins hosting server and load files to this directory and create alias/placeholder/envvar per build job to refer to this path in build config.
This job can be done with SSH access, but I think that this is "wrong way". I expect that this can be done via Jenkins UI (any manager can upload file in WEB browser).
UPDATE I have no requirements for distributed slave/master builds but it whould nice to have solution that migrate configuration files to slaves automatically...
In this way sshing to host or ftp/scp - bad thing.
I read most of Jenkins docs, ask at mail list and IRC. Yea - Jenkins community is silent. At docs I found link to Config File Provider Plugin, after that I visit http://builder.evil.com/jenkins/pluginManager/available page and look for config keyword.
There are a lot related plug-ins with various usefulness to my subject (most useless first):
https://wiki.jenkins-ci.org/display/JENKINS/Envfile+Plugin - This plugin enables you to set environment variables via a file.
https://wiki.jenkins-ci.org/display/JENKINS/Credentials+Binding+Plugin - Allows credentials to be bound to environment variables for use from miscellaneous build steps.
https://wiki.jenkins-ci.org/display/JENKINS/Environment+Script+Plugin - Allows you to run a script before each build that generates environment variables for it.
https://wiki.jenkins-ci.org/display/JENKINS/EnvInject+Plugin - This plugin makes it possible to have an isolated environment for your jobs.
https://wiki.jenkins-ci.org/display/JENKINS/Copy+Data+To+Workspace+Plugin - Copies data to workspace directory for each project build.
https://wiki.jenkins-ci.org/display/JENKINS/Copy+To+Slave+Plugin - This plugin allows to copy a set of files, from a location somewhere on the master node, to jobs' workspaces. It also allows to copy files back from the workspaces of jobs located on a slave node to their workspaces on the master one.
https://wiki.jenkins-ci.org/display/JENKINS/Config+File+Provider+Plugin - Adds the ability to provide configuration files (i.e., settings.xml for maven, XML, groovy, custom files, etc.) loaded through the Jenkins UI which will be copied to the job's workspace.
Only last plug-in - Config File Provider Plugin allow editing configs via Jenkins WEB interface. And it have brother - Managed Script Plugin - for uploading/managing/editing custom scripts. No question now I use Config File Provider Plugin!
You should keep the configs required for the tests together with the rest of source code, so that after compilation, your unit tests can run.
After deploying the .war, the DevOps team should overwrite the in-war configs with whatever per-environment configs that they have.

Resources