1. Why Using Embedded Tomcat? Maven Dependencies for Embedded Tomcat
2. Maven Dependencies for Embedded Tomcat
4. Embedding Tomcat server for a Programmatic Java Web Application
5. Using Embedded Tomcat server for a WAR File
6. Embedding Tomcat server for an Existing Java Web Application
- Rapid unit testing for web components like Java servlets: instead of starting/stopping Tomcat server and opening a web browser for manual unit testing, it is possible to use embedded Tomcat to automate unit testing.
- Delivering a Java web application as a standalone Java application: the end users now can run a JAR file which starts the embedded server which hosts the web application. No need to download and install Tomcat and deploy the web application manually.
- Programmatic control of the server: integrating an embedded server allows you to have more control of the server in programmatic ways, and automate manual steps.
- Whatever you can imagine.
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>${tomcat.version}</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <version>${tomcat.version}</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-logging-juli</artifactId> <version>${tomcat.version}</version> </dependency>Where tomcat.version is a property that points to the actual version of Tomcat:
<properties> <tomcat.version>8.0.48</tomcat.version> </properties>In case you don’t use Maven, download and add the following JAR files to your project’s classpath:
Tomcat tomcat = new Tomcat(); tomcat.setPort(8080); // configure the server // configure web applications tomcat.start();You can use following methods to configure the server:
// add context initialization parameters context.addParameter("param1", "value1"); context.addParameter("param2", "value2"); context.addErrorPage(new ErrorPage()); context.setCookies(true); context.setSessionTimeout(30);To configure the server for an existing web application, use the following Tomcat’s method: addWebapp(String contextPath, String baseDir)Where contextPath is the web application name and baseDir is the base directory of the application. baseDir can refer to an external WAR file, or to a web application directory in the same project.To add an existing Java servlet to a web application, you can use the following method:
addServlet(String contextPath, String servletName, Servlet servlet)
Or use the following static method:Tomcat.addServlet(Context context, String servletName, Servlet servlet)
To configure URL mapping for a servlet, you can use the following method of the Context class:addServletMappingDecoded(String urlPattern, String servletName)
To start, stop and destroy the server: tomcat.start() tomcat.stop() tomcat.destroy()And to cause the current thread to wait until the server is shutdown, use the following statement:tomcat.getServer().await();For complete reference, read the Javadocs of Tomcat and Context classes.
package net.codejava; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.catalina.Context; import org.apache.catalina.LifecycleException; import org.apache.catalina.startup.Tomcat; public class SimpleWebApp { public static void main(String[] args) throws LifecycleException { Tomcat tomcat = new Tomcat(); tomcat.setBaseDir("temp"); tomcat.setPort(8080); String contextPath = "/"; String docBase = new File(".").getAbsolutePath(); Context context = tomcat.addContext(contextPath, docBase); HttpServlet servlet = new HttpServlet() { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter writer = resp.getWriter(); writer.println("<html><title>Welcome</title><body>"); writer.println("<h1>Have a Great Day!</h1>"); writer.println("</body></html>"); } }; String servletName = "Servlet1"; String urlPattern = "/go"; tomcat.addServlet(contextPath, servletName, servlet); context.addServletMappingDecoded(urlPattern, servletName); tomcat.start(); tomcat.getServer().await(); } }As you can see, a Java servlet is created “on the fly”, which overrides the doGet() method:
HttpServlet servlet = new HttpServlet() { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter writer = resp.getWriter(); writer.println("<html><title>Welcome</title><body>"); writer.println("<h1>Have a Great Day!</h1>"); writer.println("</body></html>"); } };This servlet sends a simple HTML page to the client, with a heading “Have a Great Day!”.Run this program in Eclipse and you can see the server’s log in the Console view:
http://localhost:8080/go
And you can see the result looks like this:package net.codejava; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class AddServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { int a = Integer.parseInt(req.getParameter("a")); int b = Integer.parseInt(req.getParameter("b")); int sum = a + b; String result = String.format("%d + %d = %d", a, b, sum); PrintWriter writer = resp.getWriter(); writer.println("<html><title>Addition</title><body>"); writer.println("<h1>" + result + "</h1"); writer.println("</body></html>"); } }This servlet returns sum of two numbers passed from query parameters. And add this servlet to the web application like this:
AddServlet addServlet = new AddServlet(); servletName = "AddServlet"; urlPattern = "/add"; tomcat.addServlet(contextPath, servletName, addServlet); context.addServletMappingDecoded(urlPattern, servletName);Call the servlet from the web browser:
http://localhost:8080/add?a=1234&b=5678
And result:java -jar SimpleWebApp2.jarThen you can see the server is started and ready to accept client’s requests.
package net.codejava; import javax.servlet.ServletException; import org.apache.catalina.LifecycleException; import org.apache.catalina.startup.Tomcat; public class RunWarExample { public static void main(String[] args) throws ServletException, LifecycleException { Tomcat tomcat = new Tomcat(); tomcat.setBaseDir("temp"); tomcat.setPort(8080); String contextPath = "/Bookstore"; String warFilePath = "D:\\Web\\Website\\Bookstore.war"; tomcat.getHost().setAppBase("."); tomcat.addWebapp(contextPath, warFilePath); tomcat.start(); tomcat.getServer().await(); } }Run this program and you can see the content of the WAR file is extracted to the base directory, and you can access the web application using the specified context path.This approach is very convenient for testing existing web applications which are packed in WAR files, and you don’t have to touch their code.For this kind of application, generate the executable JAR file in the same way as described in the programmatic web application.
package net.codejava.servlet; import java.io.File; import javax.servlet.ServletException; import org.apache.catalina.LifecycleException; import org.apache.catalina.startup.Tomcat; public class EmbeddedTomcatTest { public static void main(String[] args) throws LifecycleException, ServletException { String contextPath = "/UploadApp"; String webappDir = new File("WebContent").getAbsolutePath(); Tomcat tomcat = new Tomcat(); tomcat.setBaseDir("temp"); tomcat.setPort(8080); tomcat.addWebapp(contextPath, webappDir); tomcat.start(); tomcat.getServer().await(); } }Now you can use your browser to access the web application using the specified port number and context path in the program above:
http://localhost:8080/UploadApp/upload.jsp
To generate executable JAR file for this kind of application, you need to use Tomcat Maven plugin as described here.