We know how to
install a Tomcat server, deploy applications to that and work with them. In this
article we will see how we can use all of the tomcat features in a independent
Java application by embedding tomcat into that.
Why do we need to embed the Tomcat?
During cases where
we need to test out application, we need run the test cases where tomcat is
installed. One more case where we need to include a servlet container run with
in out stand-alone java application so that we can run the web application on
only user local machine. During these cases with Tomcat 7 we don’t need a
install a separate tomcat, we just need to embed them into our code and ship it
as one integral piece of software.
In order to embed
the tomcat server into our java application, we need to use some of the
libraries that help in the integration.
Apache Tomcat 7 has
a special version for embedding purpose. This can be downloaded from http://tomcat.apache.org/download-70.cgi.
Once we un-pack that we will see multiple jars which help in the integration of
the embed tomcat.
Ecj.jar
- Eclipse JSP compiler, this will be used by the Jasper Engine to compile JSP
files
Tomcat-embed-core.jar
– Core Tomcat classes, this contain the main implementation of the tomcat
server
Tomct-dbcp.jar
– Apache DBCP integration classes, this is used for JDBC integration with in
the embed tomcat instance
Tomcat-embed-jasper.jar – Tomcat JSP Engine
Tomcat-embed-logging-juli.jar – JULI logging library integration
Tomcat-embed-logging-log4j.jar – Log4j logging library integration
The main classes
for embedding tomcat 7 with in your application are the tomcat-embed-core.jar
file. This contains implementation of all the architectural concepts of Apache
tomcat such as Server Engine, Service , Connector and Host. The main class that
we use is the org.apache.cataline.startup.Tomcat which provides the embedded server
wrapper. This is found in tomcat-embed-core.jar file.
In addition to
these we need at least one logging integration library to enable logging of our
embedded tomcat instance. And also a JSP compiler to server JSP classes for our
stand-alone Tomcat. The Jasper engine can be found in the tomcat-embed-jasper.jar library. This jar file contains JSP API interfaces and
classes as well, so there is no need to include jsp-api.jar library separately.
Along with this we
need to have a JSP compiler for compiling the code. Tomcat 7 ships with
A Eclipse JSP
engine “ecj” library. This can be
usedt to compile JSP files (*.jsp) to standard Java binary compiled files
(*.class) that can be executed by JVM. The other jar files will be used in
integrating JDBC code with our embed tomcat instance. We will not be using this
in our example.
Embed Components
When using Tomcat
server, we do have a server.xml which defines the way the server will run. This
file contains elements that we configure for the working of the server. When
using embed tomcat instance, the file will not be available and it is the
responsibility of the developer to assemble components.
The tomcat-embed-core.jar
files contains the main classes that correspond to the tomcat architectural
components and they are
Interface Component Description
Org.apache.catalina.Server Server Entire Tomcat
Instance
Org.apache.catalina.Service Service Holder for Engine,accessed
by Connector
Org.apache.catalina.Connector Connector Connections for Tomcat Instance
Org.apache.cataline.Engline Engine Servlet Engine
Org.apache.catalina.Host Host Host where application runs
Org.apache.catalina.Context Context application context
to be accessed
Tomcat helps
developers by providing a implementation of these interfaces that we can use
directly into our application. This is done by using org.apache.catalina.core.StandardServer
which is a standard implementation of the Server interface and also org.apache.catalina.core.StandardEngine which is a standard implementation of Tomcat’s servlet
engine.
Most often you need
to embed a single Tomcat instance, with a single Server, single Service, and
single Engine to your Java application, and run one or more web applications in it. For that purpose, Tomcat’s embedded
distribution comes with the convenient class org.apache.catalina.startup.Tomcat, which contains this minimal set up out of the box. All you
have to do is instantiate this class, and start using embedded Tomcat server in
your Java application.
Implementation
Now we will see how
we can implement a sample java application with an embed Tomcat Instance.
package com.embedTomcat;
import javax.servlet.ServletException;
import org.apache.catalina.LifecycleException;
import
org.apache.catalina.core.AprLifecycleListener;
import org.apache.catalina.core.StandardServer;
import org.apache.catalina.startup.Tomcat;
public class
StandaloneEmbedTomcat {
Tomcat tomcat;
private
void startTomcat() throws ServletException, LifecycleException {
this.tomcat = new
Tomcat();
this.tomcat.setPort(8080);
this.tomcat.setBaseDir(".");
String contextPath = "/DemoExample";
String appBase = "C:/Users/xprk477/Desktop/AppsWork/New
folder";
this.tomcat.addWebapp(contextPath,
appBase);
this.tomcat.start();
//http://localhost:8080/DemoExample
}
void
stopTomcat() throws
LifecycleException {
this.tomcat.stop();
}
public static void
main(String args[]) {
try {
StandaloneEmbedTomcat
tomcat=new StandaloneEmbedTomcat();
tomcat.startTomcat();
Thread.sleep(100000);
tomcat.stopTomcat();
} catch (Exception e){
e.printStackTrace();
}
}
}
The code written is
simple and self-explanatory. First, we instantiated the org.apache.catalina.startup.Tomcat class. As we said earlier this will take care of
the components in Tomcat. Next we set the port, base directory, context path,
and appbase.
Though the tomcat
instance will be instantiated in memory, we don’t need to set the real base
directory (CATALINA_HOME) but since we are using JSP we need a temp location to
store compiled JSP’s and it’s set relative to the base directory configured. We
set it to the project’s working directory (".").
Now
that we have a configured an embedded Tomcat instance, let’s start the Tomcat
instance, using Tomcat.start() method.
Now
we have embedded Tomcat up and running and listening for a shutdown command.
But it won’t shut down itself – that’s why we implemented stop()method,
which simply invokes Tomcat.stop(), which in
turn issues the shutdown command that our server expects (because of previous await()).
In our example we
have used sleep() method to keep tomcat instance running for some time but in
real world we don’t need to do that since we can call the Server.await() method
on the Server instance configured for the embedded Tomcat we’re
using. Calling await() on the server tells
Tomcat to keep running, but listen to any shutdown command issued. That way,
when the shutdown command is issued (by the same or another process or thread),
the server will shut down gracefully. Here is the line of code to achieve this:
this.tomcat.getServer().await();
Demo
Once we start the
java application we can see logs as,
Jun 1, 2015
11:39:24 PM org.apache.catalina.core.AprLifecycleListener lifecycleEvent
INFO: The APR based
Apache Tomcat Native library which allows optimal performance in production
environments was not found on the java.library.path: C:\Program
Files\Java\jdk1.6.0_25\bin;.;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:\Program
Files\HP_Fortify\HP_Fortify_SCA_and_Apps_3.80\bin;c:\oracle\ora-10.02.00.04\bin;C:\software\Perl\site\bin;C:\software\Perl\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program
Files (x86)\Teradata\Client\13.0\ODBC Driver for Teradata\Lib\;C:\Program Files
(x86)\Teradata\Client\13.0\Shared ICU Libraries for Teradata\lib\;C:\Program
Files (x86)\Java\jdk1.6.0_10\bin;C:\Program Files
(x86)\TortoiseSVN\bin;c:\software\maven\2.0.11\bin
Jun 1, 2015 11:39:25
PM org.apache.coyote.AbstractProtocol init
INFO: Initializing
ProtocolHandler ["http-bio-8080"]
Jun 1, 2015
11:39:25 PM org.apache.catalina.core.StandardService startInternal
INFO: Starting
service Tomcat
Jun 1, 2015
11:39:25 PM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting
Servlet Engine: Apache Tomcat/7.0.62
Jun 1, 2015
11:39:25 PM org.apache.catalina.startup.ContextConfig getDefaultWebXmlFragment
INFO: No global
web.xml found
Jun 1, 2015
11:39:25 PM org.apache.catalina.startup.TldConfig execute
INFO: At least one
JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this
logger for a complete list of JARs that were scanned but no TLDs were found in
them. Skipping unneeded JARs during scanning can improve startup time and JSP
compilation time.
Jun 1, 2015
11:39:25 PM org.apache.coyote.AbstractProtocol start
INFO: Starting
ProtocolHandler ["http-bio-8080"]
The last line tells
the Tomcat Instance is started. Access the application using
More to Come, Happy
learning J