Spring Boot with Embedded Tomcat Pros and Cons
By: Vinicius Monteiro
Tags: Spring Boot, Microservices, Java, Tomcat

Cons

1. Multiple Tomcats to manage and monitor

, This one can be addressed with utility scripts to start/stop/restart each service or all at once, and spring-boot-admin [3] to monitor the health and resources such as memory, threads and JVM in general. All visualized through a nice UI.

2. It’s not possible to change properties files only, without rebuilding.

It’s not ideal for changing properties files only and reload the application. But it’s a reality.

More often than not, I worked with applications where a (bad) common practice was to change a configuration/properties file and redeploy on Tomcat without rebuilding the entire application again. With a .war file, it’s easy — when the .war is deployed on Tomcat, the contents are extracted into a folder in web apps. Then you just need to open the folder, change the properties file, and reload the application in Tomcat manager.

Working with a .jar, force us always to rebuild the entire application— which it’s good. I see this con as a pro in disguise.

*Update: It was mentioned in the comments section that the property file could be external. Hence there would be no need to rebuild the .jar —That’s correct.

3. It breaks load balancer health check

As there are multiple Tomcats and port numbers, which service would be used for load balancer health check?

It’s common to configure the load balancer (LB) with the port being dynamic, appended to the end of the hostname — BUT load balancers also require at least one port to be fixed, to serve as a health check.

Example: A LB is configured as https://loadbalance:<port number>/. Thus it means that https://loadbalance:8083/serviceA/ and https://loadbalance:8084/serviceB/ are accessible.

The LB also needs a fixed port number for the health check. It could be 8083 or 8084, or perhaps a third one: 8080, that only serves as a health check. To use the latter could work — however, it’s not the best solution.

The ideal solution is to use a Gateway. It not only provides a common port to serve as a health check, but it also resolves the issue of having to remember multiple port numbers and URLs.

The Gateway stays in front of all services having its own unique port. It becomes a single point of failure — that’s true! But it’s a simple application that only does redirection. There is no business logic; hence it should rarely have issues.

Netflix Zuul [4] is commonly used for the Gateway. Figure 1 demonstrates such architecture.

Figure 1: Netflix Zuul Gateway. Created by author

4. Multiple port numbers / URLs to manage and monitor

As each service has its own port number, it can become a hassle to manage and monitor all the different URLs. Imagine telling for each client: client A, use service B on port 8083; client B, use service D on port 8084, and so on. It also impacts load balancer configuration as already explained.

The solution is also to have a Gateway, as described in the previous section — con number 3.

5. No hot deployment out of the box

Hot deployment means having the application deployed without having to restart the server or reload the application manually.

When I use one Tomcat installation and .war file, I usually do hot deployment for any change. All I need to do is to copy the modified .war file to Tomcat webapps folder, and that’s it, the application is updated. This process can be automated by configuring Jenkins. It can check changes in Git and move the .war.

In the case of a .jar with embedded Tomcat, Jenkins job can be used. The job can check for changes in the repository, generate the .jar, transfer it to the right location in the server and execute it.

There is also a module called spring-boot-devtools that can do reloading from the local IDE to a remote server. It doesn’t work exactly how I want, but it may be enough, at least for the TEST environment. Enabling this for production is a security risk [5]