1. debugging the dreaded "Severe: Error ListenerStart" and "Severe: Error FilterStart Tomcat Error Messages
  2. source

    Just a quick post that I hope might benefit others. If you have been developing web applications on Tomcat for a while you have likely come the two error messages mentioned in the title.

    Unfortunately by default, Tomcat won't provide you with any details about the cause of the error. Infact it wont even tell you which filter or listener is failing. This can be big problem in applications of significant size that have many filters and listeners configured. Fortunately there is a solution. In your webapplication's WEB-INF/classes folder you can create a logging.properties file with the following contents

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

    Now you will be presented with the stacktrace

  3. Tomcat support JSP / EL / Java versions per version / release
  4. Apache Tomcat versions support matrix

    To find the exact Tomcat version / release use the script version.sh which, e.g., in Ubuntu 12.04 is located in:

    /usr/share/tomcat7/bin/version.sh

  5. how to configure Tomcat7 to serve static content
  6. How to deal with the dreaded SEVERE: Error filterStart log entry in Tomcat
  7. The problem with this error is that in the default configuration of Tomcat, this is all you see. No additional information, nada.
    I was able to get a proper stack trace and solve my particular problem by changing the logging.properties file of my Tomcat installation.
    In my Ubuntu 14.04 system said file was located at:
    /var/lib/tomcat7/conf/logging.properties
    I basically had to effect two orthogonal changes:
    Here are the changes:
    $ diff /var/lib/tomcat7/conf/logging.properties /var/lib/tomcat7/conf/logging.properties.orig
    41,42c41,42
    < org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = FINE
    < org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = 2localhost.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
    ---
    > org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
    > org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = 2localhost.org.apache.juli.FileHandler
          
    And here are the original and the modified logging.properties files.
  8. How to deal with BasicDataSourceFactory class not found
  9. This is the exception:

    message javax.naming.NamingException: Could not load resource factory class [Root exception is java.lang.ClassNotFoundException: org.apache.commons.dbcp.BasicDataSourceFactory]

    The root cause of the exception is that in the context.xml file, the Resource is defined to use the Apache-provided factory class:
        <Resource name="jdbc/postgres/silly-test-database"
                  auth="Container"
                  type="javax.sql.DataSource"
                  driverClassName="org.postgresql.Driver"
                  url="jdbc:postgresql://localhost:5432/radoverview"
                  username="radoverview-user" password="radoverview-user-pass"
                  factory="org.apache.commons.dbcp.BasicDataSourceFactory" 
                  maxActive="2" maxIdle="0" maxWait="-1"/>
    
    Whereas the default DataSource factory in Tomcat7 is
    org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory
    and is sometimes distributed in the tomcat-dbcp.jar. E.g.:
    radacer@radacer ~]$ jar tvf apache-tomcat-7.0.68/lib/tomcat-dbcp.jar | grep -i BasicDataSourceFactory
    8176 Mon Feb 08 22:27:06 EET 2016 org/apache/tomcat/dbcp/dbcp/BasicDataSourceFactory.class
    
    To solve this problem it is necessary that either:
    a couple of jars are copied in the "commons" lib location
    In this solution, the library is eventually placed in the common Tomcat7 directory that is shared by all webapps running on the Tomcat server. E.g., the following worked on 2016-02-29 in Tomcat7:
    scp /usr/share/tomcat7/lib/commons-dbcp.jar  radacer@172.17.12.56:~/apache-tomcat-7.0.68/lib/
    scp /usr/share/tomcat7/lib/commons-pool.jar  radacer@172.17.12.56:~/apache-tomcat-7.0.68/lib/
            
    (in the above example, Tomcat7 was installed in user space in the target machine).
    Or ...
    ... the dependency is placed in the WEB-INF/lib directory of the WAR
  10. How to keep the size of the Catalina logs under control
  11. There's two things one has to do:
    1. Schedule a Cron job to delete old files in the Catalina log directory
    2. E.g. put the following script in a file:
      #/bin/env bash
      find ~/apache-tomcat-7.0.57/logs -mtime +7 -print0 | xargs -r -0 rm -rf
              
      ... and schedule it from Cron.
      However, the above will not help you if the catalina.out file keeps growing since the above script will be unable to delete it.
      For that you have to...
    3. Rotate the catalina.out file
    4. To rotate the catalina.out file one has to change the catalina.sh file to send the output not to a single file (catalina.out) but rather to pipe it through a problem like rotatelogs.
      For instance, the below screenshot shows the differences between the:
      catalina.sh script that supports the rotation of the catalina.out file:
      .
  12. location of tomcat-users.xml file (that is used to set the admin password)
  13. In the Beorn machine the file is found in:
    /var/lib/tomcat7/conf/tomcat-users.xml
          
  14. difference between CATALINA_HOME and CATALINA_BASE
  15. sources: SO, Apache Tomcat 7 documentation
    If you're running multiple instances, then you need both variables, otherwise only CATALINA_HOME (CATALINA_HOME then assumes the same value as CATALINA_BASE).
    In other words: CATALINA_HOME is required and CATALINA_BASE is optional.
    Typical values in my system:
    CATALINA_HOME
    /usr/share/tomcat7
    CATALINA_BASE
    /var/lib/tomcat7/
  16. How to check the memory settings of a running Tomcat
  17. Use the jinfo program to attach to Tomcat (given its PID). Among other things, the Tomcat's memory model will be diplayed with the following:
    $ sudo jinfo 1752 | grep arch.data.model
    Attaching to process ID 1752, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 24.80-b11
    sun.arch.data.model = 32
          
    Also, the maximum Heap size configured (alongside other JVM options):
    $ sudo jinfo 1752  | grep -A6 VM\ Flags
    Attaching to process ID 1752, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 24.80-b11
    VM Flags:
    
    -Djava.util.logging.config.file=/var/lib/tomcat7/conf/logging.properties -Djava.awt.headless=true -Xmx128m -XX:+UseConcMarkSweepGC -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/share/tomcat7/endorsed -Dcatalina.base=/var/lib/tomcat7 -Dcatalina.home=/usr/share/tomcat7 -Djava.io.tmpdir=/tmp/tomcat7-tomcat7-tmp
          
  18. how to handle java.lang.OutOfMemoryError: PermGen space errors in Tomcat
  19. source
    From time to time, Tomcat may give java.lang.OutOfMemoryError: PermGen space errors. E.g. I've seen these errors during startup when trying to deploy a big 100Mb WAR application.
    To eliminate these memory problems the solution is to increase the values of the various JVM options that control the memory settings of the JVM which runs Tomcat. The below JVM options appear to be the most pertinent for PermGen type errors:
    -XX:PermSize<size> - Set initial PermGen Size.
    -XX:MaxPermSize<size> - Set the maximum PermGen Size.
          
    In my Ubuntu 14.04 system with Tomcat 7.0, the $CATALINA_HOME/bin/startup.sh script invokes the catalina.sh file which in turns contains the following code:
    if [ -r "$CATALINA_BASE/bin/setenv.sh" ]; then
        . "$CATALINA_BASE/bin/setenv.sh"
    elif [ -r "$CATALINA_HOME/bin/setenv.sh" ]; then
        . "$CATALINA_HOME/bin/setenv.sh"
          
    … which basically sources the setenv.sh file (if such exists).
    So, what I did was to add the following file in my $CATALINA_HOME/bin directory:
    $ pwd
    /home/voops/apache-tomcat-7.0.57/bin
    voops@esavo00:~/apache-tomcat-7.0.57/bin#
    $ cat setenv.sh 
    export JAVA_OPTS="-Dfile.encoding=UTF-8 -Xms512m -Xmx2024m -XX:PermSize=128m -XX:MaxPermSize=512m"
          
  20. how to identify that Tomcat is running, it's pid and the port it is listening to
  21. $ netstat -anp | grep 8080 | grep LISTEN
    (Not all processes could be identified, non-owned process info
     will not be shown, you would have to be root to see it all.)
    tcp        0      0 0.0.0.0:8080                0.0.0.0:*                   LISTEN      26123/java 
          
    Additional confirmation of the pid:
    $ ps -ef | grep tomcat | grep -v grep
    voops    26123     1  3 12:49 pts/0    00:00:16 /usr/local/jdk1.7.0_67/bin/java -Djava.util.logging.config.file=/home/voops/apache-tomcat-7.0.57/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/home/voops/apache-tomcat-7.0.57/endorsed -classpath /home/voops/apache-tomcat-7.0.57/bin/bootstrap.jar:/home/voops/apache-tomcat-7.0.57/bin/tomcat-juli.jar -Dcatalina.base=/home/voops/apache-tomcat-7.0.57 -Dcatalina.home=/home/voops/apache-tomcat-7.0.57 -Djava.io.tmpdir=/home/voops/apache-tomcat-7.0.57/temp org.apache.catalina.startup.Bootstrap start
          
  22. how to configure the maximum application upload size for Tomcat
  23. This might be necessary, e.g. if you need more than the default configured value of 50.
    1. Go to the web.xml of the manager application (for instance it could be under /tomcat7/webapps/manager/WEB-INF/web.xml)
    2. Increase the <max-file-size> and <max-request-size> found inside the <multipart-config> element.

    No restart is necessary.
  24. install Tomcat7 in my home directory (without sudo privileges)
  25. I followed the instructions here (which reference this file) to install Tomcat7 in my my home directory. Steps (as recollected):
    1. download binary (not sources) tarball
    2. $ mkdir -p ~/downloads && cd ~/downloads
      $ wget http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.57/bin/apache-tomcat-7.0.57.tar.gz
              
    3. expand the tarball in my home directory
    4. $ cd
      $ whoami
      voops
      $ cp downloads/apache-tomcat-7.0.57.tar.gz .
      $ tar xvfz apache-tomcat-7.0.57.tar.gz
              
    5. check whether CATALINA_HOME is properly set and correctly set it in .bashrc otherwise
    6. $ echo $CATALINA_HOME
      /home/voops/apache-tomcat-7.0.57
                
    7. compile and run the jsvc tool (?)
    8. At that point I also followed the instructions to compile and run the jsvc to run Tomcat as a daemon, but in the end I failed to use the jsvc tool as it apparently requires permissions I didn't have. Specifically, when running this script I got the following output:
      ---%<---------------------------------------------------------
      $ tail -f /home/voops/apache-tomcat-7.0.57/logs/catalina.err 
      Cannot open PID file /var/run/jsvc.pid, PID is 12504
      Service exit with a return value of 255
      Cannot open PID file /var/run/jsvc.pid, PID is 13918
      Service exit with a return value of 255
      Cannot open PID file /var/run/jsvc.pid, PID is 14260
      Service exit with a return value of 255
      Switching umask back to 002 from 077
      Cannot open PID file /var/run/jsvc.pid, PID is 31946
      Service exit with a return value of 255
      --------------------------------------------------------->%---
                
      ... so in the end I am just using scripts $CATALINA_HOME/bin/startup.sh and shutdown.sh to start and stop Tomcat (which seem to work just fine regardless) and is not clear to me what was the purpose of this script.
    9. start the Tomcat
    10. $ $CATALINA_HOME/bin/startup.sh
      Using CATALINA_BASE:   /home/voops/apache-tomcat-7.0.57
      Using CATALINA_HOME:   /home/voops/apache-tomcat-7.0.57
      Using CATALINA_TMPDIR: /home/voops/apache-tomcat-7.0.57/temp
      Using JRE_HOME:        /usr/local/jdk1.7.0_67
      Using CLASSPATH:       /home/voops/apache-tomcat-7.0.57/bin/bootstrap.jar:/home/voops/apache-tomcat-7.0.57/bin/tomcat-juli.jar
      Tomcat started.
                
    11. visit the page at 8080 to verify Tomcat is up
    12. This is the page at localhost:8080
    13. configure Tomcat admin users
    14. At that point the manager application cannot be used. To use it you have to edit file $CATALINA_HOME/conf/tomcat-users.xml so that it has the following contents:
      $ cat /home/voops/apache-tomcat-7.0.57/conf/tomcat-users.xml  | tail -6
        <!-- below 3 lines added by MP@2014.12.02 -->
        <role rolename="manager-gui"/>
        <role rolename="manager"/>
        <role rolename="admin"/>
        <user username="admin" password="admin" roles="admin,manager,manager-gui"/>
      </tomcat-users>
                
    15. final note
    16. I note in passing that the JAVA_HOME environment was also correctly set:
      $ echo $JAVA_HOME
      /usr/local/jdk1.7.0_67
                
      Whether that was really indispensable or not I did not verify.
  26. how to find exact version of Tomcat that's already installed
  27. $ whereis tomcat7
    tomcat7: /etc/tomcat7 /usr/share/tomcat7
          

    … then do a:
    $ find /usr/share/tomcat7 | grep catalina.jar
    /usr/share/tomcat7/lib/catalina.jar
          

    … and given the above, finally a:
    $ java -cp /usr/share/tomcat7/lib/catalina.jar org.apache.catalina.util.ServerInfo
    Server version: Apache Tomcat/7.0.26
    Server built:   Apr 1 2013 08:32:04
    Server number:  7.0.26.0
    OS Name:        Linux
    OS Version:     3.2.0-70-generic-pae
    Architecture:   i386
    JVM Version:    1.7.0_60-b19
    JVM Vendor:     Oracle Corporation
          
  28. Tomcat7 directories
  29.     /var/lib/tomcat7
        /usr/share/tomcat7
        /etc/tomcat7
          
  30. java.lang.OutOfMemoryError: Java heap space in Tomcat7 in Ubuntu
  31.     cd /usr/share/tomcat7/bin/
          
    There, make sure the file setenv.sh has the following content (create the file if it doesn't already exist):
    $ cat setenv.sh 
    CATALINA_OPTS="$CATALINA_OPTS -server -Xms256m -Xmx1024m
          
    The reasoning is explained in file catalina.sh.
  32. how to make Tomcat 7 in Ubuntu 12.04 use the Oracle JDK and not the open JDK
  33. I effected the following change in the file /etc/init.d/tomcat7:
        # mperdikeas change section 2013-11-09-start
        #JDK_DIRS="/usr/lib/jvm/default-java ${OPENJDKS} /usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-sun"
        JDK_DIRS="/usr/lib/jvm/java-7-oracle /usr/lib/jvm/default-java ${OPENJDKS} /usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-sun"
        # mperdikeas change section 2013-11-09-end
          

    You have, of course, to also make sure that the Oracle 7 JDK is installed in Ubuntu by following these instructions.
  34. how to install and setup Tomcat 7 in Ubuntu 12.04
    1. install Tomcat
    2. sudo apt-get install tomcat7
    3. verify installation by visiting: localhost:8080
    4. Tomcat can be stopped, started, restarted using:
      sudo /etc/init.d/tomcat7 [start|stop|restart]

      At this point the various important Tomcat directories (CATALINA_HOME and CATALINA_BASE) are specified in the above script (grep for 'CATALINA'). They do not however need to be setup in users' bash environment (see here for more).
      The Tomcat logs when deploying to $CATALINA/webapps (typically '/var/lib/tomcat7/webapps/') can be examined with:
      tail -f /var/log/tomcat7/catalina.out
      The following may be useful too:
      tail -f /var/log/tomcat7/localhost.2013-11-02.log
    5. to access the administrative front-end:
    6. sudo apt-get install tomcat7-admin
      ... and then you have to edit file 'tomcat-users.xml':
      sudo emacs -nw /var/lib/tomcat7/conf/tomcat-users.xml
      ... and add the following:
              <role rolename="manager-gui"/>
              <role rolename="admin"/>
              <user username="admin" password="admin" roles="admin,manager-gui"/>
              
      ... the admin front-end is then available at localhost:8080/manager