SpringBoot application with multiple application.properties running under Tomcat - java

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

Related

How can I enable a resource file to pick up enivronment variables like application.properties does in spring boot

I have a resource file in spring that I want to be populated with environment variable, similar to how spring sets up application properties on startup. In application.properties I have something like this
app.foo.enabled=${app_foo_enabled}
In my environment variables in .bashrc file I have
export app_foo_enabled=false
On Startup the "app.foo.enabled" property takes the value false.
How do I enable this for other files in my resource folder in my spring app.
My approach currently is to do file manipulation..but I am looking for a more direct way.

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.

maven: can't override server.port for tomcat server

I am new with Maven/SpringBoot and trying to deploy a repository with different Tomcat Server port.
By default, I would be happy to run tomcat on :8080. But today, I wanted to add Jenkins pipelines to my project and I deployed tomcat on :8080 (with jenkins on it) before my spring cloud gateway repository.
Now, once I try to deploy gateway, compiler obviously says address :8080 already in use.
Now, I want my gateway to deploy Tomcat on another port, (or use already-existing tomcat on :8080 if possible?) so I wanted to deploy it using this command:
$ mvn spring-boot:run -Dserver.port=8181
However, same error based on :8080 happens to appear:
[ERROR] Failed to execute goal
org.springframework.boot:spring-boot-maven-plugin:1.5.8.RELEASE:run
(default-cli) on project crw-gateway: An exception occurred while
running. null: InvocationTargetException: Connector configured to
listen on port 8080 failed to start.
I tried putting server.port=8080 to application.properties or application-dev.properties files but I cant override it.
Any ideas? How can I override the port? Is there a possibility that I can use already existing tomcat-server on :8080?
Thank you for your time!
EDIT: I had my configurations under ~/config folder. There, I had gateway.properties, which included the line server.port=8080. It has overridden the command line interface as the accepted answer asserts. Changing it to 8888 worked.
According to Spring Boot documentation :
Spring Boot uses a very particular PropertySource order that is designed to allow sensible overriding of values. Properties are
considered in the following order:
Devtools global settings properties on your home directory (~/.spring-boot-devtools.properties when devtools is active).
#TestPropertySource annotations on your tests.
#SpringBootTest#properties annotation attribute on your tests.
Command line arguments.
Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property).
ServletConfig init parameters.
ServletContext init parameters.
JNDI attributes from java:comp/env.
Java System properties (System.getProperties()).
OS environment variables.
A RandomValuePropertySource that has properties only in random.*.
Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants).
Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants).
Application properties outside of your packaged jar (application.properties and YAML variants).
Application properties packaged inside your jar (application.properties and YAML variants).
#PropertySource annotations on your #Configuration classes.
Default properties (specified by setting SpringApplication.setDefaultProperties).
So your problem is that your command line (4.) can not override the application.properties file configuration (13., 14., 15.).
If you want to override the server.port property, you need to ensure to respect this order in your configuration.

separate application.properties from .war for tomcat container

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

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