Embedding Jetty or Tomcat in your Java Application

July 9th, 2013 by

Recently I needed to control an embedded web container from a Java application and I wanted to see how this could be achieved using an embedded instance of either Tomcat or Jetty here.

In the following short examples I would like to show how to embed both servers in an application in no  time using Gradle or Maven as build tool.


 

Dependencies

We just need to add the web container libraries to our project here .. I’ve added the build config for Gradle and Maven here…

Gradle

Adding the following instructions to our build.gradle adds everything needed here .. the dependencies for tomcat and jetty and a gradle task to run the  application and read user input from STDIN (and other stuff to create project files for Eclipse IDE..)..

apply plugin: 'java'
apply plugin: 'eclipse'
 
repositories {
    mavenCentral()
}
 
dependencies {
    compile 'org.eclipse.jetty:jetty-server:9.0.0.RC2'
    compile 'org.eclipse.jetty:jetty-servlet:9.0.0.RC2'
    compile 'org.apache.tomcat:tomcat-catalina:7.0.41'
    compile 'org.apache.tomcat:tomcat-util:7.0.41'
    compile 'org.apache.tomcat.embed:tomcat-embed-core:7.0.41'
}
 
sourceCompatibility = 1.7
targetCompatibility = 1.7
 
task(selectServer, dependsOn: 'classes', type: JavaExec) {
    main = 'com.hascode.tutorial.app.Main'
    classpath = sourceSets.main.runtimeClasspath
    standardInput= System.in
}
 
defaultTasks 'selectServer'

Maven

If you prefer Maven, please add the following dependencies to your pom.xml:

<dependencies>
	<dependency>
		<groupId>org.eclipse.jetty</groupId>
		<artifactId>jetty-server</artifactId>
		<version>9.0.0.RC2</version>
	</dependency>
	<dependency>
		<groupId>org.eclipse.jetty</groupId>
		<artifactId>jetty-servlet</artifactId>
		<version>9.0.0.RC2</version>
	</dependency>
	<dependency>
		<groupId>org.apache.tomcat</groupId>
		<artifactId>tomcat-catalina</artifactId>
		<version>7.0.41</version>
	</dependency>
	<dependency>
		<groupId>org.apache.tomcat</groupId>
		<artifactId>tomcat-util</artifactId>
		<version>7.0.41</version>
	</dependency>
	<dependency>
		<groupId>org.apache.tomcat.embed</groupId>
		<artifactId>tomcat-embed-core</artifactId>
		<version>7.0.41</version>
	</dependency>
</dependencies>

Now we’re ready to create a simple web application …

The Application

The main application here allows us to choose the server we want to start by reading our choice from the command line.

Pressing “1″ starts our embedded Jetty server, pressing “2″ starts a Tomcat server….

package com.hascode.tutorial.app;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
 
import org.apache.catalina.LifecycleException;
 
import com.hascode.tutorial.container.JettyEmbeddedRunner;
import com.hascode.tutorial.container.TomcatEmbeddedRunner;
 
public class Main {
	public static void main(final String[] args) throws IOException,
			LifecycleException {
		System.out
				.println("### STARTING EMBEDDED WEB CONTAINER\nPlease select your container...\n1) Jetty\n2) Tomcat\n");
		BufferedReader bufferRead = new BufferedReader(new InputStreamReader(
				System.in));
		String input = bufferRead.readLine();
		if ("1".equals(input)) {
			System.out.println("Starting Jetty ..");
			new JettyEmbeddedRunner().startServer();
		} else if ("2".equals(input)) {
			System.out.println("Starting Tomcat ..");
			new TomcatEmbeddedRunner().startServer();
		} else {
			System.out.println("Nothing selected .. quitting application...");
		}
 
	}
}

The HTTP Servlet

We’re creating a simple servlet here by extending javax.servlet.http.HttpServlet.

Our servlet simply prints a timestamp to the output stream … that’s all …

package com.hascode.tutorial.servlet;
 
import java.io.IOException;
import java.util.Date;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public class DatePrintServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
 
	@Override
	protected void doGet(final HttpServletRequest req,
			final HttpServletResponse res) throws ServletException, IOException {
		res.getWriter()
				.append(String.format("It's %s now\n\n\n\nwww.hascode.com",
						new Date()));
	}
}

Jetty embedded

