Tomcat Notes

This is a little lame. It's really a place to put notes until I get better organized.

A good link for installing Tomcat (and its issues) on Ubuntu Server is https://help.ubuntu.com/10.04/serverguide/tomcat.html


servlet-api.jar
    [Tomcat] validateJarFile(servlet-api.jar) - jar not loaded. Offending class: javax/servlet/Servlet.class

    org.apache.catalina.loader.WebappClassLoader validateJarFile
    INFO: validateJarFile(\WEB-INF\lib\servlet-api.jar) - jar not loaded. See Servlet Spec 2.3, \
        section 9.7.2. Offending class: javax/servlet/Servlet.class.

Note that servlet-api.jar already exists in Tomcat. This message isn't anything more than a warning, but it's annoying. It means simply that you've included another instance of servlet-api.jar in your build path (see Eclipse Build Path or the .classpath file). Simply remove this JAR from your build letting Tomcat supply it.


APR Apache Tomcat Native library

You see this starting Tomcat. It's no more than a warning. In order to overcome it, you'd have to go to some trouble. Google for it.

    INFO: The APR based Apache Tomcat Native library which allows optimal performance in production \
        environments was not found on the java.library.path: \
        /home/russ/dev/jdk1.6.0_31/jre/lib/amd64/server:/home/russ/dev/jdk1.6.0_31/jre/lib/amd64:\
        /home/russ/dev/jdk1.6.0_31/jre/../lib/amd64:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib

See http://stackoverflow.com/questions/8716259/what-does-the-apr-based-apache-tomcat-native-library-was-not-found-mean.

What this means is:

  1. You shouldn't worry about this during development; it's just a warning.
  2. If this is a concern in production, and perhaps it should be, the only thing that can be done about it is to download Apache code and build a libnative.so for the platform that's going to execute your production application. See http://tomcat.apache.org/tomcat-6.0-doc/apr.html#Installation.

SSL and Tomcat's server.xml

Tomcat's server.xml file is amended thus in the face of implementing HTTPS. The part in bold type is what's added to an otherwise stock server.xml:

    <!-- A "Connector" represents an endpoint by which requests are received
         and responses are returned. Documentation at :
         Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
         Java AJP  Connector: /docs/config/ajp.html
         APR (HTTP/AJP) Connector: /docs/apr.html
         Define a non-SSL HTTP/1.1 Connector on port 8080
    -->
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               URIEncoding="UTF-8"
               redirectPort="8443" />

    <!-- We added this next paragraph in recognition that Big IP will send
         secure (formerly encrypted) requests through port 8081 and calling
         ContainerRequest.isSecure() will return true.
    -->
    <Connector port="8081" protocol="HTTP/1.1"
               connectionTimeout="20000"
               URIEncoding="UTF-8"
               scheme="https"
               secure="true"
    />

If Tomcat's handling this by itself, in the situation where there is no Big IP or load-balancer, the traffic comes in encrypted over 443 (instead of 8081) and Tomcat decrypts it.


SSL and Tomcat's server.xml (part 2)

There is a second part to this equation. The following section(s), if present, must be removed (commented out) from server.xml:

     <!-- Define a SSL HTTP/1.1 Connector on port 8443
          This connector uses the JSSE configuration, when using APR, the
          connector should be using the OpenSSL style configuration
          described in the APR documentation -->
     <!-- Comment this out as we don't use SSL; instead we get secure traffic over 8081
     <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
                maxThreads="150" scheme="https" secure="true"
                clientAuth="false" sslProtocol="TLS" />
     -->

