Pick up the environment specific properties file at run time - java

I want to pick up the environment specific properties file at run time from class path
I am still learning Spring Boot,
we can do it using environment variables or vm arguments or put in application.properties in maven run configuration
However we will always have to change the code at the time of deployment for a specific env if we put it application.properties.
I want to pick it up at run time without modifying the code at all.

Use spring profiles. Create application.properties for each profile like below:
application-dev.properties
application-prod.properties
Keep the application.properties as the master copy. If a property is missing in the profile-specific file then it will be picked from the master application.properties file as a fallback.
Then either set the following in application.properties or set as an environment variable or as a system property to activate a profile:
In application.properties:
spring.profiles.active=dev
Environment variable:
export spring_profiles_active=dev
System Property:
java -jar -Dspring.profiles.active=dev xyzapp.jar

I guess you can try System.setProperty() to set something at application level. But if you don't reset it will remain throughout application.

Related

Use single profile-specific property file from multiple application.properties files

I have a few spring-boot microservices and I want to use a single profile-specific property file for all the microservices. profile-specific property file should be outside of the jars.
example:
The application-common-profile.properties file and jar files are inside the same folder
java -jar Microservice-1.jar --spring.config.location=classpath:/application.properties --spring.profiles.active=common-profile
java -jar Microservice-2.jar --spring.config.location=classpath:/application.properties --spring.profiles.active=common-profile
the above commands won't take the common-profile properties. please help to achieve this. Thanks.
IMPORTANT DETAILS
This jar file doesn't contain 'application-common-profile.properties' file. this file resides outside the jar but in the same folder. if I put my 'application.properties' file inside the same foder then it is working(retrieving the properties) with the below command.
java -jar Microservice-1.jar --spring.config.location=C:/folderpath/ --spring.profiles.active=common-profile
I can place other microservices 'application.properties' files in same folder with different names(ex: application-microservice-2.properties). and also the profile property files with different names.(ex: application-microservice-2-common.properties ) It's okay having different application.properties files. but need to have one common profile property file.
FIXED
I added common profile property file(application-common.properties) and jars in same folder and run below commands simply and it is working. I think adding unnecessary arguments was the problem.
java -jar Microservice-1.jar --spring.profiles.active=common
java -jar Microservice-2.jar --spring.profiles.active=common
If your application.properties file is bundled in your jar, then simply adding the profile-specific property file to your working directory will allow it to be picked up. However, when you set spring.config.location you're overriding the path that Spring will look up these properties from, you should drop this, it's not necessary. Spring will look in your working directory for the properties files by default if they're not bundled in the jar.
Personally, I would avoid trying to maintain the property files in the environments in favor of environment variables.
Bundle your jar with the top-level application.properties included in it, and for the variables that are different given the environment, set environment variables for them.
e.g. if you want to override spring.datasource.driver-class-name, set the environment variable SPRING_DATASOURCE_DRIVER_CLASS_NAME. I think you'll find this approach is far more flexible.

Springboot application not using the correct .properties file

I have a simple Springboot app that can be ran with the command: ./mvnw spring-boot:run. This works fine if I put the URI to my database inside of the application.properties file but the problem is that this file is used by Heroku, and is not meant for my local use.
So I came across a Stackoverflow answer that said I could simply make another .properties file but name it application-dev.properties and then when I run my app, the correct .properties file will automatically be chosen when I set the active profile to dev.
So I tried this by doing the following:
Make the application.properties file use the environment variable from Heroku since this is the .properties file I do NOT want to use locally.
I created a .properties file called application-dev.properties that has this line in it:
spring.data.mongodb.uri=mongodb+srv://MY_NAME:MY_PASSWORD#springbootcluster.v1maw.mongodb.net/Employees?retryWrites=true&w=majority
I run the app like this: ./mvnw spring-boot:run -Dspring.profiles.active=dev
The app fails with a ton of different errors because it is trying to use the application.properties file and not the application-dev.properties file
Part of the error message:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'employeeController': Unsatisfied dependency expressed through field 'employeeRepo';
ERROR MESSAGES
-Dspring.profiles.active is setting the spring.profiles.active system property in the JVM that's running Maven, not the JVM that's running your application. To fix the problem, use the spring-boot.run.jvmArguments system property to configure the arguments of the JVM that is used to run your application:
./mwnw -Dspring-boot.run.jvmArguments="-Dspring.profiles.active=dev"
Alternatively, there's a property specifically for setting the active profiles which is slightly more concise:
./mvnw spring-boot:run -Dspring-boot.run.profiles=dev
You can learn more in the relevant section of the reference documentation for Spring Boot's Maven plugin.

Custom application properties in spring boot using IntelliJ