This is our code to startup an embedded Jetty server instance, running on port 8080 with context-path “app” and our DatePrintServlet registered:

package com.hascode.tutorial.container;
 
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
 
import com.hascode.tutorial.servlet.DatePrintServlet;
 
public class JettyEmbeddedRunner {
	public void startServer() {
		try {
			Server server = new Server();
			ServerConnector c = new ServerConnector(server);
			c.setIdleTimeout(1000);
			c.setAcceptQueueSize(10);
			c.setPort(8080);
			c.setHost("localhost");
			ServletContextHandler handler = new ServletContextHandler(server,
					"/app", true, false);
			ServletHolder servletHolder = new ServletHolder(
					DatePrintServlet.class);
			handler.addServlet(servletHolder, "/date");
			server.addConnector(c);
			server.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Tomcat embedded

The following lines start a new Tomcat instance, running on port 8080 with context-path “app” and our DatePrintServlet registered, corresponding to the Jetty configuration above.

package com.hascode.tutorial.container;
 
import java.io.File;
 
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;
 
import com.hascode.tutorial.servlet.DatePrintServlet;
 
public class TomcatEmbeddedRunner {
	public void startServer() throws LifecycleException {
		Tomcat tomcat = new Tomcat();
		tomcat.setPort(8080);
		File base = new File(System.getProperty("java.io.tmpdir"));
		Context rootCtx = tomcat.addContext("/app", base.getAbsolutePath());
		Tomcat.addServlet(rootCtx, "dateServlet", new DatePrintServlet());
		rootCtx.addServletMapping("/date", "dateServlet");
		tomcat.start();
		tomcat.getServer().await();
	}
}

Directory Structure

This is what my directory structure looks like:

$ tree
.
├── build.gradle
├── README.md
└── src
 └── main
 ├── java
 │   └── com
 │       └── hascode
 │           └── tutorial
 │               ├── app
 │               │   └── Main.java
 │               ├── container
 │               │   ├── JettyEmbeddedRunner.java
 │               │   └── TomcatEmbeddedRunner.java
 │               └── servlet
 │                   └── DatePrintServlet.java
 └── resources

Running the Application

We’re now ready to run our application using the gradle task we’ve defined in the build.gradle.

When typing “1″ or “2″ the application should start either an embedded Jetty or an embedded Tomcat.

Afterwards the web application is accessible by opening the following address in your browser: http://localhost:8080/app/date

$ gradle selectServer
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:selectServer
### STARTING EMBEDDED WEB CONTAINER
Please select your container...
1) Jetty
2) Tomcat

Screenshot

This is what our application looks like in the browser.

The Date Servlet in the Browser

The Date Servlet in the Browser

Tutorial Sources

Please feel free to download the tutorial sources from my Bitbucket repository, fork it there or clone it using Git:

git clone https://bitbucket.org/hascode/webapp-embedded-tutorial.git

Resources

Updates

  • 2014-05-24: Maven dependency coordinates fixed, clean shutdown control for Tomcat added (thx @Claude Quézel)
  • 2014-10-12: Typo in build.gradle fixed (thx @Sascha Kratky)

Tags: , , , , , ,

11 Responses to “Embedding Jetty or Tomcat in your Java Application”

  1. Thai Says:

    I saw a lot of posts about embedding Jetty/Tomcat in our own applications. Your post is a little bit better/worse than others in the following items:
    - you have a Gradle build.
    - you didn’t show how to register the Spring MVC DispatcherServlet (spring mvc is quite popular, so it’ll be nice to talk about it).
    - you didn’t show how to host static files (.html, .css, .js) in your application.

  2. itoctopus Says:

    Hi Micha,

    Is the point of this branding the web server? Can you please state an example where such an action is used in the real world (other than branding the web server)?

  3. micha kops Says:

    Thanks for your feedback and I can understand your point here.

  4. Jan Bartel Says:

    Hi Micha,

    Thanks for showing one way to use Jetty in embedded mode. I just wanted to let you know that Jetty 9 is now at release level 9.0.4, with a first milestone release of 9.1 (to support the Servlet 3.1 api) coming up next month.

    cheers
    Jan

  5. Eric Martin Says:

    I entered every thing you had listed but I am getting a ton of errors, perhaps because I do not have the complete pom.xml file. Here are my errors:

