separate application.properties from .war for tomcat container - java

When I use executable .jar for my project, I can put my application.properties file into same folder as my .jar, and all my property values will be reading from extended application.properties file.
My question is: It is possible to make like this for .war and tomcat server?
[UPDATE]
The answer is: On standalone tomcat you would have to put an application.properties in <tomcat>/bin
Thanks to #Strelok

You can run your application with spring.config.location property set to the path to your properties file using the file: protocol:
# will look for /etc/myapp/application.properties
-Dspring.config.location=file:/etc/myapp/
# will look for /etc/myapp/custom.properties
-Dspring.config.location=file:/etc/myapp/custom.properties
Default config locations that are always searched:
file:./config/
file:./
classpath:/config/
classpath:/
There is a lot more info in the Externalized Configuration section of the documentation for Spring Boot.

Refer Tomcat Class loader for your version of Tomcat to understand what all class loaders are available. Depending upon that, you can add your application properties files to Shared or Common class loader by keeping it in appropriate directory and adding that directory into the class loader entry in catalina.properties file. Tomcat 7 documentation does not show shared classloader, but catalina.properties does have a placeholder for that. If shared works, go for that instead of common Tomcat 7 Classloader

Related

SpringBoot application with multiple application.properties running under Tomcat

I need two application.properties in my Spring Boot App.
I know that using the annotation #PropertySource I can specify more than 1 property files.
I tried to use: #PropertySource({"classpath:application.properties","classpath:external.properties"})
The idea of it is having application.properties with the machine independent properties and this file will be included inside the war file.
The other file (external.properties), will leave in the machine, and won't be included in the war file. Here I want to leave properties like the database connection and so on.
I've already changed catalina.properties for adding the external.properties location into the classpath, but unfortunately when running on Eclipse it doesn't work (complains about the missing database properties.).
If the external properties file will be available in a known location on the machine, then have an environment variable, system property, or command-line argument set up with the path to the file. Then, reference the file in you #PropertySource annotation using file: rather than classpath:
Example: #PropertySource("file:${CONF_DIR}/external.properties")
References:
Spring boot docs on external configuration
PropertySource documentation
Blog post regarding PropertySource

How to use external configuration files with Spring boot deployed in Tomcat 8.5

My Spring Boot application (2.1.1.RELEASE) is deployed as a WAR in a Tomcat 8.5 server under a Debian 9 system. It uses, among others, the following files to configure the application :
myApplication.properties (main configuration file for Spring)
log4j2.xml
Both are under src/main/resources.
My question is about how to configure Tomcat and Spring Boot in a way that allow me to have a directory /home/oliver/conf which contains both of these files, in order to override the defaults defined under src/main/resources (which are then in WEB-INF/classes in the exploded WAR).
Below are the steps I've taken.
First, and as a requirement for the project I'm working on, I changed the default Tomcat base directory to point to another place by editing /etc/init.d/tomcat8 :
CATALINA_HOME=/usr/share/tomcat8
CATALINA_BASE=/home/oliver
My /home/oliver/conf folder, which holds the Tomcat and Spring configs, looks like this :
- Catalina/
- context.xml
- web.xml
- server.xml
- ...
- myApplication.properties
- log4j2.xml
- otherAppConfFile.properties
- ...
Because Spring looks for application.properties by default, I'm using the #PropertySource annotation to specify another file :
#SpringBootApplication
#PropertySource({classpath: myApplication.properties})
public class MyApp extends SpringBootServletInitializer {...}
I've tried to add -Dspring.config.location=file:/home/oliver/conf/myApplication.properties to JAVA_OPTS defined in /etc/default/tomcat8, and it works (overrides the embedded file correctly), but for instance if I try to add file:/etc/oliver/conf/log4j2.xml to the previous JVM parameter, it doesn't work.
I read a bit about Spring "environment profiles" but don't wish to use them if possible.
When I launch Tomcat and issue a ps aux | grep tomcat command, I see all the JAVA_OPTS parameters defined as expected, and I also see the following :
-classpath :/home/oliver/conf:/usr/share/tomcat8/bin/.... -Dcatalina.base=/home/oliver -Dcatalina.home=/usr/share/tomcat8
I'm a bit confused about the way Tomcat's classpath and Spring's are related, and how I should solve this issue.
If the classpath I see at launch includes the /home/oliver/conf directory, why are the files inside not overriding the embedded property files (myApplication.properties, log4j2.xml ...) ? Is the folder seen and added to Spring's classpath ?
EDIT :
As a side note, there might be a variety of files under /home/oliver/conf which would need to be taken into account, for instance log4j2.xml + myApplication.properties + keystore.jks so I'm not sure I can rely on -Dspring.config.location and -Dlogging.config entirely.
What I understand from your question is that you are trying to do something like this.
-Dspring.config.location=file:/etc/oliver/conf/log4j2.xml
I think the property spring.config.location is to provide the location of a properties file for configuration and not log4j2.xml.
You can set the location of the log file in myApplication.properties by setting the value for logging.config like
logging.config=file:/etc/oliver/conf/log4j2.xml
Or else you can try
-Dlogging.config=file:/etc/oliver/conf/log4j2.xml
UPDATE
This is what I do in my production systems. Create a file setenv.sh and enter below command.
export JAVA_OPTS="$JAVA_OPTS -Djavax.net.ssl.trustStore=/path/to/keystore/keystore.jks -Djavax.net.ssl.trustStorePassword=changeit -Dspring.profiles.active=qa -Dspring.config.location=/path/to/config/ -Dfws_log=/path/to/logfile/location -Xms512m -Xmx1024m -Dsecret.key=somesecretkey"
You can add any number of key value mappings in this file and all of them will be loaded when your tomcat starts.

