Embed Tomcat with App in One Fat Jar

Adam Gent picture Adam Gent · Nov 11, 2012 · Viewed 10.2k times · Source

I was hoping to combine/embed Tomcat and my web app as aka fat jar but I'm not sure if its possible. Its possible with Jetty using the Maven Shade plugin and Winstone but I tried something similar with Tomcat 7 and could not get it to load properly. The goal is to be able to do something like: java -jar mywebapp.jar.

The problem is that Tomcat wants to load things from the file system and not from the classpath. That is you can embed Tomcat but it will expect your WAR files to be available as files.

I tried many of the techniques on previous SO Posts for embedding Tomcat 6 & 7. While I can get it embedded and started it can't access my app.

I guess one option is having the JAR on boot unzip itself so that AppBase and DocBase are files on the file system. I haven't tried that yet but will.

There is a duplicate of the question here that I finally found: Self-contained war file with Tomcat embedded? (please vote to close as duplicate)

Answer

Adam Gent picture Adam Gent · Dec 19, 2012

I have no idea how I kept missing this but the Tomcat Maven Plugin now supports make an executable WAR:

http://tomcat.apache.org/maven-plugin-2.0/executable-war-jar.html

UPDATE if you need Tomcat 8 you need a special configuration. You must use the 2.0 version of the plugin as the 2.2 Tomcat 7 plugin will not work and you will need the third party plugin tomcat8-war-runner. Below I have attached the maven configuration you will need which also allow you to select the correct version of Tomcat 8 you want (tomcat.version property).

The Tomcat8 maven plugin is in a messy state and still hasn't been released (please go vote on jira and complain to them to finish it).

Finally one major caveat with this maven plugin approach is that the plugin pseudo embeds. That is your app will not be running in the same classloader as Tomcat and is actually deployed during initialization. There are pros and cons to this approach.

Spring Boot and this example from Oracle on the other hand will run Tomcat in the same classloader as your app (that is it is truly embedded I think).

    <plugin>
      <groupId>org.apache.tomcat.maven</groupId>
      <artifactId>tomcat7-maven-plugin</artifactId>
      <version>2.0</version>
      <configuration>
        <port>${tomcat.port}</port>
        <path>/</path>
      </configuration>
      <executions>
        <execution>
          <id>tomcat-run</id>
          <goals>
            <goal>exec-war-only</goal>
          </goals>
          <phase>package</phase>
          <configuration>
            <path>/</path>
            <port>${tomcat.port}</port>
            <attachArtifactClassifierType>war</attachArtifactClassifierType>
            <mainClass>org.apache.tomcat.maven.runner.Tomcat8RunnerCli</mainClass>
            <extraDependencies>
              <extraDependency>
                <groupId>com.nitorcreations</groupId>
                <artifactId>tomcat8-war-runner</artifactId>
                <version>1.0</version>
              </extraDependency>
            </extraDependencies>
          </configuration>
        </execution>
      </executions>
      <dependencies>
        <dependency>
          <groupId>org.apache.tomcat.embed</groupId>
          <artifactId>tomcat-embed-core</artifactId>
          <version>${tomcat.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>tomcat-util</artifactId>
          <version>${tomcat.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>tomcat-coyote</artifactId>
          <version>${tomcat.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>tomcat-api</artifactId>
          <version>${tomcat.version}</version>
        </dependency>

        <dependency>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>tomcat-jdbc</artifactId>
          <version>${tomcat.version}</version>
        </dependency>

        <dependency>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>tomcat-dbcp</artifactId>
          <version>${tomcat.version}</version>
        </dependency>

        <dependency>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>tomcat-servlet-api</artifactId>
          <version>${tomcat.version}</version>
        </dependency>

        <dependency>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>tomcat-jsp-api</artifactId>
          <version>${tomcat.version}</version>
        </dependency>

        <dependency>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>tomcat-jasper</artifactId>
          <version>${tomcat.version}</version>
        </dependency>

        <dependency>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>tomcat-jasper-el</artifactId>
          <version>${tomcat.version}</version>
        </dependency>

        <dependency>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>tomcat-el-api</artifactId>
          <version>${tomcat.version}</version>
        </dependency>

        <dependency>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>tomcat-catalina</artifactId>
          <version>${tomcat.version}</version>
        </dependency>

        <dependency>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>tomcat-tribes</artifactId>
          <version>${tomcat.version}</version>
        </dependency>

        <dependency>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>tomcat-catalina-ha</artifactId>
          <version>${tomcat.version}</version>
        </dependency>

        <dependency>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>tomcat-annotations-api</artifactId>
          <version>${tomcat.version}</version>
        </dependency>

        <dependency>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>tomcat-juli</artifactId>
          <version>${tomcat.version}</version>
        </dependency>

        <dependency>
          <groupId>org.apache.tomcat.embed</groupId>
          <artifactId>tomcat-embed-logging-juli</artifactId>
          <version>${tomcat.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.tomcat.embed</groupId>
          <artifactId>tomcat-embed-logging-log4j</artifactId>
          <version>${tomcat.version}</version>
        </dependency>
      </dependencies>
    </plugin>