CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-zaxxer--hikari-cp

High-performance JDBC connection pool library for Java applications

Pending
Overview
Eval results
Files

utilities.mddocs/

Utilities

Supporting utility classes for credentials management, JNDI integration, and advanced connection handling.

Capabilities

Credentials Management

Immutable credentials holder for secure username/password management.

/**
 * Immutable credentials holder for database authentication
 * Thread-safe and designed for use with atomic updates
 */
public final class Credentials {
    
    /**
     * Factory method to create credentials instance
     * @param username Database username (can be null)
     * @param password Database password (can be null)
     * @return New Credentials instance
     */
    public static Credentials of(String username, String password);
    
    /**
     * Constructor for credentials
     * @param username Database username
     * @param password Database password
     */
    @ConstructorParameters({"username", "password"})
    public Credentials(String username, String password);
    
    /**
     * Get the username
     * @return Username string or null
     */
    public String getUsername();
    
    /**
     * Get the password
     * @return Password string or null  
     */
    public String getPassword();
}

Credentials Usage Examples:

import com.zaxxer.hikari.util.Credentials;
import java.util.concurrent.atomic.AtomicReference;

// Basic credential creation
Credentials creds = Credentials.of("dbuser", "dbpass");
Credentials nullCreds = Credentials.of(null, null);

// Thread-safe credential updates (used internally by HikariConfig)
AtomicReference<Credentials> credentialsRef = new AtomicReference<>(
    Credentials.of("olduser", "oldpass"));

// Atomic username update
credentialsRef.updateAndGet(current -> 
    Credentials.of("newuser", current.getPassword()));

// Atomic password update  
credentialsRef.updateAndGet(current ->
    Credentials.of(current.getUsername(), "newpass"));

// Atomic full update
credentialsRef.set(Credentials.of("admin", "secretpass"));

// Usage in configuration
HikariConfig config = new HikariConfig();
config.setCredentials(Credentials.of("appuser", "apppass"));

// Runtime credential updates (DataSource-based connections only)
HikariDataSource dataSource = new HikariDataSource(config);
dataSource.setCredentials(Credentials.of("newuser", "newpass"));

JNDI Integration

JNDI ObjectFactory for creating HikariDataSource instances in application servers.

/**
 * JNDI ObjectFactory for creating HikariDataSource instances
 * Enables deployment in Java EE application servers with JNDI configuration
 */
public class HikariJNDIFactory implements ObjectFactory {
    
    /**
     * Create HikariDataSource instance from JNDI Reference
     * @param obj Reference object (must be javax.sql.DataSource Reference)
     * @param name JNDI name being created
     * @param nameCtx Naming context
     * @param environment JNDI environment
     * @return HikariDataSource instance or null if not applicable
     * @throws Exception if creation fails
     */
    @Override
    public synchronized Object getObjectInstance(Object obj, Name name, Context nameCtx, 
                                               Hashtable<?, ?> environment) throws Exception;
}

JNDI Configuration Examples:

Tomcat context.xml:

<Context>
    <Resource name="jdbc/MyDB"
              factory="com.zaxxer.hikari.HikariJNDIFactory"
              type="javax.sql.DataSource"
              jdbcUrl="jdbc:mysql://localhost:3306/mydb"
              username="dbuser"
              password="dbpass"
              maximumPoolSize="20"
              minimumIdle="5"
              connectionTimeout="30000"
              idleTimeout="600000"
              maxLifetime="1800000"
              poolName="JNDI-Pool"
              dataSource.cachePrepStmts="true"
              dataSource.prepStmtCacheSize="250"
              dataSource.useServerPrepStmts="true" />
</Context>

WildFly/JBoss standalone.xml:

<subsystem xmlns="urn:jboss:domain:naming:2.0">
    <bindings>
        <object-factory name="java:jboss/datasources/MyDB"
                       module="com.zaxxer.hikari"
                       class="com.zaxxer.hikari.HikariJNDIFactory">
            <environment>
                <property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/mydb"/>
                <property name="username" value="dbuser"/>
                <property name="password" value="dbpass"/>
                <property name="maximumPoolSize" value="25"/>
                <property name="minimumIdle" value="5"/>
                <property name="poolName" value="WildFly-Pool"/>
                <property name="registerMbeans" value="true"/>
            </environment>
        </object-factory>
    </bindings>