    [INFO] ————————————————————————
    [INFO] Building ericMartin-app 1.0-SNAPSHOT
    [INFO] ————————————————————-
    [ERROR] COMPILATION ERROR :
    [INFO] ————————————————————-
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\DataPrintServlet.java
    :[11,7] class DatePrintServlet is public, should be declared in a file named Dat
    ePrintServlet.java
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[8,3] cannot find symbol
    symbol : class Server
    location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[8,23] cannot find symbol
    symbol : class Server
    location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[9,3] cannot find symbol
    symbol : class ServerConnector
    location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[9,27] cannot find symbol
    symbol : class ServerConnector
    location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[14,3] cannot find symbol
    symbol : class ServletContextHandler
    location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[14,39] cannot find symbol
    symbol : class ServletContextHandler
    location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[16,3] cannot find symbol
    symbol : class ServletHolder
    location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[16,37] cannot find symbol
    symbol : class ServletHolder
    location: class com.ericMartin.app.JettyEmbeddedRunner
    [INFO] 10 errors
    [INFO] ————————————————————-
    [INFO] ————————————————————————
    [INFO] BUILD FAILURE
    [INFO] ————————————————————————
    [INFO] Total time: 3.746s
    [INFO] Finished at: Wed Sep 04 16:56:02 EDT 2013
    [INFO] Final Memory: 6M/16M
    [INFO] ————————————————————————
    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.
    5.1:compile (default-compile) on project ericMartin-app: Compilation failure: Co
    mpilation failure:
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\Main.java:[9,7] class
    HelloServlet is public, should be declared in a file named HelloServlet.java
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\DataPrintServlet.java
    :[11,7] class DatePrintServlet is public, should be declared in a file named Dat
    ePrintServlet.java
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[8,3] cannot find symbol
    [ERROR] symbol : class Server
    [ERROR] location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[8,23] cannot find symbol
    [ERROR] symbol : class Server
    [ERROR] location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[9,3] cannot find symbol
    [ERROR] symbol : class ServerConnector
    [ERROR] location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[9,27] cannot find symbol
    [ERROR] symbol : class ServerConnector
    [ERROR] location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[14,3] cannot find symbol
    [ERROR] symbol : class ServletContextHandler
    [ERROR] location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[14,39] cannot find symbol
    [ERROR] symbol : class ServletContextHandler
    [ERROR] location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[16,3] cannot find symbol
    [ERROR] symbol : class ServletHolder
    [ERROR] location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[16,37] cannot find symbol
    [ERROR] symbol : class ServletHolder
    [ERROR] location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] -> [Help 1]
    [ERROR]
    [ERROR] To see the full stack trace of the errors, re-run Maven with the -e swit
    ch.
    [ERROR] Re-run Maven using the -X switch to enable full debug logging.
    [ERROR]
    [ERROR] For more information about the errors and possible solutions, please rea
    d the following articles:
    [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureExc
    eption
    C:\ericMartin-app>mvn clean
    [INFO] Scanning for projects…
    [INFO]
    [INFO] ————————————————————————
    [INFO] Building ericMartin-app 1.0-SNAPSHOT
    [INFO] ————————————————————————
    [INFO]
    [INFO] — maven-clean-plugin:2.5:clean (default-clean) @ ericMartin-app —
    [INFO] Deleting C:\ericMartin-app\target
    [INFO] ————————————————————————
    [INFO] BUILD SUCCESS
    [INFO] ————————————————————————
    [INFO] Total time: 0.997s
    [INFO] Finished at: Wed Sep 04 16:57:56 EDT 2013
    [INFO] Final Memory: 2M/15M
    [INFO] ————————————————————————
    C:\ericMartin-app>mvn clean compile exec:java
    [INFO] Scanning for projects…
    [INFO]
    [INFO] ————————————————————————
    [INFO] Building ericMartin-app 1.0-SNAPSHOT
    [INFO] ————————————————————————
    [INFO]
    [INFO] — maven-clean-plugin:2.5:clean (default-clean) @ ericMartin-app —
    [INFO]
    [INFO] — maven-resources-plugin:2.6:resources (default-resources) @ ericMartin
    -app —
    [INFO] Using ‘UTF-8′ encoding to copy filtered resources.
    [INFO] skip non existing resourceDirectory C:\ericMartin-app\src\main\resources
    [INFO]
    [INFO] — maven-compiler-plugin:2.5.1:compile (default-compile) @ ericMartin-ap
    p —
    [INFO] Compiling 3 source files to C:\ericMartin-app\target\classes
    [INFO] ————————————————————-
    [ERROR] COMPILATION ERROR :
    [INFO] ————————————————————-
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\Main.java:[9,7] class
    HelloServlet is public, should be declared in a file named HelloServlet.java
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\DataPrintServlet.java
    :[11,7] class DatePrintServlet is public, should be declared in a file named Dat
    ePrintServlet.java
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[8,3] cannot find symbol
    symbol : class Server
    location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[8,23] cannot find symbol
    symbol : class Server
    location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[9,3] cannot find symbol
    symbol : class ServerConnector
    location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[9,27] cannot find symbol
    symbol : class ServerConnector
    location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[14,3] cannot find symbol
    symbol : class ServletContextHandler
    location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[14,39] cannot find symbol
    symbol : class ServletContextHandler
    location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[16,3] cannot find symbol
    symbol : class ServletHolder
    location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[16,37] cannot find symbol
    symbol : class ServletHolder
    location: class com.ericMartin.app.JettyEmbeddedRunner
    [INFO] 10 errors
    [INFO] ————————————————————-
    [INFO] ————————————————————————
    [INFO] BUILD FAILURE
    [INFO] ————————————————————————
    [INFO] Total time: 5.054s
    [INFO] Finished at: Wed Sep 04 17:01:39 EDT 2013
    [INFO] Final Memory: 8M/23M
    [INFO] ————————————————————————
    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.
    5.1:compile (default-compile) on project ericMartin-app: Compilation failure: Co
    mpilation failure:
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\Main.java:[9,7] class
    HelloServlet is public, should be declared in a file named HelloServlet.java
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\DataPrintServlet.java
    :[11,7] class DatePrintServlet is public, should be declared in a file named Dat
    ePrintServlet.java
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[8,3] cannot find symbol
    [ERROR] symbol : class Server
    [ERROR] location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[8,23] cannot find symbol
    [ERROR] symbol : class Server
    [ERROR] location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[9,3] cannot find symbol
    [ERROR] symbol : class ServerConnector
    [ERROR] location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[9,27] cannot find symbol
    [ERROR] symbol : class ServerConnector
    [ERROR] location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[14,3] cannot find symbol
    [ERROR] symbol : class ServletContextHandler
    [ERROR] location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[14,39] cannot find symbol
    [ERROR] symbol : class ServletContextHandler
    [ERROR] location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[16,3] cannot find symbol
    [ERROR] symbol : class ServletHolder
    [ERROR] location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] C:\ericMartin-app\src\main\java\com\ericMartin\app\JettyEmbeddedRunner.j
    ava:[16,37] cannot find symbol
    [ERROR] symbol : class ServletHolder
    [ERROR] location: class com.ericMartin.app.JettyEmbeddedRunner
    [ERROR] -> [Help 1]
    [ERROR]
    [ERROR] To see the full stack trace of the errors, re-run Maven with the -e swit
    ch.
    [ERROR] Re-run Maven using the -X switch to enable full debug logging.
    [ERROR]
    [ERROR] For more information about the errors and possible solutions, please rea
    d the following articles:
    [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureExc
    eption
    C:\ericMartin-app>

    Thank you for your help,
    Eric

  6. Claude Quézel Says:

    The correct maven dependency is:

    org.apache.tomcat.embed
    tomcat-embed-core
    7.0.41

  7. Claude Quézel Says:

    while (true) {
    }

    should probably be

    tomcat.getServer().await();

  8. micha kops Says:

    Hi Claude,

    thanks for your remarks! I’ve updated the article .

    Cheers,

    Micha

  9. Alex Says:

    Thank you.
    Very nice tutorial. It is work for me.

  10. Smiles Says:

    Hi Micha,

    Great article. Helped a lot.
    Did you come across classpath issues with embedded Tomcat? In my app I start a lot of stuff besides the embedded tomcat and after that I want to access this stuff from my servlet. It seems that this stuff is not accessible due to the way the embedded tomcat loads subsequent classes. I just wanted to create a tiny web frontend to my app and hoped the servlet could communicate directly to my apps other classes in the same JVM. It does not seem to work that way.

    Cheers, Milé

  11. Jatin Says:

    Nice Article, thanks for posting it.

Search
Categories