This guide details the process of updating Apache Tomcat to the latest version (9.0.87) in a Red Hat Enterprise Linux (RHEL) 9.4 (Plow) environment, covering specific challenges encountered in July 2025. The motivation for this article arose from memory failures in the survivor area of the JVM, affecting critical Java applications and causing crashes even with a small number of active users.
We chose Tomcat to host ORDS/APEX and other Java-based applications. Despite initial efforts such as upgrading from Java 8 to Java 21 and constant monitoring using jstat
, the memory leak persisted. Red Hat support recommended upgrading Tomcat to a version maintained via the AppStream repositories.
1. Prerequisites
Before starting, ensure the following:
- Operating system: RHEL 9.4 with AppStream repositories configured (use of
dnf
is recommended). - Superuser privileges (
sudo
). - JDK installed and updated, compatible with the target Tomcat version (minimum Java 8 for Tomcat 9).
2. Preparing the Environment
2.1. Backup Current Installation
Perform a full backup of your existing Tomcat installation, preserving permissions, symbolic links, and metadata:
sudo systemctl stop tomcat
sudo cp -rp --preserve=all /opt/tomcat /backup_path/tomcat -v
Note: The
--preserve=all
option ensures symbolic links, ownerships, groups, and permissions are retained.
2.2. Remove Old Versions
In order to avoid future errors or conflicts, rmove any residual Tomcat packages and service files:
sudo dnf remove 'tomcat*' -y
sudo rm -f /etc/systemd/system/tomcat.service
sudo rm -rf /opt/tomcat
Confirm the removal:
rpm -qa -v | grep -i tomcat
sudo ls -lha /opt/tomcat
sudo ls -lha /usr/share/tomcat/
3. Installing Tomcat 9 via AppStream
3.1. Update and Install
Update the system and install Tomcat and its modules:
sudo dnf update -y
sudo dnf install tomcat tomcat-webapps tomcat-admin-webapps -y
3.2. Enable the Service
Start and enable the Tomcat service:
sudo systemctl enable --now tomcat
sudo systemctl daemon-reload
3.3. Configure Firewall
Open port 8080 if necessary:
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
4. Directory Structure
The following table compares the directory paths used by Tomcat when installed via AppStream vs. a traditional installation:
Category | AppStream (RHEL) Path | Traditional Path |
---|---|---|
Configuration | /etc/tomcat |
[TOMCAT_HOME]/conf |
Applications | /var/lib/tomcat/webapps |
[TOMCAT_HOME]/webapps |
Logs | /var/log/tomcat |
[TOMCAT_HOME]/logs |
Binaries | /usr/share/tomcat |
[TOMCAT_HOME]/bin |
5. Configuration and Application Deployment
5.1. Restore Configuration
Back up the default configuration and restore from your previous installation:
sudo mv /etc/tomcat/tomcat-users.xml /etc/tomcat/tomcat-users.xml.bkp
sudo cp /backup_path/tomcat/conf/tomcat-users.xml /etc/tomcat/tomcat-users.xml
sudo cp /backup_path/tomcat/webapps/manager/META-INF/context.xml /usr/share/tomcat/webapps/manager/META-INF/context.xml
5.2. Deploy Applications
Copy .war
files and context configuration from backup:
sudo cp /backup_path/tomcat/webapps/*.war /usr/share/tomcat/webapps/
sudo cp /backup_path/tomcat/conf/Catalina/localhost/*.xml /etc/tomcat/Catalina/localhost/
sudo chown root:tomcat /usr/share/tomcat/webapps/*.war
sudo chmod 644 /usr/share/tomcat/webapps/*.war
sudo chown root:tomcat /etc/tomcat/Catalina/localhost/*.xml
sudo chmod 644 /etc/tomcat/Catalina/localhost/*.xml
5.3. Restart Tomcat
Reload the configuration and restart the service:
sudo systemctl daemon-reload
sudo systemctl restart tomcat
6. Memory Configuration (CATALINA_OPTS
)
6.1. Initial Recommendations
Red Hat offers a JVM Configuration Calculator that helps generate optimal memory and GC settings:
Also, this article provides excellent insights on JVM memory allocation:
6.2. Configure Systemd
Edit Tomcat’s override configuration:
sudo systemctl edit tomcat
Insert the following content:
[Service]
Environment="CATALINA_OPTS=\
-Xms20G -Xmx20G -server \
-XX:+UseG1GC \
-XX:+ExplicitGCInvokesConcurrent \
-XX:MaxGCPauseMillis=500 \
-Xlog:gc*:file=/var/log/tomcat/gc.log:time,uptime,level,tags:filecount=5,filesize=10M \
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/"
Or use a single-line version for compatibility:
[Service]
Environment="CATALINA_OPTS=-Xms20G -Xmx20G -server -XX:+UseG1GC -XX:+ExplicitGCInvokesConcurrent -XX:MaxGCPauseMillis=500 -Xlog:gc*:file=/var/log/tomcat/gc.log:time,uptime,level,tags:filecount=5,filesize=10M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/"
Note: If formatting issues prevent the service from starting, use the single-line version.
6.3. Set Log Permissions
sudo chown -R tomcat:tomcat /var/log/tomcat
sudo chmod 750 /var/log/tomcat
6.4. Restart and Validate
sudo systemctl restart tomcat
sudo systemctl status tomcat --no-pager
sudo systemctl show tomcat | grep CATALINA_OPTS
Why use
--no-pager
?
- Displays full output directly in the terminal.
- Easier to pipe or redirect in automation scripts.
- Prevents hangs in automated tools that rely on
systemctl
.
6.5. Garbage Collector Selection
Avoid using multiple collectors simultaneously. Choose one:
- For G1GC (recommended for modern JVMs):
-XX:+UseG1GC
- For ParallelGC:
-XX:+UseParallelGC
6.6. Configure tomcat-users.xml to enable Web Mannager
Copy your configuration (if exists) of you
backup_tomcat_path/tomcat-users.xml
to
/etc/tomcat/tomcat-users.xml
7. Issues with Missing Libraries (commons-dbcp)
7.1. Problem Context
Some applications failed to deploy due to missing commons-dbcp
. Red Hat’s minimal Tomcat packaging excludes legacy libraries like commons-dbcp 1.4
.
Check availability:
sudo dnf search dbcp
7.2. Solution: Manual Installation
Step 1: Create Temporary Directory
mkdir -p ~/downloads/missing_libs_dnf_tomcat/
cd ~/downloads/missing_libs_dnf_tomcat/
Step 2: Download the Libraries
wget https://archive.apache.org/dist/commons/dbcp/binaries/commons-dbcp-1.4-bin.zip
wget https://archive.apache.org/dist/commons/pool/binaries/commons-pool-1.6-bin.zip
Step 3: Unzip and Copy to Tomcat’s lib
unzip commons-dbcp-1.4-bin.zip
unzip commons-pool-1.6-bin.zip
sudo cp commons-dbcp-1.4/commons-dbcp-1.4.jar /usr/share/tomcat/lib/
sudo cp commons-pool-1.6/commons-pool-1.6.jar /usr/share/tomcat/lib/
Step 4: Adjust catalina.properties
(Optional)
If JNDI-related errors persist, comment out the DataSource.Factory
line:
sudo vi /etc/tomcat/tomcat.conf
Comment the following:
#javax.sql.DataSource.Factory=org.apache.commons.dbcp.BasicDataSourceFactory
Step 5: Restart Tomcat
sudo systemctl restart tomcat
Conclusion
This guide documents how we solved JVM memory issues in a RHEL 9.4 environment by upgrading Java and Tomcat 9 via AppStream. The process involved backing up the existing setup, removing old versions, performing a clean install, fine-tuning JVM settings, and resolving missing library issues. We hope this article, written in July 2025, provides helpful guidance to other professionals facing similar challenges.
By Tarcisio Freitas
Oracle APEX Architect, Senior APEX Developer, Senior Oracle DBA
portuguese version:
https://dev.to/tarcisiogf/atualizando-o-apache-tomcat-no-rhel-9-via-appstream-e-seus-desafios-4g74
Header image credit: https://www.novoshore.com/2025/01/28/ords-24-4-http-removal
Top comments (11)
good Job
Excellent!!!!
Parabéns pelo excelente artigo!
Fantastic S2
Nice Work!
Good job, keep it up!
Amazing work
Amazing!
Nice job
Great job!