</subsystem>

JNDI Lookup Usage:

import javax.naming.InitialContext;
import javax.sql.DataSource;

public class DatabaseService {
    
    private DataSource dataSource;
    
    public void init() {
        try {
            InitialContext ctx = new InitialContext();
            dataSource = (DataSource) ctx.lookup("java:comp/env/jdbc/MyDB");
            System.out.println("HikariDataSource obtained from JNDI");
        } catch (Exception e) {
            throw new RuntimeException("Failed to lookup DataSource", e);
        }
    }
    
    public Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
}

JNDI with DataSource Reference:

<!-- Alternative JNDI configuration using existing DataSource -->
<Resource name="jdbc/MyDB"
          factory="com.zaxxer.hikari.HikariJNDIFactory"
          type="javax.sql.DataSource"
          dataSourceJNDI="java:comp/env/jdbc/UnderlyingDS"
          maximumPoolSize="15"
          minimumIdle="3"
          poolName="Wrapped-Pool" />

SQL Exception Override

Interface for customizing SQLException handling and connection eviction behavior.

/**
 * Interface for custom SQLException handling in HikariCP
 * Allows overriding default connection eviction logic
 */
public interface SQLExceptionOverride {
    
    /**
     * Enumeration of eviction override decisions
     */
    enum Override {
        /** Continue with default HikariCP eviction logic */
        CONTINUE_EVICT,
        /** Do not evict the connection regardless of exception */
        DO_NOT_EVICT,
        /** Force eviction regardless of exception type */
        MUST_EVICT
    }
    
    /**
     * Adjudicate whether a connection should be evicted based on SQLException
     * @param sqlException The SQLException that was thrown
     * @return Override decision for connection eviction
     */
    default Override adjudicate(SQLException sqlException);
}

SQL Exception Override Examples:

import com.zaxxer.hikari.SQLExceptionOverride;
import java.sql.SQLException;

/**
 * Custom exception override for database-specific error handling
 */
public class CustomSQLExceptionOverride implements SQLExceptionOverride {
    
    @Override
    public Override adjudicate(SQLException sqlException) {
        String sqlState = sqlException.getSQLState();
        int errorCode = sqlException.getErrorCode();
        
        // MySQL-specific error handling
        if (sqlState != null) {
            switch (sqlState) {
                case "08S01": // Communication link failure
                case "08007": // Connection failure during transaction
                case "08006": // Connection failure
                    return Override.MUST_EVICT;
                    
                case "40001": // Serialization failure (deadlock)
                case "25006": // Read-only transaction
                    return Override.DO_NOT_EVICT; // Temporary condition
                    
                case "42000": // Syntax error - don't evict for application errors
                case "23000": // Integrity constraint violation
                    return Override.DO_NOT_EVICT;
            }
        }
        
        // MySQL error codes
        switch (errorCode) {
            case 1205: // Lock wait timeout - temporary condition
            case 1213: // Deadlock - temporary condition
                return Override.DO_NOT_EVICT;
                
            case 2006: // MySQL server has gone away
            case 2013: // Lost connection to MySQL server
                return Override.MUST_EVICT;
        }
        
        // PostgreSQL-specific handling
        if (sqlException.getMessage() != null) {
            String message = sqlException.getMessage().toLowerCase();
            if (message.contains("connection refused") || 
                message.contains("connection reset") ||
                message.contains("broken pipe")) {
                return Override.MUST_EVICT;
            }
        }
        
        // Default to HikariCP's built-in logic
        return Override.CONTINUE_EVICT;
    }
}

// Configuration usage
HikariConfig config = new HikariConfig();
config.setExceptionOverrideClassName("com.myapp.CustomSQLExceptionOverride");

// Or set instance directly
config.setExceptionOverride(new CustomSQLExceptionOverride());

