Add and Replace placeholder in XML from property files - java

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.

Related

Load all property files with unknown names from a directory in Spring Boot

I have a Spring Boot (2.6.5) application that has a build in default property file (contained in the jar).I also specify an external property file by using --spring.config.additional-location=/data/config/myapp.properties.
This works as expected, both files are loaded and properties of both files are used where the external pairs override the internal in the case of duplicate keys.
Now I want to split up the myapp.properties into multiple smaller property files. The reason for this is that they are created by a Kubernetes configMap, and some parts are used in multiple applications, so it makes sense to split those in smaller files instead of duplicating everything.
I tried to set the parameter to a directory, like --spring.config.additional-location=/data/config/ and then placing the various .properties files in this directory. However, when I do this, Spring will no longer load the files. So it seems that when I don't specify a specific filename, it only scans for application.properties.
How can I configure Spring to look for and load all files of type .properties in the given directory? I could specify each file individually, but that would require me to always keep track of the files that are present which is difficult to maintain.
Reference: features.external-config.files.wildcard-locations
In your case if you use --spring.config.additional-location=file:data/config/*/ then the files like data/config/first/application.properties and data/config/second/application.properties will be loaded.
Note: If you have a different config.name, like --spring.config.name=myapp
then all the directories should contain myapp.properties

Log4j2 read properties from an external property file

I have an application that i have to deliver in a packaged JAR which is then run by the client in a complicated environment that makes editing env variables or JVM arguments very cumbersome (additionally client is not too technical). Currently we are using some external proeprty files for configuring the database and so on and this is going well so far.
I would like to allow the client to configure some aspects of Log4j2 using these properties files, i can see that Log4j2 allows multiple ways of performing property substitutions https://logging.apache.org/log4j/log4j-2.1/manual/configuration.html#PropertySubstitution
I can also see that it is possible to load property bundles but if i understand the docs correctly these bundles need to be loaded from classpath and i have not stumbled upon a possibility of define this properties file by giving its direct path (such as "load the properties file /tmp/myconfig.properties").
So ultimately - is it possible to use variables from an external .properties file that is NOT in classpath but in a specified filesystem location? Or maybe some other way exists to load this data from external file? (i already noted that using env variables or jvm arguments is out of the question in my case).

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.

Java config - dev & prod environments

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 :)

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