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
targetCompatability = 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)

    Tags: , , , , , ,

    9 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.

    Leave a Reply

    Please leave these two fields as-is:

    Protected by Invisible Defender. Showed 403 to 80,965 bad guys.

    Search
    Categories