I'm working on a project and have a use case where I need to provide application.properties file for Spring Boot from outside the JAR.
According to Baeldung, the priority order for picking up the application.properties is
A /config subdirectory of the current directory
The current directory
A classpath /config package
The classpath root
The issue with first two is I'll need to navigate to the directory containg the configs to run the JAR. It sounds no issue when working on local but wont be a feasible solution when deploying on remote hosts as through CI/CD frameworks.
I'm trying to find a mechanism using classpaths and avoid using spring boot's command line options mentioned over here or setting up environment variables.
I'm unable to figure out how to setup classpath while running FAT JAR and specify configs all together. If you can, please help me figure it out!
Thanks in advance :)
EDIT : I understand there are ways to achieve this using Spring Boot's command line options such as spring.config or loader.path etc.
I was trying to find a more implicit solution based on classpath and directory structures only to make it less coupled with the fact that Spring Boot is being used.
According to the Spring docs, you can define external config locations using the spring.config.location property. More specifically:
If spring.config.location contains directories (as opposed to files),
they should end in / (and, at runtime, be appended with the names
generated from spring.config.name before being loaded, including
profile-specific file names).
Files specified in
spring.config.location are used as-is, with no support for
profile-specific variants, and are overridden by any profile-specific
properties.
Config locations are searched in reverse order. By default, the
configured locations are:
classpath:/,classpath:/config/,file:./,file:./config/.
The resulting
search order is the following:
file:./config/ file:./ classpath:/config/ classpath:/
When custom
config locations are configured by using spring.config.location, they
replace the default locations. For example, if spring.config.location
is configured with the value
classpath:/custom-config/,file:./custom-config/
the search order
becomes the following:
file:./custom-config/ classpath:custom-config/
Alternatively, when
custom config locations are configured by using
spring.config.additional-location, they are used in addition to the
default locations.
Additional locations are searched before the
default locations. For example, if additional locations of
classpath:/custom-config/,file:./custom-config/
are configured, the
search order becomes the following:
file:./custom-config/ classpath:custom-config/ file:./config/ file:./ classpath:/config/ classpath:/
An example usage for a directory containing your external configi would look like:
java -jar myproject.jar --spring.config.location=file:/custom-config-dir/
Or directly to an external config file:
java -jar myproject.jar --spring.config.location=file:/custom-config-dir/custom-config.properties
Specify custom config location as VM argument is another option.
java -Dspring.config.location=<config-dir-path> -jar demo.jar
Related
Is there a way to read the updated changes in application.properties without repackaging the jar in Quarkus? I could not find anything related in the official documentation at https://quarkus.io/guides/config-reference. So I am assuming that the uber jar has the application properties built in. So is there a way to override those configs while running the jar?
Edit: What I mean by overriding is: Is there a way to specify the path of the config file that the jar reads while running the jar. Something similar to java -jar app.jar -DConfig='/path/to/application.properties'.
In Quarkus some of the configurations are fixed at build time, (the once in the documentation with the lock). Others are not, this ones you can change them at runtime using several methods, for example, using environmental variables or properties in the launch commands.
Check this links for more information:
https://quarkus.io/guides/config#build-time-configuration
https://quarkus.io/guides/config-reference#configuration-sources
As you can see in the configuration-source section, quarkus will firstly search in system properties and other sources rather than in the application properties file, there is one possibility for you to change the value of your properties.
I have a web application created in maven. I am using tomcat server on my local as well as on dev unix box. I need to use two different .properties file like local.properties and dev.properties (may be in different folders). My doubt is 'How can we configure the tomcat of local and the tomcat of unix box to read different properties file at the time of deployment?' What are different ways for it.
The easiest and out of the box solution you can use with spring is to have two files, named application-dev.properties and application-prod.properties which will be activated if if you pass -Dspring.profiles.active=dev or prod. You pass this parameter when deploying the app. No configuration, no annotation, no xml. As long as you keep the naming convention application-something.properties
Easiest is pass a system parameter to your JVM to identify the environment, then package up a dev.properties and local.properties in the jar.
#PropertySource(value = {"classpath:local.properties", "classpath:${ENVX}.properties"}, ignoreResourceNotFound = true)
Use a -DENVX=dev for dev (add to your tomcat script), if it is not specified local.properties will be picked up.
I am trying to create an environment where the application build remains same across environments. To support this I've externalized any property files to be read from an external directory e.g.$CATALINA_BASE/conf/app1/config
We use ehcache for caching (for CAS) and for replication between instances I seem to get the errror if the ehcache-replicated.xml is not present in the WEB-INF/classes directory. I've tried updating the setenv.sh of Tomcat so:
CLASSPATH=$CATALINA_BASE/conf/app1/config/ehcache-replicated.xml
export CLASSPATH
I also tried adding to JAVA_ENDORSED_DIRS but none of them seem to work. Any ideas?
A classpath entry is a directory, not a file. So try CLASSPATH=$CATALINA_BASE/conf/app1/config, it might work.
I am saying might because Tomcat is applying class loader isolation. A war won't see the classpath of the application server. So, it depends where you are setting the classpath.
In general, adding the classpath entry in catalina.properties shared.loader works. But that's from the top of my head.
I have put my logger.properties file inside src/java/resources directory. Using this file I configure different levels of logging (for both console and to file). Now when I make a jar file of my project, how can I configure or change the logging level because then I won't have access to the logger.properties file.
Basically I want to provide users the ability to set the logging level before the run the jar.
In general you shouldn't keep the configuration file inside the jar.
Instead, place it somewhere (depends on your distribution, usually it can be something like $YOUR_PROJECT_HOME_DIR/conf folder). When running the application specify the following property:
java.util.logging.config.file=<PATH TO PROPERTY FILE GOES HERE>
Here is a good tutorial on java.util.Logging that covers this point among others.
You could use enviorment variables https://docs.oracle.com/javase/tutorial/essential/environment/env.html
You could also take the logging level you want to use as an argument for your program.
https://docs.oracle.com/javase/tutorial/essential/environment/cmdLineArgs.html
Hi How would you solved that?
I have one application in which I have a few configuration files, I make war file and deploy it on the tomcat.
But at the same time I have to make the war file and deploy the same application under different context and/or a server with modified configuration files.
I can create my own task in ant, and replace needed paramaters but there can be possibility of moving to maven, and anyway I'm not sure about it. Or can I use something like spring's property place holder configurer or jgroups
Spring can handle this quite well in a variety of ways. The approach I found most useful and flexible is to setup in each environment a system variable that specifies trhe environment name e.g. test, dev, int, prod, etc.
Spring can then use this system variable to load the correct property files. Depending on your needs these property files can be bundled with the app or loaded from an external location. Theres an example of a similar approach here:
http://www.developer.com/java/ent/print.php/3811931
I'd deploy Spring apps packaged as a WAR to either Tomcat or WebLogic without any changes. It would contain both the META-INF/context.xml for Tomcat and weblogic.xml for WebLogic. No worries, no changes.
What we did was create a folder structure for the properties that were environment specific. Under that folder we created folders for each specific environment targeted for deployment, including local development. It looked like this:
Project
\
-Properties
\
-Local (your PC)
-Dev (shared dev server)
-Test (pre-production)
-Prod (Production)
In each folder we put parallel copies of the properties/config files and put the different configurations only in the file in the appropriate folder. The secret was to control the classpath of the deployment environment. We defined a PROPERTIES classpath entry on every server. On Prod, it would be set to "$ProjectDir/Properties/Prod" while on Test the same variable would be set to "$ProjectDir/Properties/Test".
This way we could have database connection strings for the dev/test/prod database preconfigured and not have to checkout/in the property file each time we wanted to build for a different environment.
This also meant that we could deploy the exact same .war/.ear file to Test and Prod without rebuilding. Any properties that weren't declared in the properties file we handled in a similar way by using the same JNDI name in each environment but using values that were specific to that environment.
http://www.gifnoc.com/config could help as it stores configuration on a central place and the client is pulling from it for different environments