Install webapp under Apache/Tomcat

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 :

  1. Servlet, a Java's class used to handle HTTP requests, is dynamically loaded.
  2. 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.
  3. 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.
  4. 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.

Apache configuration

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

  2. 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>
    
  3. 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         
    
  4. 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

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

  2. The service reload is necessary

    We make this with the same command like at the previous step : sudo service apache2 reload

  3. 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).

  4. 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).

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

  6. 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).

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

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

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

If you liked it, you should read:

The comments are moderated. I publish them when I answer, so don't worry if you don't see yours immediately :)

📚 Newsletter Get new posts, recommended reading and other exclusive information every week. SPAM free - no 3rd party ads, only the information about waitingforcode!