Follow

How to Migrate Heirloom Applications from Tomcat JDBC Pool to HikariCP

 

Table of Contents

  1. Overview
  2. Prerequisites
  3. Step-by-Step Migration Process
  4. Common Issues and Solutions
  5. Validation and Testing
  6. Performance Comparison
  7. 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/DcbDB

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

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

Step 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/DcbDB

Step 6: Validate XML Syntax

Before restarting, validate the XML:

xmllint --noout /path/to/tomcat/conf/context.xml

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

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

Cause: Using MySQL-specific properties with SQL Server

Solution: Remove these MySQL-specific properties:

  • dataSource.cachePrepStmts
  • dataSource.prepStmtCacheSize
  • dataSource.prepStmtCacheSqlLimit
  • dataSource.useServerPrepStmts

Only use SQL Server-compatible properties:

  • dataSource.sendStringParametersAsUnicode
  • dataSource.applicationIntent
  • dataSource.trustServerCertificate

Issue 3: Connection Pool Not Found

Error:

Name jdbc/VitecDB is not bound in this Context

Cause: JNDI name mismatch or Resource not loading

Solution:

  1. Verify Resource name matches exactly in context.xml and deploy.properties
  2. Check for XML errors preventing Resource from loading
  3. 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 -l

Rollback Procedure

If issues arise, rollback is simple:

1. Stop Tomcat

/path/to/tomcat/bin/shutdown.sh

2. Restore Original Configuration

cp /path/to/tomcat/backup_before_hikari/context.xml.backup \
   /path/to/tomcat/conf/context.xml

3. Remove HikariCP (Optional)

cd /path/to/tomcat/lib
rm HikariCP-*.jar
rm slf4j-*.jar

4. Restart Tomcat

/path/to/tomcat/bin/startup.sh

Best 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

  1. Always set autoCommit="false" - Heirloom manages transactions
  2. Use TRANSACTION_READ_COMMITTED isolation level
  3. Set appropriate connectionTestQuery for your database
  4. Configure connectionTimeout based 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:

  1. Setting autoCommit="false"
  2. Using SQL Server-compatible properties only
  3. Proper XML formatting (comments outside elements)
  4. Maintaining the same JNDI names

With proper testing and monitoring, HikariCP will provide substantial improvements to your Heirloom application's database performance.

References

Was this article helpful?
0 out of 0 found this helpful
Have more questions? Submit a request

0 Comments

Please sign in to leave a comment.
Powered by Zendesk