Advanced Exception Override:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ProductionSQLExceptionOverride implements SQLExceptionOverride {
    
    private static final Logger logger = LoggerFactory.getLogger(ProductionSQLExceptionOverride.class);
    
    @Override
    public Override adjudicate(SQLException sqlException) {
        // Log all exceptions for monitoring
        logger.warn("SQLException in connection pool - State: {}, Code: {}, Message: {}", 
            sqlException.getSQLState(), sqlException.getErrorCode(), sqlException.getMessage());
        
        // Check for specific patterns that indicate connection issues
        if (isConnectionFailure(sqlException)) {
            logger.error("Connection failure detected, forcing eviction", sqlException);
            return Override.MUST_EVICT;
        }
        
        // Check for temporary conditions that shouldn't cause eviction
        if (isTemporaryCondition(sqlException)) {
            logger.info("Temporary condition detected, preserving connection");
            return Override.DO_NOT_EVICT;
        }
        
        // Use default HikariCP logic for other cases
        return Override.CONTINUE_EVICT;
    }
    
    private boolean isConnectionFailure(SQLException e) {
        String sqlState = e.getSQLState();
        int errorCode = e.getErrorCode();
        String message = e.getMessage();
        
        // SQLSTATE classes indicating connection problems
        if (sqlState != null && (sqlState.startsWith("08") || sqlState.startsWith("57"))) {
            return true;
        }
        
        // Common database error codes for connection issues
        if (errorCode == 2006 || errorCode == 2013 || // MySQL
            errorCode == 17002 || errorCode == 17008 || // Oracle
            errorCode == -4499 || errorCode == -30108) { // DB2
            return true;
        }
        
        // Message-based detection
        if (message != null) {
            String lowerMessage = message.toLowerCase();
            return lowerMessage.contains("connection") && 
                   (lowerMessage.contains("closed") || lowerMessage.contains("reset") || 
                    lowerMessage.contains("refused") || lowerMessage.contains("timeout"));
        }
        
        return false;
    }
    
    private boolean isTemporaryCondition(SQLException e) {
        String sqlState = e.getSQLState();
        int errorCode = e.getErrorCode();
        
        // Serialization failures, deadlocks - retry without eviction
        if ("40001".equals(sqlState) || "40P01".equals(sqlState)) {
            return true;
        }
        
        // Lock timeouts
        if (errorCode == 1205 || errorCode == 1213) { // MySQL
            return true;
        }
        
        return false;
    }
}

Utility Integration

Integrate utility classes with HikariCP configuration and monitoring.

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.util.Credentials;

public class DatabaseConnectionManager {
    
    private HikariDataSource primaryDataSource;
    private HikariDataSource readOnlyDataSource;
    
    public void initialize() {
        // Primary database with custom exception handling
        HikariConfig primaryConfig = createBaseConfig();
        primaryConfig.setJdbcUrl("jdbc:mysql://primary-db:3306/myapp");
        primaryConfig.setCredentials(Credentials.of("app_user", "app_pass"));
        primaryConfig.setExceptionOverride(new ProductionSQLExceptionOverride());
        primaryConfig.setPoolName("Primary-DB");
        primaryDataSource = new HikariDataSource(primaryConfig);
        
        // Read-only replica
        HikariConfig readOnlyConfig = createBaseConfig();
        readOnlyConfig.setJdbcUrl("jdbc:mysql://readonly-db:3306/myapp");
        readOnlyConfig.setCredentials(Credentials.of("readonly_user", "readonly_pass"));
        readOnlyConfig.setReadOnly(true);
        readOnlyConfig.setPoolName("ReadOnly-DB");
        readOnlyDataSource = new HikariDataSource(readOnlyConfig);
    }
    
    private HikariConfig createBaseConfig() {
        HikariConfig config = new HikariConfig();
        config.setMaximumPoolSize(20);
        config.setMinimumIdle(5);
        config.setConnectionTimeout(30000);
        config.setIdleTimeout(600000);
        config.setMaxLifetime(1800000);
        config.setLeakDetectionThreshold(60000);
        config.setRegisterMbeans(true);
        
        // MySQL optimizations
        config.addDataSourceProperty("cachePrepStmts", "true");
        config.addDataSourceProperty("prepStmtCacheSize", "250");
        config.addDataSourceProperty("useServerPrepStmts", "true");
        
        return config;
    }
    
    public Connection getPrimaryConnection() throws SQLException {
        return primaryDataSource.getConnection();
    }
    
    public Connection getReadOnlyConnection() throws SQLException {
        return readOnlyDataSource.getConnection();
    }
    
    public void updateCredentials(String username, String password) {
        Credentials newCreds = Credentials.of(username, password);
        primaryDataSource.setCredentials(newCreds);
        // Note: credential updates only work with DataSource-based connections
    }
    
