Multiple web applications in one tomcat instance start with a properties file from another applications - spring-boot

We have multiple web applications in one tomcat instance on 1 server, all running a spring-boot application inside.
Whenever we start tomcat and it starts to boot up all the spring-boot applications we mostly see that each application might use property files/settings from another application.
What especially happens is that we see it sometimes use the database information from other applications being used, resulting in a database which holds tables from other applications. This is scary since we might start a database migration or something.
We also see that the logs are written to the wrong project log file.
We define these settings using a application.properties like (or sometimes application-test.properties or application-secret.properties):
spring.datasource.username
spring.datasource.password
logging.file.name
Anyone have an idea why this is happening?

We found 2 possible causes for this behavior:
if Tomcat is started in a directory where application property files are present, or where application property files are placed in a /config subdirectory, like a WEB-INF/classes directory, these application property files are used by every Spring Boot application deployed in the tomcat instance. To fix this, make sure the Tomcat start script changes the working directory to a directory not containing application property files.
if the 'startStopThreads' attribute of the Tomcat Engine element in server.xml is set to values higher than 1, Spring Boot applications seem to occasionally and randomly use application property files of other Spring Boot applications deployed in the Tomcat instance. When 'startStopThreads' is set to 1, we don't see this behavior.

Related

Can you replace a Spring Boot jar while the application is running?

In our Linux environment applications are restarted periodically (the reasons aren't important here). It would be convenient for us to deploy new versions of an application by copying the application Spring Boot jar on top of the existing (old) jar thereby overwriting it and then simply wait for the application to restart (that is, the JVM running the application to restart).
However, this seems to not work. We get different kinds of errors - sometimes the app just hangs, sometimes we get a ClassNotFoundException. It's as if Spring Boot (or something inside Spring Boot) reopens the jar and expects it to be the same one it was when the application was originally started.
We had a look through Spring's common application properties, but didn't see anything appropriate. Is there a way to make this work? When we were using WAR files we configured the servlet container to unpack the WAR file and run from the unpacked version. Can we do something similar with Spring Boot?
First of all the errors you are experiencing can come from multiple sources. Usually replacing the file from a process is not a big problem as the whole file is loaded into memory before execution. Java is a little bit different, because the actual process that is running is the JVM and it only loads the jar file from disk. The JVM loads classes only on demand, this means if there was any class that was not loaded before it will try to load it and most likely fail, if the jar file is different. In the case of spring boot there are also other resources (such as HTML files) inside the jar file that are dynamically loaded.
You mentioned you are using a linux environment. If you can just replace your startup with a script you can just copy the jar and start it from the copied location:
#!/bin/bash
JAR_NAME="spring-boot.jar"
NEW_JAR_NAME=".$JAR_NAME" # Use an appropriate name here
cp $JAR_NAME $NEW_JAR_NAME
java -jar $NEW_JAR_NAME
rm $NEW_JAR_NAME
Now every time you start the application a copy is being made and started from there. You can replace the original jar and on the next restart the new application will load.
You coud also use rsync instead of cp to avoid copying the same jar twice, if the application is restarted multiple times without changing the jar.
It would be convenient for us to deploy new versions of an application
by copying the Spring Boot jar on top of the existing (old) jar and
then simply wait for the application to restart
Why would you do such a thing to yourself? You are trying solve a usecase that's against best practices, sound like asking for trouble just to avoid an app restart. When you are doing a deployment, you need to make sure the deployment went through, otherwise how will you troubleshoot if something goes wrong in your application, you will have one more variable in hand when you troubleshoot, i,e the uncertainty of current version of the code.
If you are having downtime while deploying (I am assuming thats why you want to limit the restarts), why don't you bring up another instance with the newer version of code and once its healthy shutdown the old one

Using Spring Boot profiles on external tomcat

I am looking for a solution to the problem, which is that having an external Tomcat server with several different applications (war),
I would like to use application Spring Profile (dev, prod) to choose application.properties for a given profile.
To avoid keeping the database configuration in the git repository, I didn't store in the application
application.properties, but I kept them in the $catalina.base directory, where in common.loader
I indicated the path to this directory. This worked until I started deploying several different applications. Then each of them began to use
from the same datasource. One solution is to keep the application.properties in Jenkins and directly in Jobie indicating which one to use,
but I am not sure if this is a good solution.
Option 1: Create a separate instance of tomcat (using same tomcat binary) and place application.properties in instance's classpath. As classpath is separate for every instance, applications don't refer to same application.properties file. Refer to this article to see how to create multiple instances on same tomcat server.
Option 2: Create JNDI datasource on tomcat server and use it in your application to access database. This way, should you choose to, same datasource can be shared across different related applications and/or modules. For more information on how to create JNDI datasource in Tomcat, refer to this link

Unable to link Spring boot application with Azure Application insight using application.properties, when logback.xml is used

I have created a spring-boot starter project and linked Azure Application insight to it. The properties like instrumentation- key is defined in "application.properties". On launching the application it is correctly linked to App Insight as can be verified by Live Metrics Stream.
However same application fails to connect to Azure App Insight if logback.xml is included in project (in resources), in this case to connect to App insight I have to include ApplicationInsights.xml as well.
But I do not want to use "ApplicationInsights.xml" in my application for 2 reasons. 1. I do not want multiple configuration files. 2. I am not able to inject key , i.e. not able to externalize key which might come as vm arguments or environment variable.
Defining InstrumentationKey and other configuration in application.properties works only when logback.xml is not present.
sample project (asset-register.zip) can be found at https://github.com/Microsoft/ApplicationInsights-Java/issues/710

spring boot application properties based on spring profiles

Hi I want my spring boot web project to be deployed both on development and production environment and it should be run on specific profile based setting.
I googled on how to do that, and first of all that I have searched is defining application-{profile name}.properties properly in the src/main/resources classpath.
Now the problem is how to set profiles.
Since I am working on tomcat 8 in linux, there should be some configuration but I don't know how to do that.
and I am also curious that when my project is packaged as war file, java -jar {filename} -Dspring.active.profile=blahblah will not be work, but I think there is an alternative way.
plus, is there an way to set profile on tomcat 8 in Windows 10 ?
Thanks you
First:
I will recommend get rid of dedicated tomcat server and use embedded tomcat, jetty etc. Build your web apps as jar files and just run them. (of course if you don't have any limitations)
Second: You can do this either system property or env variable.
If you go with system property (order is important)
java -Dspring.profiles.active=blahblah -jar {filename}
If you go with env variable you need specify
SPRING_PROFILES_ACTIVE=blahblah

How to load Spring boot application static contain automatically while server is running?

I have created a spring boot application in which at location src/resource/static I have kept my all html, js and css files, Whenever I do any changes in these files I need to restart the spring boot application. Is there any easy way so that I will not require to restart my application.
As per the spring boot documentation, you need to move the static contents under web apps folder. Also make following settings
Projects->Build automatically
if you using eclipse
1) If you are using thyme leaf it would be very easy just add
spring.resources.static-locations
in application properties.
2) If you want auto restart try adding
spring.devtools.restart.additional-paths
to your
application.properties
References :
http://www.logicbig.com/tutorials/spring-framework/spring-boot/boot-live-reload/
http://www.concretepage.com/spring-boot/spring-boot-automatic-restart-using-developer-tools-with-maven
Using Thymeleaf:
http://blog.codeleak.pl/2016/12/thymeleaf-reload-templates-and-static-resources.html

Resources