Embedding Jetty or Tomcat in your Java Application
July 9th, 2013 by Micha KopsRecently 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.
Contents
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.
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: catalina, gradle, Java, jetty, server, servlet, tomcat
July 10th, 2013 at 1:46 pm
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.
July 10th, 2013 at 2:29 pm
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)?
July 10th, 2013 at 7:32 pm
Thanks for your feedback and I can understand your point here.
July 11th, 2013 at 9:27 am
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
September 4th, 2013 at 9:13 pm
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
May 23rd, 2014 at 4:03 pm
The correct maven dependency is:
org.apache.tomcat.embed
tomcat-embed-core
7.0.41
May 23rd, 2014 at 5:02 pm
while (true) {
}
should probably be
tomcat.getServer().await();
May 24th, 2014 at 3:09 pm
Hi Claude,
thanks for your remarks! I’ve updated the article .
Cheers,
Micha
June 11th, 2014 at 10:51 am
Thank you.
Very nice tutorial. It is work for me.
December 20th, 2014 at 5:32 pm
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é
March 22nd, 2016 at 9:09 am
Nice Article, thanks for posting it.