Java config - dev & prod environments - java

I have several java projects which use hibernate to persist to a DB. At the moment, I have hibernate.properties file embedded in one persistence project.
However, I would like to be able to specify to have two different files one for prod and one for dev.
What is the best practise....should I embed the config files into my jars? How do I build my projects to use the correct properties with Maven?
Thanks.

You probably want to have the key database properties (name/user/password) set as properties at runtime either from a properties file that's itself specified as a property (the URL of the file can be specified as a property) or a set of properties (a property for each of name/user/password). The former is probably the preferred approach.
You could ask your system/database administrator type what they like :)

Related

How I can change my application.properties file?

I have a Spring Boot Application, which have a connection to a MongoDB database.
The connection I can configurate in the server.properties.
For the current development I can use the localhost.
But for the later server implementation, I need configurate a new server.properties.
How I can change it, if I start the programm, please use the development.server.properties or the consumer.server.properties with different server connection?
Option 1:
For most real word applications, the properties are not directly packaged with the sources as it can contain sensible info (database password for instance). A simple solution to this, is to put application properties on filesystem and then reference them with the spring.config.location argument
java java -jar demo-0.0.1-SNAPSHOT.jar -Dspring.config.location=/etc/demo/application.properties
this way you keep application.properties away of the packaged jar and you can parse and subsitute values into the application.properties file with your deployment toolchain (like ansible) for each environment accordingly.
some useful doc can be found here: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
Option 2:
use profiles. In classpath resources you can have a main application.properties which stores the properties which are common for all environments and then one application-{env}.properties for each environment with specific keys e.g application-dev.properties, application-int.properties, application-prod.properties...
At startup you specify the active profile with then environment variable spring.profiles.active :
java -jar -Dspring.profiles.active=prod demo-0.0.1-SNAPSHOT.jar

How to externalize configurations for multiple webapps inside a tomcat server?

I'm running a standalone tomcat webserver, with multiple different web applications (war files).
Question: I want to externalize some sensitive application.properties fields like database accounts, each separated for every application.
I could provide the following property at startup:
--Dspring.config.additional-location=/etc/java/
Problem: each webapp would load the same /etc/java/application-production.properties file then! So that doesn't help.
Question: how can I separate them by application, so each of the webapps loads it's own additional external file?
Like on the testserver:
/etc/java/myapp1/application-test.properties
/etc/java/myapp2/application-test.properties
Prod:
/etc/java/myapp1/application-production.properties
/etc/java/myapp2/application-production.properties
one way to go is, you create key-value files, like test1.env, test2.env.... The content would be:
DB_URL=test1DB
DB_USR=hi
DB_PWD=pwd
...
In your application.properties you can use placeholder like db.url=${DB_URL}
When you start your application, using a start (shell) script, export the variables in *.env, and source the given env file, so that the right values can be filled in application.properties.
Create a new file that only contains the sensitive data:
/src/main/resources/config/application-production.properties
And add a .gitignore so that this specific file will not be commited for version control.

Add and Replace placeholder in XML from property files

I am developing a web application which will be deployed in different environments like Dev, Test and Production. Some of the configurations will be specific to environments and so I need to change the configurations in the property files with respect to the environments where the project is deployed.
I added the Environment variable in machine and obtained it using the method
System.getEnv("Environment")
which would return the value like, dev, test and prod and I load the respective property files (File names are dev-config.properties, test-config.properties).
I am implementing the PicketLink libraries in jBoss AS to integrate the application with SSO-SAML. One of the configurations is to add a file named picketlink-idfed.xml, where I mention the IDP URL and application url. Both the URLs will be different for environments. I cannot have different file names like dev-picketlink-idfed.xml and so I cannot follow the above approach of using different files.
Question is that I need to use the same file picketlink-idfed.xml, just by adding the placeholder and replace it with the respective values from the property files. Attached the sample content of picketlink-idfed.xml.
<IdentityURL>https://idfed.test.com.au/adfs/ls/idpinitiatedsignon.aspx?LoginToRP=https%3A%2F%2Fapp.test.com.au%2Fdisplays%2FHome.action
</IdentityURL>
<ServiceURL>https://app.test.com.au/displays/Home.action
</ServiceURL>
In the above line the values for tags IdentityURL and ServiceURL will be changed for different environments. Can you please tell me on how to address this issue?
Note: For time being, I am replacing the contents for every deployment, which is not good practice. Also, I am not using Maven or Ant build files. I cannot use these due to insufficient time.

Java Properties - Global and local properties

