Getting Started with Embedded Tomcat

The purpose of this post is to help you get started with embedded Tomcat, and will cover the following:

  • Starting a new Mavenized Tomcat project
  • Deploy a simple servlet to the embedded Tomcat process
  • Create a Tomcat Maven Project

TL;DR All of the sources for this example project are available on GitHub here.

The first step to getting started is to create a new project. You can do this by using a maven archetype, or by creating the directory structure that you need. If you want to use an archetype to generate the structure for you, execute the following:

mvn archetype:generate -DgroupId=io.github.csutherl.tomcat \
    -DartifactId=HelloApplication \
    -DarchetypeArtifactId=maven-archetype-webapp \
    -DinteractiveMode=false

The maven-archetype-webapp archetype creates a directory structure that looks like this:

|----HelloApplication
| |----pom.xml
| |----src
| | |----main
| | | |----resources
| | | |----webapp
| | | | |----index.jsp
| | | | |----WEB-INF
| | | | | |----web.xml

I’m all for using tools to automatically do things for me, but in reality we just want to create a simple servlet and start it up with maven so we don’t really need all of that fluff. We can manually create the directory structure necessary which will mirror the one generated by Maven by using the following command. This will build the structure we need while leaving out the web.xml and JSP stuff that’s generated by the archetype.

mkdir -p HelloApplication/src/main/java/io/github/csutherl/tomcat/servlets/
cd HelloApplication

After we have a working directory for the application we can create the application and servlet code along with the maven pom.

Create and Deploy the Servlet

To create the application code which uses embedded tomcat we place this java class in a file (named HelloApplication.java) within the tomcat package directory:

package io.github.csutherl.tomcat;
 
import io.github.csutherl.tomcat.servlets.HelloServlet;
 
import org.apache.catalina.Context;
import org.apache.catalina.startup.Tomcat;
 
public class HelloApplication {
    public static void main(String[] args) throws Exception {
        // Get an instance of Tomcat
        Tomcat tomcat = new Tomcat();
 
        // Add an empty context
        Context ctx = tomcat.addContext("", null);
 
        // Get an instance of the servlet and add a servlet mapping
        Tomcat.addServlet(ctx, "hello", new HelloServlet());
        ctx.addServletMapping("/hello", "hello");
 
        // Start the tomcat instance
        tomcat.start();
 
        // Wait for a control-C to stop the process to allow for testing
        tomcat.getServer().await();
    }
}

The code above uses a servlet, HelloServlet, defined by the java code below. This code should be placed in a file named HelloServlet.java which should be located within the servlets package directory.

package io.github.csutherl.tomcat.servlets;
 
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
 
import java.io.IOException;
import java.io.PrintWriter;
 
public class HelloServlet extends HttpServlet {
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException {
 
        response.setContentType("text/html");
 
        PrintWriter out = response.getWriter();
        out.println("<h3>Hello!!</h3>");
    }
}

Now that we have application code and a servlet to deploy, we need to setup the pom so that we can compile and run this application. My pom.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>io.github.csutherl.tomcat</groupId>
    <artifactId>hello</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <name>hello</name>
    <description>Hello World for Embedded Tomcat</description>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <tomcat-version>8.0.36</tomcat-version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>${tomcat-version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-logging-juli</artifactId>
            <version>${tomcat-version}</version>
        </dependency>
    </dependencies>
 
    <!-- The build portion is not necessary, but it saves you from using The
      exec.MainClass system property, such as:
      mvn exec:java -Dexec.mainClass=io.github.csutherl.tomcat.HelloApplication -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
 
                <configuration>
                    <mainClass>io.github.csutherl.tomcat.HelloApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

OK! Now we can compile and run the application. To do so, execute the following:

mvn clean install exec:java

After running the above commands you will see the code being compiled and executed, which looks something like the following for a successful build:

[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building hello 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> exec-maven-plugin:1.2.1.jbossorg-3:java (default-cli) > validate @ hello >>>
[INFO]
[INFO] <<< exec-maven-plugin:1.2.1.jbossorg-3:java (default-cli) < validate @ hello <<<
[INFO]
[INFO] --- exec-maven-plugin:1.2.1.jbossorg-3:java (default-cli) @ hello ---
Feb 02, 2017 9:42:52 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-nio-8080"]
Feb 02, 2017 9:42:52 PM org.apache.tomcat.util.net.NioSelectorPool getSharedSelector
INFO: Using a shared selector for servlet write/read
Feb 02, 2017 9:42:52 PM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Tomcat
Feb 02, 2017 9:42:52 PM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/8.0.36
Feb 02, 2017 9:42:52 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-nio-8080"]
  • Note: I used the call to tomcat.getServer().await() so that the container process continues running until you stop it.

You can test the servlet in a separate terminal with curl (or your browser) like this:

curl http://localhost:8080/hello

And that’s it! You have created an embedded tomcat application that is serving a simple servlet.

Be the first to read my posts!

* indicates required