The lines being commented out come by default in the stock Tomcat server.xml. The traffic is unencrypted by the load balancer and passed over port 8081 instead of 8443 and we want to stop listening on port 8443 which will otherwise give us keystore errors like:

    Aug 09, 2013 4:55:12 PM org.apache.tomcat.util.net.jsse.JSSESocketFactory getStore
    SEVERE: Failed to load keystore type JKS with path /usr/share/tomcat6/.keystore due to /usr/share/tomcat6/.keystore (No such file or directory)
    java.io.FileNotFoundException: /usr/share/tomcat6/.keystore (No such file or directory)
            at java.io.FileInputStream.open(Native Method)
            at java.io.FileInputStream.(FileInputStream.java:138)
            at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getStore(JSSESocketFactory.java:405)
            at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getKeystore(JSSESocketFactory.java:296)
            at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getKeyManagers(JSSESocketFactory.java:544)
            at org.apache.tomcat.util.net.jsse.JSSESocketFactory.init(JSSESocketFactory.java:481)
            at org.apache.tomcat.util.net.jsse.JSSESocketFactory.createSocket(JSSESocketFactory.java:156)
            at org.apache.tomcat.util.net.JIoEndpoint.init(JIoEndpoint.java:538)
            at org.apache.coyote.http11.Http11Protocol.init(Http11Protocol.java:176)
            at org.apache.catalina.connector.Connector.initialize(Connector.java:1049)
            at org.apache.catalina.core.StandardService.initialize(StandardService.java:703)
            at org.apache.catalina.core.StandardServer.initialize(StandardServer.java:838)
            at org.apache.catalina.startup.Catalina.load(Catalina.java:538)
            at org.apache.catalina.startup.Catalina.load(Catalina.java:562)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:601)
            at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:261)
            at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)

    Aug 09, 2013 4:55:12 PM org.apache.coyote.http11.Http11Protocol init
    SEVERE: Error initializing endpoint
    java.io.FileNotFoundException: /usr/share/tomcat6/.keystore (No such file or directory)
            at java.io.FileInputStream.open(Native Method)
            at java.io.FileInputStream.(FileInputStream.java:138)
            at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getStore(JSSESocketFactory.java:405)
            at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getKeystore(JSSESocketFactory.java:296)
            at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getKeyManagers(JSSESocketFactory.java:544)
            at org.apache.tomcat.util.net.jsse.JSSESocketFactory.init(JSSESocketFactory.java:481)
            at org.apache.tomcat.util.net.jsse.JSSESocketFactory.createSocket(JSSESocketFactory.java:156)
            at org.apache.tomcat.util.net.JIoEndpoint.init(JIoEndpoint.java:538)
            at org.apache.coyote.http11.Http11Protocol.init(Http11Protocol.java:176)
            at org.apache.catalina.connector.Connector.initialize(Connector.java:1049)
            at org.apache.catalina.core.StandardService.initialize(StandardService.java:703)
            at org.apache.catalina.core.StandardServer.initialize(StandardServer.java:838)
            at org.apache.catalina.startup.Catalina.load(Catalina.java:538)
            at org.apache.catalina.startup.Catalina.load(Catalina.java:562)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:601)
            at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:261)
            at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)

    Aug 09, 2013 4:55:12 PM org.apache.catalina.core.StandardService initialize
    SEVERE: Failed to initialize connector [Connector[HTTP/1.1-8443]]
    LifecycleException:  Protocol handler initialization failed: java.io.FileNotFoundException: /usr/share/tomcat6/.keystore (No such file or directory)
            at org.apache.catalina.connector.Connector.initialize(Connector.java:1051)
            at org.apache.catalina.core.StandardService.initialize(StandardService.java:703)
            at org.apache.catalina.core.StandardServer.initialize(StandardServer.java:838)
            at org.apache.catalina.startup.Catalina.load(Catalina.java:538)
            at org.apache.catalina.startup.Catalina.load(Catalina.java:562)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:601)
            at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:261)
            at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
            ...

How to use a Sun JRE with Tomcat...

This assumes that on an Ubuntu Precise Server installation, only the OpenJDK is installed, which it is by default. This example assumes Java 1.6, call it jdk1.6.0_38 for the sake of our illustration.