So I'm beginning to use the Java Properties class in order to set key-value pairs for my project. The way I'm designing my project is so that there are default properties which will be created using a config file as well as another config file for either overwriting or adding additional properties. The default config file will be in my Eclipse MainFramework project while the other config file will be in the local project where tests are stored.
MainFramework
Validation
TestProject1
TestProject2
In this example, MainFramework has the default config file and each TestProject may or may not have it's own local config file. Is there a way to have my desired functionality through Java's Properties class.
The java properties object is a Hashtable. If you read the properties for your main configuration file and then read a second properties file into the same object it will override the existing properties if they exist in both places, or add new ones if they don't already exist. Properties that are only found in the original file will remain as well.
How about using a 3rd party configuration library to achieve this?
Typesafe's config supports the usage of properties files, and can handle merging a global configuration with a subconfiguration, among many other features.
Apache commons configuration also supports property files as configuration sources and mechanisms for combining different sources.
I personally found Typesafe a bit easier to understand and use, but have a look at some examples to see what fits your style. They are both available through maven.

How to differentiate between test and production properties in an application?

We're developing a big J2ee e-sales solution. It's got a lot of integrations: CMS, ERP, Mail server etc. All these systems are divided into test and production environments.
We need to deploy our application to our test servers with test configuration and when deployed to our production servers it should use the production configuration. How do we make our application select the correct properties?
The thing we've tried so far is this:
All our property files contain test properties and production properties
test.mvxapi.server = SERV100TS
test.mvxapi.username = user
test.mvxapi.password = password
test.mvxapi.port = 6006
test.mvxapi.cono = 600
mvxapi.server = SERV10001
mvxapi.username = user
mvxapi.password = password
mvxapi.port = 6001
mvxapi.cono = 100
The Util that reads these properties has a switch: isTest() which prefixes the key with "test."
public String getProperty(String property)
{
return properties.getProperty(prefix + "" + property);
}
The switch is set by another property which is created by our build server. When the .EAR is built the script for our production servers injects (input to build.xml) "isProduction=true" into system.properties.
<propertyfile file="${buildDir}/system.properties">
<entry key="isProduction" value="${systemType}"/>
</propertyfile>
I'm not sure this is the best way to do it. If for some reason "isProduction=false" is committed wrongly to our production environment all hell is loose.
I've read people have properties locally on the server. But we really don't want to have files spread around. We have cluster of production servers. Making sure every server has the right property file doesn't seem fail-safe
What you want to avoid is having the config file inside the EAR, the problem with this is that you need different EAR's for different environments, and also, changing the config file requires a rebuild.
Rather deploy the same EAR to every server but configure each server with a different URL resource. iow, add a JNDI URL resource to all the servers you deploy to that point to the config file for that resource. If you have read only SVN access to your repo then create the config files on the svn repo, or any repo you can access via a URL. The cool thing here is that all your configuration is centralized and thus managing them is easy.
What I've done (by customizing with spring) is make sure that JNDI URL resource optional. So, if it's there, the app will use it, if not, it won't. The app starts up whether it's there or not. That way, even when running with no JNDI resource available, the app still works (development environment for example).
You deploy an EAR? Then put the properties needed in JNDI.
I can't say if this is the best way, however, what we do is include a client and server jar which houses the properties accordingly. We then include those jars in the EAR file. So during our build process we include the appropriate (QA, TEST, PROD) jars for the environment in which we are deploying to.
The downside is we have to manage three sets of environment jars and the build team has to be careful not to deploy the incorrect one. In fact, it has happened once that we had a PROD jar deployed to our QA environment and QA data was getting put into production....yes that sucked and was a major mess to clean up.
I will be watching this discussion because I often wonder how we can make this process better/safer. Great Post +1
In a previous J2EE project, we've been doing exactly that. The build process (an ant script) put together the right config files, added them to a certain jar which was then put into the EAR file for production environments, test, training, QA, etc.
The file name of the EAR file contained the name of the target environment, so it was basically impossible to deploy a file to the wrong environment. If we built for target 156p2 (factory 156, production env. 2), this would be part of the file name of the EAR file and ant would include config_156p2.xml. If the target was incorrect, the EAR file's name would be wrong and as a last failsafe the guy who deployed it would notice.
The build file had to contain this: one ant target to start the build for each environment which would set a property that told ant which config file to include.
The only difference between the EAR files would then be the config files. Everything else was identical. There is a possibility, of course, that someone might have written a wrong value to a config file for a certain environment. However, in practice this never happened in several years, even with some pretty junior developers and about fifteen target environments (different test, QA, training and production servers in different countries).
We have 3 folders for this purpose in our projects, each one contains configuration files (filenames are the same between the folders):
personal: contains paths to test db, server, etc
test: contains paths to the servers shared with my colleagues
production: contains... well you guessed
When I build my project I add the suited profile to Intellij Idea project build, in the desidered module, this basically means that i am adding a different folder to the project structure, but because filenames are the same what changes are only profile properties.
Very old post still responding in case someone checks it. In each application server you can set System properties e.g
Wildfly Management Console --> Configuration --> System Properties
There I add a variable SERVER_ENVIRONMENT with value as DEV/UAT/PROD.
In my java code I use:
System.getProperty ("SERVER_ENVIRONMENT")
which gives me value from the server.
Like #Alberto-Zaccagni said you can have separate folders with properties files that exist only in respective environment. Your code checks for existence of folder starting with PROD then UAT then DEV and when it finds a path exists it uses the properties files there.

Categories