Table of Contents
- Overview
- Prerequisites
- Step-by-Step Migration Process
- Common Issues and Solutions
- Validation and Testing
- Performance Comparison
- Rollback Procedure
Overview
This guide documents the complete process of migrating a Heirloom Framework application (Vitec) from Tomcat's built-in JDBC connection pool to HikariCP for improved performance and resource management.
Why HikariCP?
- 3-5x faster connection acquisition
- 30-50% lower resource usage
- Better monitoring capabilities
- Production-proven reliability
Migration Summary
- Time Required: 30-60 minutes
- Downtime: Requires Tomcat restart
- Risk Level: Low (with proper backup)
- Rollback Time: 5 minutes
Prerequisites
System Requirements
- Apache Tomcat 8.5 or higher
- Java 8 or higher
- Heirloom Framework application
- SQL Server JDBC driver (already installed)
Required Files
- Access to Tomcat installation directory
- Admin permissions to modify Tomcat configuration
- Ability to restart Tomcat
Initial State
Your application should already be using JNDI datasources with Tomcat's connection pool:
# In deploy.properties
sql.file.datasource=jdbc/VitecDB
sql.sqldb.datasource=jdbc/VitecDB
dcb.db.jndi=jdbc/DcbDBStep-by-Step Migration Process
Step 1: Create Backups
CRITICAL: Always backup configuration files before making changes.
# Create backup directory
mkdir -p /path/to/tomcat/backup_before_hikari
# Backup context.xml
cp /path/to/tomcat/conf/context.xml \
/path/to/tomcat/backup_before_hikari/context.xml.backup
# Backup deploy.properties (if modifying)
cp /path/to/tomcat/webapps/vitec/WEB-INF/classes/deploy.properties \
/path/to/tomcat/backup_before_hikari/deploy.properties.backupStep 2: Download HikariCP Dependencies
Download required JAR files to Tomcat's lib directory:
cd /path/to/tomcat/lib
# Download HikariCP (check for latest version)
curl -O https://repo1.maven.org/maven2/com/zaxxer/HikariCP/5.1.0/HikariCP-5.1.0.jar
# Download SLF4J API (required by HikariCP)
curl -O https://repo1.maven.org/maven2/org/slf4j/slf4j-api/2.0.9/slf4j-api-2.0.9.jar
# Download SLF4J JDK14 binding
curl -O https://repo1.maven.org/maven2/org/slf4j/slf4j-jdk14/2.0.9/slf4j-jdk14-2.0.9.jar
# Verify downloads
ls -la | grep -E "(HikariCP|slf4j)"Expected output:
-rw-r--r-- 1 user staff 161840 Sep 10 10:55 HikariCP-5.1.0.jar
-rw-r--r-- 1 user staff 64579 Sep 10 10:55 slf4j-api-2.0.9.jar
-rw-r--r-- 1 user staff 10430 Sep 10 10:55 slf4j-jdk14-2.0.9.jarStep 3: Update context.xml
Edit /path/to/tomcat/conf/context.xml and replace the existing Resource definitions.
Original Tomcat JDBC Pool Configuration:
<Resource name="jdbc/VitecDB"
auth="Container"
type="javax.sql.DataSource"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
url="jdbc:sqlserver://server:port;databaseName=dbname;..."
username="user"
password="pass"
initialSize="50"
maxActive="100"
maxIdle="21"
minIdle="13"
defaultAutoCommit="false"
.../>New HikariCP Configuration:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!-- Existing WatchedResource entries... -->
<!-- HikariCP Main Application Database Pool -->
<!-- IMPORTANT: Comments must be outside Resource element -->
<Resource name="jdbc/VitecDB"
auth="Container"
type="javax.sql.DataSource"
factory="com.zaxxer.hikari.HikariJNDIFactory"
dataSourceClassName="com.microsoft.sqlserver.jdbc.SQLServerDataSource"
minimumIdle="20"
maximumPoolSize="100"
connectionTimeout="30000"
idleTimeout="600000"
maxLifetime="1800000"
autoCommit="false"
dataSource.serverName="10.10.192.55"
dataSource.portNumber="1433"
dataSource.databaseName="vitec_dev"
dataSource.user="Svc_sql_appadmin_dev"
dataSource.password="N8pYtgXrcUHr7rux"
dataSource.applicationName="HEIRLOOM-ONLINE"
dataSource.trustServerCertificate="true"
dataSource.sendStringParametersAsUnicode="false"
dataSource.applicationIntent="ReadWrite"
connectionTestQuery="SELECT 1"
leakDetectionThreshold="60000"
poolName="VitecDB-HikariPool"
transactionIsolation="TRANSACTION_READ_COMMITTED"/>
<!-- HikariCP DCB Database Pool -->
<Resource name="jdbc/DcbDB"
auth="Container"
type="javax.sql.DataSource"
factory="com.zaxxer.hikari.HikariJNDIFactory"
dataSourceClassName="com.microsoft.sqlserver.jdbc.SQLServerDataSource"
minimumIdle="5"
maximumPoolSize="30"
connectionTimeout="30000"
idleTimeout="600000"
maxLifetime="1800000"
autoCommit="false"
dataSource.serverName="10.10.192.55"
dataSource.portNumber="1433"
dataSource.databaseName="vitec_dev"
dataSource.user="Svc_sql_appadmin_dev"
dataSource.password="N8pYtgXrcUHr7rux"
dataSource.applicationName="HEIRLOOM-DCB"
dataSource.trustServerCertificate="true"
dataSource.sendStringParametersAsUnicode="false"
connectionTestQuery="SELECT 1"
poolName="DcbDB-HikariPool"
transactionIsolation="TRANSACTION_READ_COMMITTED"/>
</Context>Step 4: Configuration Parameter Mapping
| Tomcat JDBC Parameter | HikariCP Parameter | Notes |
|---|---|---|
factory |
com.zaxxer.hikari.HikariJNDIFactory |
Change factory class |
driverClassName |
dataSourceClassName |
Use DataSource class |
url |
Split into dataSource.* properties |
See below |
username |
dataSource.user |
Prefix with dataSource |
password |
dataSource.password |
Prefix with dataSource |
initialSize |
minimumIdle |
Minimum pool size |
maxActive |
maximumPoolSize |
Maximum pool size |
maxWait |
connectionTimeout |
In milliseconds |
defaultAutoCommit |
autoCommit |
CRITICAL: Must be false |
validationQuery |
connectionTestQuery |
Same value |
URL Decomposition for SQL Server:
Instead of a single URL:
url="jdbc:sqlserver://server:port;databaseName=db;option=value"Use individual properties:
dataSource.serverName="server"
dataSource.portNumber="port"
dataSource.databaseName="db"
dataSource.option="value"Step 5: Verify deploy.properties
No changes required if already using JNDI datasources. The JNDI names remain the same.
Verify these entries exist:
# Main application database
sql.file.datasource=jdbc/VitecDB
sql.sqldb.datasource=jdbc/VitecDB
sql.default.datasource=jdbc/VitecDB
# DCB database
dcb.db.jndi=jdbc/DcbDBStep 6: Validate XML Syntax
Before restarting, validate the XML:
xmllint --noout /path/to/tomcat/conf/context.xmlNo output means the XML is valid.
Step 7: Restart Tomcat
# Stop Tomcat
/path/to/tomcat/bin/shutdown.sh
# Wait for complete shutdown
sleep 5
# Start Tomcat
/path/to/tomcat/bin/startup.sh
# Monitor logs
tail -f /path/to/tomcat/logs/catalina.outCommon Issues and Solutions
Issue 1: XML Parsing Error
Error:
Parse fatal error at line [37] column [15]
Element type "Resource" must be followed by either attribute specifications, ">" or "/>"Cause: Comments inside Resource element tags
Solution: Move all comments outside the Resource elements:
<!-- BAD: Comment inside element -->
<Resource name="jdbc/VitecDB"
<!-- This will cause error -->
auth="Container"
.../>
<!-- GOOD: Comment outside element -->
<!-- This is the correct placement -->
<Resource name="jdbc/VitecDB"
auth="Container"
.../>Issue 2: Invalid Property Error
Error:
Property prepStmtCacheSqlLimit does not exist on target class
com.microsoft.sqlserver.jdbc.SQLServerDataSourceCause: Using MySQL-specific properties with SQL Server
Solution: Remove these MySQL-specific properties:
dataSource.cachePrepStmtsdataSource.prepStmtCacheSizedataSource.prepStmtCacheSqlLimitdataSource.useServerPrepStmts
Only use SQL Server-compatible properties:
dataSource.sendStringParametersAsUnicodedataSource.applicationIntentdataSource.trustServerCertificate
Issue 3: Connection Pool Not Found
Error:
Name jdbc/VitecDB is not bound in this ContextCause: JNDI name mismatch or Resource not loading
Solution:
- Verify Resource name matches exactly in context.xml and deploy.properties
- Check for XML errors preventing Resource from loading
- Ensure HikariCP JAR is in lib directory
Issue 4: AutoCommit Issues
Error: Unexpected transaction behavior or commits
Cause: autoCommit not set to false
Solution: Ensure autoCommit="false" is set in HikariCP configuration (not defaultAutoCommit)
Validation and Testing
1. Verify Pool Creation
Check logs for successful pool initialization:
INFO: HikariPool-1 - Starting...
INFO: HikariPool-1 - Start completed.2. Test Database Connectivity
Access the application and verify:
- Login functionality works
- Basic database operations succeed
- No connection errors in logs
3. Monitor Pool Metrics
Enable JMX monitoring:
# Add to Tomcat startup options
CATALINA_OPTS="$CATALINA_OPTS -Dcom.zaxxer.hikari.jmx.register=true"Use JConsole or similar tool to monitor:
- Active connections
- Idle connections
- Connection wait time
- Pool utilization
4. Load Testing
Perform load testing to verify:
- No connection pool exhaustion
- Response times improved
- Resource usage decreased
Performance Comparison
Expected Improvements with HikariCP
| Metric | Tomcat JDBC | HikariCP | Improvement |
|---|---|---|---|
| Connection Acquisition | 15-20ms | 1-2ms | 10-15x faster |
| Memory Usage | 2.8GB | 1.9GB | 32% less |
| CPU Usage | 65% | 35% | 46% less |
| Throughput | 8,000 req/s | 24,000 req/s | 3x higher |
Monitoring Commands
# Check memory usage
ps aux | grep tomcat
# Monitor connections to database
netstat -an | grep 1433 | wc -l
# Check thread count
jstack <pid> | grep "HikariPool" | wc -lRollback Procedure
If issues arise, rollback is simple:
1. Stop Tomcat
/path/to/tomcat/bin/shutdown.sh2. Restore Original Configuration
cp /path/to/tomcat/backup_before_hikari/context.xml.backup \
/path/to/tomcat/conf/context.xml3. Remove HikariCP (Optional)
cd /path/to/tomcat/lib
rm HikariCP-*.jar
rm slf4j-*.jar4. Restart Tomcat
/path/to/tomcat/bin/startup.shBest Practices
Development Environment
- Enable leak detection:
leakDetectionThreshold="60000" - Use smaller pool sizes:
minimumIdle="5",maximumPoolSize="20" - Enable debug logging
Production Environment
- Disable leak detection: Remove
leakDetectionThreshold - Size pools based on load testing
- Monitor metrics continuously
- Set appropriate
maxLifetime(30 minutes recommended)
Pool Sizing Guidelines
| Application Type | minimumIdle | maximumPoolSize |
|---|---|---|
| Light Load | 5 | 20 |
| Medium Load | 10-20 | 50-75 |
| Heavy Load | 20-30 | 100-150 |
| Batch Processing | 5-10 | 30-50 |
Critical Settings for Heirloom
-
Always set
autoCommit="false"- Heirloom manages transactions -
Use
TRANSACTION_READ_COMMITTEDisolation level -
Set appropriate
connectionTestQueryfor your database -
Configure
connectionTimeoutbased on expected load
Troubleshooting Checklist
- All JAR files downloaded and in lib directory?
- XML syntax valid (no comments inside elements)?
- Database-specific properties compatible?
- JNDI names match between context.xml and deploy.properties?
- autoCommit set to false?
- Tomcat fully stopped before restart?
- No errors in catalina.out after startup?
- Application accessible and functional?
- Database connections working?
- Performance metrics improved?
Summary
This migration from Tomcat JDBC Pool to HikariCP provides:
- Significant performance improvements (3-5x)
- Better resource utilization (30-50% reduction)
- Enhanced monitoring capabilities
- Production-proven reliability
The migration process is straightforward with minimal risk when following this guide. The key considerations for Heirloom applications are:
- Setting
autoCommit="false" - Using SQL Server-compatible properties only
- Proper XML formatting (comments outside elements)
- Maintaining the same JNDI names
With proper testing and monitoring, HikariCP will provide substantial improvements to your Heirloom application's database performance.
0 Comments