There are reasons you want to do this. One is the ability to run more competent encryption/hashing.

First, you can see which JVM is being used by Tomcat via this command:

    $ ps -ef | grep [t]omcat

Likely, it will be /usr/lib/jvm/default-java/bin/java. If you list this path, you'll see that it's the non-Sun OpenJDK.

    $ ll /usr/lib/jvm/default-java
    lrwxrwxrwx 1 root root 24 Jan 29 06:30 /usr/lib/jvm/default-java -> java-1.6.0-openjdk-amd64/
  1. Download the Sun JRE or JDK from http://java.sun.com; download the .bin file. At time of writing, once you've reached this page, you'd hover over DOWNLOADS and choose Java for Developers under "Popular Downloads".
  2. Copy the .bin over to your server.
  3. Copy the .bin file to /usr/local, make it executable and explode it.
  4. Go to /usr/local.
  5. Create a new link, jdk1.6.0_38 to point at the new JDK/JRE or just move the whole JDK/JRE to this path.
  6. Own the exploded download (chown -R root:root jdk1.6.0_38).
  7. Go to /usr/lib/jvm.
  8. Create a link named java-6-oracle to /usr/local/jdk1.6.0_38.
  9. Create a new link named default-java (or, replace the one that's there) to point at ./java-6-oracle. This is the key to getting Tomcat to use it (examine /etc/init.d/tomcat6, search for "default-java" and you'll understand).

At this point, bounce Tomcat and you'll see that it's running atop the real, Sun JDK/JRE.

    $ /etc/init.d/tomcat6 restart
    $ ps -ef | grep [t]omcat
    (stuff similar to what you saw before except...)
    $ ll /usr/lib/jvm/default-java
    lrwxrwxrwx 1 root root 24 Jan 29 06:30 /usr/lib/jvm/default-java -> java-6-oracle/

Tomcat-deployed application behaves peculiarly (load-balancing)...

If one leg of your load-balanced application is not up, you could experience peculiarities like missing CSS, images, etc.


See if Tomcat is holding port 8080

To see whether Tomcat is running on 8080, do this:

    [email protected]:# lsof -i :8080
    COMMAND PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
    java    916 tomcat6   33u  IPv6   7764      0t0  TCP *:http-alt (LISTEN)

Log files too big, flooding disk, etc....

If you're out of space or even catalina.out gets much over 500Mb, you could fail to deploy new or redeploy existing applications because of it.

Good rules of thumb for this configuration are:


JAVA_HOME for Tomcat

There's lots of idiocy out there when you look for this. Most of it comes from a Windoz orientation. However, others seem to answer not knowing that the user tomcat6 isn't something you can "become" (via su), have a "home" directory, etc.

At least for Ubuntu and Mint, the place to look is /etc/default/tomcat6, a file that contains a lot of settings or commented-out potential settings.