I'm trying to use application properties, other than application.properties, say application_local.properties within resources directory.
So that I can have 2 properties files, one for local and other the server.
As mentioned in many blogs, I should use below command:
spring-boot:run -Dspring.config.location=/Users/myuser/work/MyProject/my-app/src/main/resources/application_local.properties
But this is not working, it is still fetching values from application.properties.
What am I missing, please suggest?
Thanks
1- Follow the naming convention application-{profile}.properties
application-local.properties
2-set profile
-Dspring.profiles.active=local
Briefly, you can use these two links:
How to load property file based on spring profiles
spring-profiles
-Dspring.profile.location takes directory as input. The purpose of this property is to specify additional directory location to keep your property files.
You are using property file name in your command.
Refer to detailed # Answer at other thread here
Instead you can use as suggested by #mehardad
The -D option will send parameters to Java virtual machine. In order to send parameters to Spring boot, the command option of '--' must be used.
Example:
Suppose, there is an option named 'spring.profiles.active' defined in the application.properties file as follows:
spring.profiles.active=dev
This option can be overwritten using command line parameter as follows:
java -jar application.jar --spring.profiles.active=prod
Use Spring profiles and choose at runtime, locally would
-Dspring.profiles.active=local
The property file should be called application-local.properties

Tomcat does not exclude JARs specified in tomcat.util.scan.StandardJarScanFilter.jarsToSkip

I'm trying to set a Tomcat configuration setting through an environment variable. It works for some, it seems not to work for others.
Specifically I'd like to exclude certain JARs from being scanned for TLD files.
Here's my dockerfile:
FROM tomcat:8.5.34-jre8
EXPOSE 8080
EXPOSE 8000
ENV CATALINA_OPTS="-Djava.util.logging.config.file=/usr/local/tomcat/webapps/catalinaLogging.properties -Dtomcat.util.scan.StandardJarScanFilter.jarsToSkip=jackson-module-jaxb-annotations-2.7.0.jar"
COPY /target/my.war /usr/local/tomcat/webapps/my.war
COPY /catalinaLogging.properties /usr/local/tomcat/webapps
CMD ["catalina.sh", "jpda", "run"]
The catalinaLogging.properties is successfully applied because I see the difference in logging during startup. The tomcat.util.scan.StandardJarScanFilter.jarsToSkip does not seem to be applied though, I still see the following in the output:
Do I have to set the tomcat.util.scan.StandardJarScanFilter.jarsToSkip property differently?
Do I have to use a different property altogether?
tomcat.util.scan.StandardJarScanFilter.jarsToSkip can't be configured through the CATALINA_OPTS environment variables and has has to be configured in the catalina.properties instead.
The location of the catalina.properties however is configurable through the -Dcatalina.config=/path/to/folder as described by Andreas.

How to configure logging when running a JAR?

I am new to Java logging API and need some help with this problem:
While creating the application, my config file was stored in the project root folder, so I used -Djava.util.logging.config.file=logging.properties switch to run the program.
But then I exported the executable JAR.
How to configure the logging now? It doesn't work, when I specify the path to config file with the -D switch.
You can't specify JVM arguments into the MANIFEST.MF file so you have to specify the logging properties at the command line or with a shortcut :
java -Djava.util.logging.config.file=logging.properties -jar yourjar.jar
Otherwise you could package a properties file(logging.properties in your case) in the JAR, read that at
startup and put those settings into the system properties.
The javadoc says:
In addition, the LogManager uses two optional system properties that
allow more control over reading the initial configuration:
"java.util.logging.config.class"
"java.util.logging.config.file"
These two properties may be set via the Preferences API, or as command
line property definitions to the "java" command, or as system property
definitions passed to JNI_CreateJavaVM.
If the "java.util.logging.config.class" property is set, then the
property value is treated as a class name. The given class will be
loaded, an object will be instantiated, and that object's constructor
is responsible for reading in the initial configuration. (That object
may use other system properties to control its configuration.) The
alternate configuration class can use readConfiguration(InputStream)
to define properties in the LogManager.
So, either use the java.util.logging.config.file system property, and store the config file out of the jar file (which is probably a good idea if you want to be able to customize the logging properties in order to debug or analyze some weird behavior), or store the config file wherever you want (in the jar file, for example), and use the java.util.logging.config.class system property to load and instantiate a class that will read the file in the jar file (Using Class.getResourceAsStream()).
I know it's little late to answer this question but I ran into this issue few days back with the runnable jar and I solved it like this:
java -Djava.util.logging.config.file=logging.properties -cp test.jar com.sample.test.Main
where test.jar is the name of your jar and com.sample.test.Main is the fully qualified name of your main class.

Categories