Java web applications are specific. They need a servlet container to work. In this article we will see how to configure Apache and one of the most populars servlet containers, Tomcat, to work together.
Firstly, we will explain what is servlet container. After that, on second part, we will see how to configure Apache and Tomcat step by step.
What is servlet container ?
To undestand why we need to install servlet container on Apache, let's start by remind how does HTTP communication work ? HTTP is a protocol based on response-request and client-server model. It means that somebody (client) sends something (request) and is waiting for the reaction (response) of someone else (server). The analogy in the real world could be the telephone call. Person who make the number is one client. Has has one request (composed number). At the other side, there are one person who receives the call (server in HTTP meaning) and who produces the response (the 'Hello' pronounced by the call's receiver, in HTTP meaning it can be website corresponding to the request).
In HTTP, a browser is very often the client who sends the request. A web server, like Apache, is the server which returns the response. This communication works well on static files like HTML, zip or images. They are no calculation to make and the server serves the files immediately. But when the client demands some supplementary operations, like add 1 to 1, the web server can't respond successfully without supplementary help. It's the reason why we need some of "web server plugin" which is able to help web server. In our case, we'll consider web servlet container as this helper element.
Servlet container is a part of web server. The original request is always destinated to web server (Apache). According to its configuration, he can decide to abandon the request or pass it farther, to a servlet container for exemple. In the second case, some of operations are made inside the servlet container :
- Servlet, a Java's class used to handle HTTP requests, is dynamically loaded.
- init() method of previously retrieved servlet is invoked. This method is called only once, when the servlet is loaded. It must be executed successfully. Otherwise, the request won't be handle.
- The second servlet's method, service(), is called. In this method the application makes some operations to produce a response adequate to the request. For example, the application can produce a JSON response corresponding to request parameters as langue. The response is send after all of these treatments.
- The last method that can be invoked is destroy(). It's called when the servlet container wants to remove a servlet instance from the service. For exemple, destroy() can be invoked when the server needs more memory.
Each request has its own thread. And one servlet object can handle multiple thread's requests. Servlet container is there to manage all of these operations, like servlet instance creation and destroying.
Configure Tomcat on Apache
In our exemple, we want to set up a website available only in localhost, sandbox.lcom. At the first step, we will submit it as Apach's static resource. The setup scenario is destined only to Linux users.
Add new local subdomain
Edit the /etc/hosts file and put the sandbox.lcom domain at the end of the file :
... 127.0.0.1 localhost 127.0.0.1 sandbox.lcom
The 127.0.0.1 means the localhost IP address where the http://sandbox.lcom will be present.
Create a virtual host to Apache's standard 80 port.
Now, to test subdomain setup, we will make a virtual host to 80 port. A virtual host is a technic which make possible hosting multiple domain names on a single server. Make a new file inside your Apache directory, in our case, inside /etc/apache2/sites-available. The name of this file should be equal to the domain name specified in hosts file from previous step.
// file sandbox.lcom <VirtualHost *:80> DocumentRoot /home/bartosz/workspace/sandbox ServerName www.sandbox.lcom ServerAlias sandbox.lcom LogFormat "%h %l %u %t \"%r\" %>s %b" common CustomLog /home/bartosz/tmp/www/sandbox/access.log common ErrorLog /home/bartosz/tmp/www/sandbox/error.log </VirtualHost>
We activate new site and reload Apache
Actually our new domain is not actived. We need to enable it with a2ensite command:
bartosz@bartosz-K70ID:/etc/apache2/sites-available$ sudo a2ensite sandbox Enabling site sandbox. To activate the new configuration, you need to run: service apache2 reload
As printed on the screen, we have to reload Apache2 to activate new configuration. We do it with this command sudo service apache2 reload. You should see something like that :
bartosz@bartosz-K70ID:/etc/apache2/sites-available$ sudo service apache2 reload * Reloading web server config apache2
Check static file accessibility
Next, we check if one of the /home/bartosz/workspace/sandbox static files is accessible from the browser. For exemple, we can call http://sandbox.lcom/pom.xml. If we see an Maven configuration file, that means that the first step was made successfully.
Transform Apache configuration to Tomcat configuration
Transforming Apache configuration to Tomcat one is very simple
The only thing to do is replace Apache's default port 80 <VirtualHost *:80> by Tomcat's default port 8080 <VirtualHost *:8080> on our virtual host file. If Apache or Tomcat turns on different port, use the appropriated values.
The service reload is necessary
We make this with the same command like at the previous step : sudo service apache2 reload
To test the configuration, we call http://sandbox.lcom:8080
If the configuration was correctly made, we should see the default Tomcat page, like this one :
It works ! If you're seeing this page via a web browser, it means you've setup Tomcat successfully. Congratulations! This is the default Tomcat home page. It can be found on the local filesystem at: /var/lib/tomcat7/webapps/ROOT/index.html
It's important to add the :8080 port at the end of the URL. Otherwise, we will see the default Apache page (port 80 is reserved to Apache, 8080 to Tomcat).
Add new context
If we want to add new Java web applications, we need to add a new context. A context is like a directory with the application's files. It's not a directory but a XML description text where we can specify the application's base directory or the default logging strategy. The context is located in $CATALINA_BASE/conf/[enginename]/[hostname]/[webappname].xml or $CATALINA_BASE/webapps/[webappname]/META-INF/context.xml. In our case, we can find the context at this place : /etc/tomcat7/Catalina.
The XML file content looks like :
<?xml version='1.0' encoding='utf-8'?> <Context docBase="/home/bartosz/workspace/sandbox/target/sandbox" path="librarySpring"> <Valve className="org.apache.catalina.valves.AccessLogValve" prefix="localhost_access_log." suffix=".txt" pattern="common" directory="/home/bartosz/logs/" /> </Context>
To activate it, first we make a new directory with domain name. After, we put the configuration file inside it:
cd /etc/tomcat7/Catalina; mkdir sandbox.lcom; gedit ROOT.xml
At the last command, a Gedit window will open. Put inside the XML context and save. You check if everything works well by accessing your webapp from browser. The ROOT.xml name is very important. Thanks to it, Tomcat7 knows which context corresponds to main domain name (sandbox.lcom in case).
Activate domain in Tomcat
Single context is not sufficent to make working a webapp under Tomcat. In additionally, we need to add a host definition in /etc/tomcat7/server.xml file :
<Host name="sandbox.lcom" autoDeploy="true" unpackWARs="true" appBase="/home/bartosz/test"> <Alias>www.sandbox.lcom l&;tValve className="org.apache.catalina.valves.AccessLogValve" prefix="sandbox.lcom_access_log." suffix=".txt" pattern="%h %l %u %t "%r" %s %b" directory="/home/bartosz/logs/" /> </Host>
This fragment must be added under <Engine /> tag.
Add workers on virtual host
Tomcat doesn't know how it must handle the request without the workers. A worker is a instance of Tomcat which are listening to web server events. When the configuration of one worker corresponds to request received by the web server, the request is transmitted to the appropriated Tomcat's worker. For now we won't enter into the details. The only thing to do, will be the workers configuration on the virtual host file :
// these lines need to be added before VirtualHost closing tag # Uncomment this line if jk module isn't present in /etc/apache2/mods-enabled LoadModule jk_module /usr/lib/apache2/modules/mod_jk.so JkMount /* sandboxWorker
JkMount reffers to a mod_jk Apache module which must be installed to enable Tomcat's workers. To check if this module is enabled, we go to /etc/apache2/mods-enabled directory and look for jk.conf file.
Additionally, remove the pointing to :8080 port from the VirtualHost tag. You must replace it by the host presented there at the begin (:80 in our case).
Add workers on Apache configuration
The worker's configuration has to be made at the Apache file, /etc/apache2/workers.properties. We add there a libraryWorker, defined on the virtual host file :
worker.list=sandboxWorker worker.sandboxWorker.type=ajp13 # host corresponds to ServerName entry from virtual host configuration worker.sandboxWorker.host=www.sandbox.lcom # port corresponds to AJP 1.3 Connector from Tomcat's server.xml file worker.sandboxWorker.port=8009
Now we return to /etc/apache2/mods-enabled/jk.conf file and check if the entry configuration, JkWorkersFile, points to /etc/apache2/workers.properties file. If it's not the case, we must edit it.
Add workers on Tomcat configuration
Actually, we have to configure workers on Tomcat side. We open the /etc/tomcat7/server.xml and active the connector :
<!-- Define an AJP 1.3 Connector on port 8009 --> <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
A connector represents the endpoint by which requests are received and responses are returned.
New domain's ROOT.xml file
To add new domain to Tomcat 7, we need to make a new directory which name is the same as the domain name. The directory must be made at this localisation : /etc/tomcat7/Catalina/. In our exemple, we'll make the sandbox.lcom directory. The content of it must be a ROOT.xml file. The name is very important because this file is looked by Tomcat 7 for each domain. For exemple, if we have a domain localhost, the configuration for http://localhost:8080 will be placed on /etc/tomcat7/Catalina/localhost/ROOT.xml file. The ROOT.xml's content is :
<Context path="/" docBase="/home/bartosz/workspace/sandbox/target/sandbox" antiResourceLocking="false"> <Valve className="org.apache.catalina.valves.AccessLogValve" prefix="librarysample." suffix=".txt" pattern="%h %l %u %t "%r" %s %b" directory="/home/bartosz/logs/" /> </Context>
This configurations means that it's applied to http://sandbox.lcom/ (path="/"). The http://sandbox.lcom/ files are placed on /home/bartosz/workspace/sandbox/target/sandbox directory (docBase="/home/bartosz/workspace/sandbox/target/sandbox"). The attribute antiResourceLocking means that Tomcat won't lock the files. The <Valve /> configuration is applied to logging system. We retreive there a logging pattern (pattern's attribute), logging file prefix and suffix, and the logging files directory.
In this article we seen how to configuration Apache and Tomcat to work together. In the first part we explained that the servlet container is responsible for manage the dynamic client demands. After that we implement Tomcat to make this job with Apache.