If you want to switch what version of Java your Tomcat installation is running on, there are two, good ways. Let's imagine you want to begin running Java 7 instead of 6.

  1. As just alluded, tweak the value for JAVA_HOME in /etc/default/tomcat6 to point at the Java 7 you installed.
  2.  
  3. Determine what version of Java is available and where it's running. You should see something like this:
        # which java
        /usr/bin/java
        # java -version
        java version "1.7.0_21"
        OpenJDK Runtime Environment (IcedTea 2.3.9) (7u21-2.3.9-0ubuntu0.12.04.1)
        OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)
    
     
  4. Install, e.g.: openjdk7, then uninstall openjdk6. Don't touch any definitions of JAVA_HOME anywhere. This is the approach to take if you're dealing with a VM running nothing but Tomcat (and your web application suite).
        # java -version
        java version "1.6.0_27"
        OpenJDK Runtime Environment (IcedTea6 1.12.5) (6b27-1.12.5-0ubuntu0.12.04.1)
        OpenJDK 64-Bit Server VM (build 20.0-b12, mixed mode)
        # apt-get update
        # apt-get install openjdk-7-jre
        (installs latest, known Java 7)
        # apt-get purge openjdk-6-jre-headless
        (removes Java 6 and dependencies; lose system notion of Java)
    

    Ordinarily, however, on Ubuntu server systems I've installed using mostly defaults I have not had anything to do past this point.

  5. You should examine /etc/alternatives to see if everything is good.
        # cd /etc/alternatives
        /etc/alternatives # ln -s /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/javaws*
        (updates system notion of Java which was lost)
        # java -version
        java version "1.7.0_21"
        OpenJDK Runtime Environment (IcedTea 2.3.9) (7u21-2.3.9-0ubuntu0.12.04.1)
        OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)
    

    If everything is okay, you should see only Java 7 here:

        [email protected]:/etc/alternatives# ll java*
        lrwxrwxrwx 1 root root 46 Nov 12 21:01 java -> /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java*
        lrwxrwxrwx 1 root root 56 Nov 12 21:01 java.1.gz -> /usr/lib/jvm/java-7-openjdk-amd64/jre/man/man1/java.1.gz
    

    If this wasn't enough, note that replacing Java 6 with 7 is not for the faint-hearted. You need to do more than simply install openjdk/jre 7 or Sun Java 7. You also have to update the Java "alternatives" to make it look more or less like the above. (Or see below for a more twisted result.)

* Despite complaints and claims to the contrary out there, there is no way update-java-alternatives will update the javaws links; you have to do it by hand. However, you need not do it if this link was not there in the first place.

More notes

On occasion, the above is insufficient and you can still see this in the Tomcat Web Application Manager, the wrong JVM:

(To get into the manager go to http://hostname:port/manager/html. If you don't know how to respond to the authentication dialog, see below.)

I thought I had laid to rest the question of which JVM would hold sway on the server host. Following is a picture I hope will be a thousand words. Please note especially the lines in bold which describe the state of things after I fixed the remaining trouble.

[email protected]:/usr/lib/jvm# ll
total 24
drwxr-xr-x  5 root root 4096 Nov  6 16:06 ./
drwxr-xr-x 64 root root 4096 Nov  6 14:18 ../
lrwxrwxrwx  1 root root   21 Nov  6 16:06 default-java -> java-7-openjdk-amd64//
lrwxrwxrwx  1 root root   20 Jul 15 19:46 java-1.7.0-openjdk-amd64 -> java-7-openjdk-amd64/
-rw-r--r--  1 root root 2439 Jul 15 19:46 .java-1.7.0-openjdk-amd64.jinfo
lrwxrwxrwx  1 root root   15 Jan 25  2013 java-6-sun -> /usr/local/java/
drwxr-xr-x  5 root root 4096 Nov  6 14:17 java-7-openjdk-amd64/
drwxr-xr-x  3 root root 4096 Nov  6 14:17 java-7-openjdk-common/
drwxr-xr-x  2 root root 4096 Feb 26  2012 java-7-oracle/
lrwxrwxrwx  1 root root   10 Jan 25  2013 old-default-java -> java-6-sun/

Links to peruse:


Application deployed, but Tomcat gives back HTTP Status 404 Not Found

There are many reasons this can happen. One that might escape is that the application was deployed (i.e.: it shows up in /var/lib/tomcat6/webapps), but it failed to start up. Examine the log, /var/log/tomcat6/catalina.out to see why. Perhaps you were trying to connect to your database node(s), but had forgotten to update the application server's /etc/hosts file with the mappings to those hosts and they aren't know to DNS. Etc.


The SEVERE: Error filterStart mess...

In catalina.out, you might find mysteriously, one of...

    SEVERE: Error filterStart
    SEVERE: Error listenerStart

...when you try to start your application. By default, Tomcat won't tell you intelligently what's happening. It won't even tell you which filter or listener is failing. The solution is very simple:

  1. Under Tomcat's webapps folder, under your deployed application, create WEB_INF/class/logging.properties—even if you've already got log4j.properties, etc. there.
  2. Add the following content to this file:
        org.apache.catalina.core.ContainerBase.[Catalina].level = ALL
        org.apache.catalina.core.ContainerBase.[Catalina].handlers = java.util.logging.ConsoleHandler
    
  3. Clear out catalina.out if you like to squint through less output.
  4. Bounce Tomcat:
        $ service tomcat6 restart
    

You should see a proper stacktrace with all the verbosity you need to sort this problem out.


Useless ${catalina.home} property...

...after installing Tomcat 6. Old Apache log4j like Apache Tomcat 5.5 Servlet/JSP Container: Logging in Tomcat says to use statements like

    log4j.appender.R.File=${catalina.home}/logs/myapp.log

...where myapp.log is the name you invent for the logfile different from catalina.out.

This won't work, at very least, on Debian platforms where ${catalina.home} points at /usr/share/tomcat6, which has no logs subdirectory or link to /var/log/tomcat6 where catalina.out lives. Use ${catalina.base} instead; it points at /var/lib/tomcat6 which has logs as a symbolic link to /var/log/tomcat6.

When you see something like...

    log4j:ERROR setFile(null,true) call failed.
    java.io.FileNotFoundException: /usr/share/tomcat6/logs/myapp.log (No such file or directory)
            at java.io.FileOutputStream.open(Native Method)
            at java.io.FileOutputStream.(FileOutputStream.java:212)
            at java.io.FileOutputStream.(FileOutputStream.java:136)
            at org.apache.log4j.FileAppender.setFile(FileAppender.java:294)
            at org.apache.log4j.FileAppender.activateOptions(FileAppender.java:165)
            at org.apache.log4j.DailyRollingFileAppender.activateOptions(DailyRollingFileAppender.java:223)
            at org.apache.log4j.config.PropertySetter.activate(PropertySetter.java:307)
            at org.apache.log4j.config.PropertySetter.setProperties(PropertySetter.java:172)
            at org.apache.log4j.config.PropertySetter.setProperties(PropertySetter.java:104)
            at org.apache.log4j.PropertyConfigurator.parseAppender(PropertyConfigurator.java:809)
            at org.apache.log4j.PropertyConfigurator.parseCategory(PropertyConfigurator.java:735)
            at org.apache.log4j.PropertyConfigurator.configureRootCategory(PropertyConfigurator.java:615)
            at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:502)
            at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:547)
            at org.apache.log4j.helpers.OptionConverter.selectAndConfigure(OptionConverter.java:483)
            at org.apache.log4j.LogManager.(LogManager.java:127)
            at org.apache.log4j.Logger.getLogger(Logger.java:117)
            at com.hp.web.util.ApplicationProperties.(ApplicationProperties.java:17)
            at com.hp.web.controller.AppInitializer.contextInitialized(AppInitializer.java:20)
            at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4206)
            at org.apache.catalina.core.StandardContext.start(StandardContext.java:4705)
            at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:799)
            at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:779)
            at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:601)
            at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:943)
            at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:778)
            at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:504)
            at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1385)
            at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:306)
            at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:142)
            at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1389)
            at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1653)
            at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1662)
            at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1642)
            at java.lang.Thread.run(Thread.java:722)

...it's because Tomcat is unable to create /usr/share/tomcat/logs/myapp.log. This is because the path to it doesn't exist.


Getting into the Tomcat Web Application Manager

To get into the manager go to http://hostname:port/manager/html. If you don't know what to respond to the authentication dialog, it's because /etc/tomcat6/tomcat-users.xml has nothing in it. You'll want to add...

        .
        .
        .
        <role rolename="manager"/>
        <role rolename="manager-gui"/>
        <role rolename="admin"/>
        <user username="user" password="password" roles="admin,manager,manager-gui"/>
    </tomcat-users>

