Embed Tomcat with App in One Fat Jar
Asked Answered
G

2

8

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)

Gelhar answered 11/11, 2012 at 18:3 Comment(5)
embed tomcat in webapp... what for?Menashem
Sorry I miss worded the question. I meant combine and not embed in the webapp itself. The idea of a fat jar is to simplify DevOps. All you need to run the app is java -jar my-webapp.jar.Gelhar
Here is another example of Fat Jar creation: one-jar.sourceforge.netGelhar
possible duplicate of Self-contained war file with Tomcat embedded?Gelhar
Duplicate of question here: #7904063 . Please vote to close thanks.Gelhar
G
5

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>
Gelhar answered 19/12, 2012 at 22:49 Comment(0)
E
0

I did a tutorial on embedded Tomcat JARs and wanted to create as small of a POM file as possible that would create an executable JAR. I didn't want any environment variables or superfluous dependencies - just the bare bones. Here's what I came up with:

POM configuation for Tomcat plugin

<?xml version="1.0" encoding="UTF-8"?>
<project>


  <!-- create an executable jar file example -->
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mcnz.maven</groupId>
  <artifactId>javawebapp</artifactId>
  <version>1.0-embedded</version>
  <packaging>war</packaging>


  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>



   <!-- Maven embedded Tomcat server example -->
   <build>
      <finalName>javawebapp</finalName>
      <pluginManagement>
           <plugins>
            <plugin>
               <groupId>org.apache.tomcat.maven</groupId>
               <artifactId>tomcat7-maven-plugin</artifactId>
               <version>2.1</version>
               <configuration>
                 <!-- context root for Java web apps -->
                 <path>/tutorial</path>
                 <!-- name of executable jar file -->
                 <finalName>executable.jar</finalName>
               </configuration>
            </plugin>
         </plugins>
      </pluginManagement>
   </build>
   <!-- end of embedded Tomcat server tutorial -->

</project>

Running the tomcat7 plugin with Maven

The maven command co create the embedded jar is as follows:

$ mvn clean install tomcat7:exec-war-only

Here is the project structure that maven creates when the command is run:

Maven Project Structure

Running the JAR

And then I use the following command to run the JAR:

$ java -jar executable.jar

More information

Those are the basics. I posted a video on how to create an embedded Tomcat JAR as well for anyone interested in seeing all of the steps from start to finish.

Exteroceptor answered 10/7, 2019 at 14:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.