spring-boot and ./config directory

I'm not certain anymore about how Spring-boot exactly handles environment, properties file and config location.
Use case
Below the result docker container of my spring-boot application
Docker container
/
|- spring-boot-app.jar
|- /config/
|--|- application.properties
|--|- logback-spring.xml
I also use environment variables
The problem
The logback-spring.xml isn't read by Spring-boot.
To make it so I HAVE TO add LOGGING_CONFIG=config/logback-spring.xml
Shouldn't Spring-boot look for logback-spring.xml automatically under this directory ?
Thank you
In the Spring Documentation (https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-logging.html) it says:
The various logging systems can be activated by including the
appropriate libraries on the classpath, and further customized by
providing a suitable configuration file in the root of the classpath,
or in a location specified by the Spring Environment property
logging.config.
So if you put the file directly beneath spring-boot-app.jar it should work without configuration of logging.config.
Spring boot automatically loads application.properties and application.yaml from below locations, Values from lower-order overriding earlier ones
The classpath root
The classpath /config package
The current directory
The /config subdirectory in the current directory
Immediate child directories of the /config subdirectory

How to force Tomcat doesn't write data (like logs, temp, ets) to its own root folder?

I'd like to create a desktop standalone application from my Java/Spring web application. I created MSI-installer that copy all required files to C:\Program Files (x86)\App. But tomcat doesn't have permission and can't write to its own folder. How I can configure tomcat so it would write all app-specific data to other folder? I wouldn't like to install my app to C:\App or user dir.
java.io.FileNotFoundException: C:\Program Files (x86)\App\tomcat\logs\catalina.2016-06-18.log (Access denied)
By setting the environment variable CATALINA_BASE to another directory in your tomcat start script you can configure Tomcat to read/put the working data, configuration and stuff from/to another location. If CATALINA_BASE is set, Tomcat will use the folders %CATALINA_BASE%/bin, %CATALINA_BASE%/conf, %CATALINA_BASE%/logs, %CATALINA_BASE%/temp, etc. for the current instance of Tomcat. This is described in more detail in the Advanced Configuration - Multiple Tomcat Instances section of the RUNNING.txt file in Tomcat's root folder.
If you are planning to ship Tomcat with your application and put all Tomcat files to some user choosable folder you should set CATALINA_HOME to this folder. Tomcat will then use this folder as base directory for everything.
However I think, as you mentioned to ship a standalone application based on Spring, you should seriously take a look at Spring Boot. This will allow you to ship a single fat jar containing all of your application's dependencies (including Tomcat). And this application can simply be started by executing the jar file.
If it's just about the log and temp files, you can set the Java system properties java.util.logging.config.file and java.io.tmpdir in the setenv.bat file under %CATALINA_BASE%/bin to make Tomcat use a custom logging configuration and a different temp dir, respectively. That is the file would look something like this:
set CATALINA_OPTS="-Djava.util.logging.config.file=file:///c:/path/to/log/config.properties"
set CATALINA_OPTS="%CATALINA_OPTS% -Djava.io.tmpdir=c:/path/to/temp/dir"
Find and update all occurrences of "$CATALINA_BASE"/logs/catalina.out to custom path in catalina.sh script.

when deployed Spring Boot war in tomcat where should application.yml file should be placed?

When spring boot,mvc war file has been deployed in stand alone tomcat, application.yml is located at $CATALINA_HOME/webapps/demo/WEB-INF/classes/application.yml
Can I move the same to $CATALINA_HOME/conf/Catalina/localhost/dmo.yml ?
In general without using spring boot my configuration file will be located at $CATALINA_HOME/webapps/demo/META-INF/context.xml which can be moved to $CATALINA_HOME/conf/Catalina/localhost/demo.xml
Is the same is possible for application.yml also? Then How?
This will help while re-deploying my config file will be backed-up automatically.
You can change the default location for application.properties/yml files using spring.config.location and spring.config.name properties and their corresponding environment variables. The easiest way is to set the SPRING_CONFIG_LOCATION environment variable:
export SPRING_CONFIG_LOCATION=$CATALINA_HOME/conf/Catalina/localhost/dmo.yml
Check out spring boot documentation for more info on loading property files.

Categories