What do you think? Discuss, post comments, or ask questions at the end of this article [More about me]

Apache Tomcat is an open source Java servlet container that's used to run Java webapps.  It's simple, easy to deploy, and a downright wonderful implementation of Java servlet tech that I've used (especially recently) in software projects.  It's also used extensively in other systems that I use and maintain, particularly Atlassian's stack (JIRA, confluence, crowd, etc.).

Below is a guide to deploying a Java webapp with Tomcat in a simple (the simplest?) way on a Linux server (in this example I'll be using Ubuntu Server 16.04).

Guide

I prefer just running Tomcat without any bells and whistles (like the included manager app) - hence I'll cover setting up Tomcat and deploying a .war file.

Installing

Tomcat will need JDK (Java Development Kit).  See my Install JDK 8 article for how to do this.

Next, let's download Tomcat.  We'll be downloading from https://tomcat.apache.org/download-90.cgi and we want the tar.gz binary distribution:

An easy way to download this directly to your server is to right-click on the tar.gz link and copy the link address.  Then use wget to download (you can also use curl if that is what you have on your Linux distro).  For example:

wget http://apache.mirror.digitalpacific.com.au/tomcat/tomcat-9/v9.0.4/bin/apache-tomcat-9.0.4.tar.gz

We can run Tomcat from any location on our server.  We'll simply extract it to wherever and run it from there.  You can follow this guide here.  We'll do likewise and extract to /opt/tomcat/.

sudo mkdir /opt/tomcat
sudo tar xzvf apache-tomcat-9.0.4.tar.gz -C /opt/tomcat --strip-components=1

Note that if you any specific jar, like the JDBC connector for MySQL, you should copy those required jars to /opt/tomcat/lib.

Simplifying

I prefer to keep things simple and strip Tomcat down to only run the web application that I want to deploy.  So, I'm going to delete everything in the webapps folder on the default tomcat install.  This folder (by default) contains applications like the manager app that can be used to upload and deploy webapps.  I find Tomcat dead simple enough that I don't need any including management gui and would prefer to start clean:

sudo su
cd /opt/tomcat/webapps
rm -rf *
exit

That's pretty much the setup that I'm going to use.

Installing the .war file to run

Tomcat runs .war files - self-contained web archive files that contain your web application.  You don't really install these, just simply copy it to /opt/tomcat/webapps/ROOT.war 

For example (if I had a .war file in my home folder):

sudo cp ~/my.war /opt/tomcat9/webapps/ROOT.war

Running Tomcat

We can now start Tomcat.  You can do this by runing the startup.sh script in /opt/tomcat/bin, or use catalina.sh run:

sudo /opt/tomcat/bin/startup.sh

Or

sudo /opt/tomcat/bin/catalina.sh run

Passing variables to Tomcat

You can define and pass variables to Tomcat in order to change how your application runs.  For example, in a Spring Boot app you might defined different .properties files to define running the application in a development/test mode, where you might use an in-memory database for persistency (h2 is great for this!), and another .properties file for production (which could connect to a production MySql database for example).

You then can pass variables to Tomcat to deploy according to the variables you pass it.

For example, in one of my vaadin applications, I have application.properties and aplication.production.properties files which define development and production modes respectively.  By default my spring boot app runs the application.properties configuration.

application.production.properties
# set application profile
spring.profiles.active=PROD

# Logging level of SQL run. Change to DEBUG to print out SQL statements into logs
logging.level.org.hibernate.SQL=INFO
# Logging level of values passed to SQL statements. Change to TRACE to print out values in logs
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=INFO
# use component ids for client-server communication (for load testing, false by default)
loadtestmode.enabled=false
#
logging.level.com.vaadin.spring.navigator.SpringViewProvider=WARN
logging.level.com.vaadin.spring.server.SpringUIProvider=WARN
# No need to presist sessions
server.session.persistent=false
# Put Vaadin into production mode
vaadin.servlet.productionMode=true
# Use MySQL production db
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://${MYSQL_HOSTNAME}:${MYSQL_PORT}/${DB_NAME}
spring.datasource.username=${USERNAME}
spring.datasource.password=${PASSWORD}
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

You'll note that in the above production properties file we define certain variables like MYSQL_HOSTNAMEMYSQL_PORTUSERNAME, PASSWORD etc.

To get Tomcat to use not only the above application.production.properties file, but also know variables values for the above variables, we need to pass these variables to Tomcat.  We do this by defining a setenv.sh file /opt/tomcat/bin.

Let's do this for the above example, first fire up a text editor (I like nano) and create the setenv.sh file.

sudo nano /opt/tomcat/bin/setenv.sh

Now add the following context (modified to your needs):

/opt/tomcat/bin/setenv.sh
export MYSQL_HOSTNAME="127.0.0.1"
export MYSQL_PORT="3306"
export DB_NAME="<db_name>"
export USERNAME="<username>"
export PASSWORD="<PASSWORD>"
export JAVA_OPTS="-Dspring.config.name=application.production"

These variables will be passed to Tomcat on startup which should startup your application according to the variables and .properties files passed.

References

  1. https://tomcat.apache.org/whichversion.html
  2. https://tomcat.apache.org/tomcat-9.0-doc/RUNNING.txt
  3. https://www.digitalocean.com/community/tutorials/how-to-install-apache-tomcat-8-on-ubuntu-16-04

Related articles