...inside the <tomcat-users> tag. Replace user and password with something a little more secure.


How to make a web application Tomcat's root application

Add a file called ROOT.xml in $CATALINA_HOME/conf/Catalina/localhost/

ROOT.xml will override the default settings for the root context of the Tomcat installation for that engine and host (Catalina and localhost).

Enter the following to the ROOT.xml file:

<Context docBase="yourApp" path="" reloadable="true" />

Here, yourApp is the name of your application.

And there you go, your application is now the default application and will show up on http://localhost:8080.

However, there is one side effect; your application will be loaded twice. Once for localhost:8080 and once for localhost:8080/yourApp. To fix this you can put your application OUTSIDE $CATALINA_HOME/webapps and use a relative or absolute path in the ROOT.xml's docBase tag. Something like this:

<Context docBase="/opt/mywebapps/yourApp" path="" reloadable="true" />

Tomcat context

Individual Context elements may be explicitly defined:


Tomcat 6 access log example

In Tomcat's server.xml file, at the bottom, you can awaken ('cause it ships commented out) the access log by uncommenting and configuring it. Here's something I did one day, with consideration for Tomcat 7 and solving a problem explained in the additional comment:

  <!-- Access log processes all example.
       Documentation at: /docs/config/valve.html -->
  <!--
       Note: this is uncommented giving us 1 second granularity in the
       log entries, see
       http://tomcat.apache.org/tomcat-6.0-doc/config/valve.html

       Millisecond granularity will (only) come after moving to Tomcat 7.
       The "common" pattern, even in Tomcat 7, does not include this, so
       it will explicitly become "%h %l %u %{msec}t "%r" %s %b". See
       https://tomcat.apache.org/tomcat-7.0-doc/config/valve.html
    -->
  <Valve className="org.apache.catalina.valves.AccessLogValve"
         directory="/home/fs/log"
         prefix="tomcat-access."
         suffix="log"
         pattern="%h %{x-forwarded-for}i; %H %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" %Dms"
         resolveHosts="false"
         rotatable="false"
         checkExists="true"
              />

Debugging the dreaded "SEVERE: ERROR LISTENERSTART"
"SEVERE: ERROR LISTENERSTART" AND "SEVERE: ERROR FILTERSTART" TOMCAT ERROR MESSAGES

The errors being sparse, I add logging.properties to src with contents:

org.apache.catalina.core.ContainerBase.[Catalina].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].handlers = java.util.logging.ConsoleHandler

Forcing Tomcat to use NIO...

From a certain Faheem Sohail...

In HTTP 1.1, all connections between the browser and the server are considered persistent unless declared otherwise. Persistence, in this context, means to use a single TCP connection to send and receive multiple HTTP requests/responses, as opposed to opening a new connection for every single request/response pair.

In Tomcat, the default HTTP connector is blocking and follows a one thread per connection model. This means that in order to serve 100 concurrent users, it requires 100 active threads. We end up wasting resources (the thread) because connections may not be used heavily, but just enough to avoid a timeout.

Opposed to this is the relatively new NIO or non blocking connector. This connector has a couple of poller threads used to keep the connection alive for all connected users while worker threads are called whenever data (a new HTTP request) is available. This model leads to a much better sharing of resources (threads) and a larger number of concurrent users can be served from the same server.

In order to configure tomcat to use the non-blocking NIO connector instead of the default blocking BIO one simply change the value of the protocol attribute of the connector tag in the server.xml from HTTP/1.1 to org.apache.coyote.http11.Http11NioProtocol.


To verify that you indeed are using the NIO connector, take a look at the start-up logs. You should see lines similar to this.

Mar 28, 2014 3:59:04 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-nio-8080"]
Mar 28, 2014 3:59:04 PM org.apache.tomcat.util.net.NioSelectorPool getSharedSelector

Use VisualVM to look at the threads being created in both cases. You’ll find NIO to use threads much more efficiently.