    public void shutdown() {
        if (primaryDataSource != null) {
            primaryDataSource.close();
        }
        if (readOnlyDataSource != null) {
            readOnlyDataSource.close();
        }
    }
}

Advanced Utility Patterns

Advanced patterns using HikariCP utilities for enterprise scenarios.

import javax.naming.InitialContext;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

/**
 * Multi-tenant database connection manager using HikariCP utilities
 */
public class MultiTenantConnectionManager {
    
    private final Map<String, HikariDataSource> tenantDataSources = new ConcurrentHashMap<>();
    private final SQLExceptionOverride commonExceptionOverride = new ProductionSQLExceptionOverride();
    
    /**
     * Get or create DataSource for specific tenant
     */
    public DataSource getDataSource(String tenantId) {
        return tenantDataSources.computeIfAbsent(tenantId, this::createTenantDataSource);
    }
    
    private HikariDataSource createTenantDataSource(String tenantId) {
        try {
            // Try JNDI lookup first
            InitialContext ctx = new InitialContext();
            String jndiName = "java:comp/env/jdbc/" + tenantId;
            
            try {
                return (HikariDataSource) ctx.lookup(jndiName);
            } catch (Exception e) {
                // JNDI lookup failed, create programmatically
                return createProgrammaticDataSource(tenantId);
            }
            
        } catch (Exception e) {
            throw new RuntimeException("Failed to create DataSource for tenant: " + tenantId, e);
        }
    }
    
    private HikariDataSource createProgrammaticDataSource(String tenantId) {
        HikariConfig config = new HikariConfig();
        
        // Tenant-specific configuration
        TenantConfig tenantConfig = getTenantConfig(tenantId);
        config.setJdbcUrl(tenantConfig.getJdbcUrl());
        config.setCredentials(Credentials.of(tenantConfig.getUsername(), tenantConfig.getPassword()));
        
        // Common pool settings
        config.setMaximumPoolSize(tenantConfig.getMaxPoolSize());
        config.setMinimumIdle(tenantConfig.getMinIdle());
        config.setConnectionTimeout(30000);
        config.setIdleTimeout(600000);
        config.setMaxLifetime(1800000);
        config.setPoolName("Tenant-" + tenantId);
        config.setRegisterMbeans(true);
        
        // Common exception handling
        config.setExceptionOverride(commonExceptionOverride);
        
        return new HikariDataSource(config);
    }
    
    /**
     * Update credentials for all tenants (rolling update)
     */
    public void updateCredentials(Map<String, Credentials> tenantCredentials) {
        tenantCredentials.forEach((tenantId, credentials) -> {
            HikariDataSource ds = tenantDataSources.get(tenantId);
            if (ds != null) {
                ds.setCredentials(credentials);
                System.out.printf("Updated credentials for tenant: %s%n", tenantId);
            }
        });
    }
    
    /**
     * Shutdown all tenant connections
     */
    public void shutdown() {
        tenantDataSources.values().forEach(HikariDataSource::close);
        tenantDataSources.clear();
    }
    
    private TenantConfig getTenantConfig(String tenantId) {
        // Load tenant-specific configuration from external source
        // This is implementation-specific
        return new TenantConfig(tenantId);
    }
    
    private static class TenantConfig {
        private final String tenantId;
        
        public TenantConfig(String tenantId) {
            this.tenantId = tenantId;
        }
        
        public String getJdbcUrl() {
            return "jdbc:mysql://db-" + tenantId + ":3306/" + tenantId;
        }
        
        public String getUsername() {
            return tenantId + "_user";
        }
        
        public String getPassword() {
            return loadPasswordFromVault(tenantId);
        }
        
        public int getMaxPoolSize() {
            return "premium".equals(getTenantTier()) ? 20 : 10;
        }
        
        public int getMinIdle() {
            return "premium".equals(getTenantTier()) ? 5 : 2;
        }
        
        // Implementation-specific methods
        private String loadPasswordFromVault(String tenantId) { return "password"; }
        private String getTenantTier() { return "standard"; }
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-com-zaxxer--hikari-cp

docs

configuration.md

connection-pooling.md

hibernate-integration.md

index.md

jmx-management.md

metrics-integration.md

utilities.md

tile.json