diff --git a/src/main/java/com/zaxxer/hikari/HikariDataSource.java b/src/main/java/com/zaxxer/hikari/HikariDataSource.java index a172dbfe..a4f1dd51 100644 --- a/src/main/java/com/zaxxer/hikari/HikariDataSource.java +++ b/src/main/java/com/zaxxer/hikari/HikariDataSource.java @@ -16,6 +16,13 @@ package com.zaxxer.hikari; +import com.zaxxer.hikari.metrics.MetricsTrackerFactory; +import com.zaxxer.hikari.pool.HikariPool; +import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.sql.DataSource; import java.io.Closeable; import java.io.PrintWriter; import java.sql.Connection; @@ -23,15 +30,6 @@ import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.concurrent.atomic.AtomicBoolean; -import javax.sql.DataSource; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.zaxxer.hikari.metrics.MetricsTrackerFactory; -import com.zaxxer.hikari.pool.HikariPool; -import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException; - /** * The HikariCP pooled DataSource. * @@ -75,11 +73,12 @@ public class HikariDataSource extends HikariConfig implements DataSource, Closea public HikariDataSource(HikariConfig configuration) { configuration.validate(); - configuration.copyStateTo(this); + final HikariConfig copy = new HikariConfig(); + configuration.copyStateTo(copy); this.seal(); LOGGER.info("{} - Starting...", configuration.getPoolName()); - pool = fastPathPool = new HikariPool(this); + pool = fastPathPool = new HikariPool(copy); LOGGER.info("{} - Start completed.", configuration.getPoolName()); } @@ -104,8 +103,11 @@ public class HikariDataSource extends HikariConfig implements DataSource, Closea validate(); LOGGER.info("{} - Starting...", getPoolName()); try { - pool = result = new HikariPool(this); + final HikariConfig copy = new HikariConfig(); + this.copyStateTo(copy); this.seal(); + + pool = result = new HikariPool(copy); } catch (PoolInitializationException pie) { if (pie.getCause() instanceof SQLException) { @@ -293,7 +295,7 @@ public class HikariDataSource extends HikariConfig implements DataSource, Closea */ public HikariConfigMXBean getHikariConfigMXBean() { - return this; + return (fastPathPool != null) ? fastPathPool.config : pool.config; } /** diff --git a/src/main/java/com/zaxxer/hikari/pool/PoolBase.java b/src/main/java/com/zaxxer/hikari/pool/PoolBase.java index 655322e7..19ba0aa4 100644 --- a/src/main/java/com/zaxxer/hikari/pool/PoolBase.java +++ b/src/main/java/com/zaxxer/hikari/pool/PoolBase.java @@ -16,10 +16,21 @@ package com.zaxxer.hikari.pool; -import static com.zaxxer.hikari.pool.ProxyConnection.DIRTY_BIT_SCHEMA; -import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.metrics.IMetricsTracker; +import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException; +import com.zaxxer.hikari.util.DriverDataSource; +import com.zaxxer.hikari.util.PropertyElf; +import com.zaxxer.hikari.util.UtilityElf; +import com.zaxxer.hikari.util.UtilityElf.DefaultThreadFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.sql.DataSource; import java.lang.management.ManagementFactory; import java.sql.Connection; import java.sql.SQLException; @@ -32,38 +43,17 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.atomic.AtomicReference; -import javax.management.MBeanServer; -import javax.management.ObjectName; -import javax.naming.InitialContext; -import javax.naming.NamingException; -import javax.sql.DataSource; - -import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.metrics.IMetricsTracker; -import com.zaxxer.hikari.util.DriverDataSource; -import com.zaxxer.hikari.util.PropertyElf; -import com.zaxxer.hikari.util.UtilityElf; -import com.zaxxer.hikari.util.UtilityElf.DefaultThreadFactory; - -import static com.zaxxer.hikari.pool.ProxyConnection.DIRTY_BIT_AUTOCOMMIT; -import static com.zaxxer.hikari.pool.ProxyConnection.DIRTY_BIT_CATALOG; -import static com.zaxxer.hikari.pool.ProxyConnection.DIRTY_BIT_ISOLATION; -import static com.zaxxer.hikari.pool.ProxyConnection.DIRTY_BIT_NETTIMEOUT; -import static com.zaxxer.hikari.pool.ProxyConnection.DIRTY_BIT_READONLY; -import static com.zaxxer.hikari.util.ClockSource.currentTime; -import static com.zaxxer.hikari.util.ClockSource.elapsedMillis; -import static com.zaxxer.hikari.util.ClockSource.elapsedNanos; +import static com.zaxxer.hikari.pool.ProxyConnection.*; +import static com.zaxxer.hikari.util.ClockSource.*; import static com.zaxxer.hikari.util.UtilityElf.createInstance; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; abstract class PoolBase { private final Logger LOGGER = LoggerFactory.getLogger(PoolBase.class); - protected final HikariConfig config; + public final HikariConfig config; protected final String poolName; long connectionTimeout; long validationTimeout; diff --git a/src/test/java/com/zaxxer/hikari/db/BasicPoolTest.java b/src/test/java/com/zaxxer/hikari/db/BasicPoolTest.java index 89bf2a16..eeb927d0 100644 --- a/src/test/java/com/zaxxer/hikari/db/BasicPoolTest.java +++ b/src/test/java/com/zaxxer/hikari/db/BasicPoolTest.java @@ -29,7 +29,7 @@ import java.sql.Statement; import static com.zaxxer.hikari.pool.TestElf.getPool; import static com.zaxxer.hikari.pool.TestElf.newHikariConfig; -import static com.zaxxer.hikari.pool.TestElf.unsealDataSource; +import static com.zaxxer.hikari.pool.TestElf.getUnsealedConfig; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import static org.junit.Assert.assertEquals; @@ -76,14 +76,14 @@ public class BasicPoolTest System.setProperty("com.zaxxer.hikari.housekeeping.periodMs", "1000"); - try (HikariDataSource ds = unsealDataSource(new HikariDataSource(config))) { + try (HikariDataSource ds = new HikariDataSource(config)) { System.clearProperty("com.zaxxer.hikari.housekeeping.periodMs"); SECONDS.sleep(1); HikariPool pool = getPool(ds); - ds.setIdleTimeout(3000); + getUnsealedConfig(ds).setIdleTimeout(3000); assertEquals("Total connections not as expected", 5, pool.getTotalConnections()); assertEquals("Idle connections not as expected", 5, pool.getIdleConnections()); @@ -117,14 +117,14 @@ public class BasicPoolTest System.setProperty("com.zaxxer.hikari.housekeeping.periodMs", "1000"); - try (HikariDataSource ds = unsealDataSource(new HikariDataSource(config))) { + try (HikariDataSource ds = new HikariDataSource(config)) { System.clearProperty("com.zaxxer.hikari.housekeeping.periodMs"); SECONDS.sleep(1); HikariPool pool = getPool(ds); - ds.setIdleTimeout(3000); + getUnsealedConfig(ds).setIdleTimeout(3000); assertEquals("Total connections not as expected", 50, pool.getTotalConnections()); assertEquals("Idle connections not as expected", 50, pool.getIdleConnections()); diff --git a/src/test/java/com/zaxxer/hikari/pool/TestConnections.java b/src/test/java/com/zaxxer/hikari/pool/TestConnections.java index 5e057df3..e8a486b0 100644 --- a/src/test/java/com/zaxxer/hikari/pool/TestConnections.java +++ b/src/test/java/com/zaxxer/hikari/pool/TestConnections.java @@ -16,45 +16,25 @@ package com.zaxxer.hikari.pool; -import static com.zaxxer.hikari.pool.TestElf.newHikariConfig; -import static com.zaxxer.hikari.pool.TestElf.newHikariDataSource; -import static com.zaxxer.hikari.pool.TestElf.getPool; -import static com.zaxxer.hikari.pool.TestElf.setConfigUnitTest; -import static com.zaxxer.hikari.pool.TestElf.setSlf4jLogLevel; -import static com.zaxxer.hikari.pool.TestElf.setSlf4jTargetStream; -import static com.zaxxer.hikari.pool.TestElf.unsealDataSource; -import static com.zaxxer.hikari.util.UtilityElf.quietlySleep; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.SQLTransientConnectionException; -import java.sql.SQLTransientException; -import java.sql.Statement; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import org.apache.logging.log4j.Level; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.mocks.StubConnection; import com.zaxxer.hikari.mocks.StubDataSource; import com.zaxxer.hikari.mocks.StubStatement; import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException; +import org.apache.logging.log4j.Level; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.sql.*; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import static com.zaxxer.hikari.pool.TestElf.*; +import static com.zaxxer.hikari.util.UtilityElf.quietlySleep; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.Assert.*; /** * @author Brett Wooldridge @@ -136,10 +116,10 @@ public class TestConnections System.setProperty("com.zaxxer.hikari.housekeeping.periodMs", "100"); setConfigUnitTest(true); - try (HikariDataSource ds = unsealDataSource(new HikariDataSource(config))) { + try (HikariDataSource ds = new HikariDataSource(config)) { System.clearProperty("com.zaxxer.hikari.housekeeping.periodMs"); - ds.setMaxLifetime(700); + getUnsealedConfig(ds).setMaxLifetime(700); HikariPool pool = getPool(ds); @@ -193,8 +173,8 @@ public class TestConnections System.setProperty("com.zaxxer.hikari.housekeeping.periodMs", "100"); setConfigUnitTest(true); - try (HikariDataSource ds = unsealDataSource(new HikariDataSource(config))) { - ds.setMaxLifetime(700); + try (HikariDataSource ds = new HikariDataSource(config)) { + getUnsealedConfig(ds).setMaxLifetime(700); HikariPool pool = getPool(ds); assertSame("Total connections not as expected", 0, pool.getTotalConnections()); @@ -615,10 +595,10 @@ public class TestConnections System.setProperty("com.zaxxer.hikari.housekeeping.periodMs", "1000"); StubConnection.slowCreate = true; - try (HikariDataSource ds = unsealDataSource(new HikariDataSource(config))) { + try (HikariDataSource ds = new HikariDataSource(config)) { System.clearProperty("com.zaxxer.hikari.housekeeping.periodMs"); - ds.setIdleTimeout(3000); + getUnsealedConfig(ds).setIdleTimeout(3000); SECONDS.sleep(2); diff --git a/src/test/java/com/zaxxer/hikari/pool/TestElf.java b/src/test/java/com/zaxxer/hikari/pool/TestElf.java index fa5438a7..836826ab 100644 --- a/src/test/java/com/zaxxer/hikari/pool/TestElf.java +++ b/src/test/java/com/zaxxer/hikari/pool/TestElf.java @@ -16,13 +16,9 @@ package com.zaxxer.hikari.pool; -import java.io.DataInputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.lang.reflect.Field; -import java.net.URL; -import java.sql.Connection; - +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import com.zaxxer.hikari.util.ConcurrentBag; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.LogEvent; @@ -32,9 +28,12 @@ import org.apache.logging.log4j.core.layout.CsvLogEventLayout; import org.apache.logging.slf4j.Log4jLogger; import org.slf4j.LoggerFactory; -import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.HikariDataSource; -import com.zaxxer.hikari.util.ConcurrentBag; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.lang.reflect.Field; +import java.net.URL; +import java.sql.Connection; /** * Utility methods for testing. @@ -75,13 +74,18 @@ public final class TestElf } } - public static HikariDataSource unsealDataSource(final HikariDataSource ds) + public static HikariConfig getUnsealedConfig(final HikariDataSource ds) { try { + HikariPool pool = getPool(ds); + Field configField = PoolBase.class.getDeclaredField("config"); + configField.setAccessible(true); + HikariConfig config = (HikariConfig) configField.get(pool); + Field field = HikariConfig.class.getDeclaredField("sealed"); field.setAccessible(true); - field.setBoolean(ds, false); - return ds; + field.setBoolean(config, false); + return config; } catch (Exception e) { throw new RuntimeException(e); diff --git a/src/test/java/com/zaxxer/hikari/pool/TestJNDI.java b/src/test/java/com/zaxxer/hikari/pool/TestJNDI.java index da919032..4f2dd0ef 100644 --- a/src/test/java/com/zaxxer/hikari/pool/TestJNDI.java +++ b/src/test/java/com/zaxxer/hikari/pool/TestJNDI.java @@ -22,18 +22,12 @@ import com.zaxxer.hikari.mocks.StubDataSource; import org.junit.Test; import org.osjava.sj.jndi.AbstractContext; -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.Name; -import javax.naming.RefAddr; -import javax.naming.Reference; +import javax.naming.*; import java.sql.Connection; +import static com.zaxxer.hikari.pool.TestElf.getUnsealedConfig; import static com.zaxxer.hikari.pool.TestElf.newHikariConfig; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import static org.junit.Assert.*; public class TestJNDI { @@ -54,7 +48,7 @@ public class TestJNDI try (HikariDataSource ds = (HikariDataSource) jndi.getObjectInstance(ref, null, nameCtx, null)) { assertNotNull(ds); - assertEquals("foo", ds.getUsername()); + assertEquals("foo", getUnsealedConfig(ds).getUsername()); } } @@ -76,7 +70,7 @@ public class TestJNDI try (HikariDataSource ds = (HikariDataSource) jndi.getObjectInstance(ref, null, nameCtx, null)) { assertNotNull(ds); - assertEquals("foo", ds.getUsername()); + assertEquals("foo", getUnsealedConfig(ds).getUsername()); } } diff --git a/src/test/java/com/zaxxer/hikari/pool/TestMBean.java b/src/test/java/com/zaxxer/hikari/pool/TestMBean.java index 51635f33..6e6a5e62 100644 --- a/src/test/java/com/zaxxer/hikari/pool/TestMBean.java +++ b/src/test/java/com/zaxxer/hikari/pool/TestMBean.java @@ -16,6 +16,7 @@ package com.zaxxer.hikari.pool; import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariConfigMXBean; import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariPoolMXBean; import org.junit.Test; @@ -29,8 +30,8 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.concurrent.TimeUnit; +import static com.zaxxer.hikari.pool.TestElf.getUnsealedConfig; import static com.zaxxer.hikari.pool.TestElf.newHikariConfig; -import static com.zaxxer.hikari.pool.TestElf.unsealDataSource; import static org.junit.Assert.assertEquals; public class TestMBean @@ -60,9 +61,9 @@ public class TestMBean System.setProperty("com.zaxxer.hikari.housekeeping.periodMs", "100"); - try (HikariDataSource ds = unsealDataSource(new HikariDataSource(config))) { + try (HikariDataSource ds = new HikariDataSource(config)) { - ds.setIdleTimeout(3000); + getUnsealedConfig(ds).setIdleTimeout(3000); TimeUnit.SECONDS.sleep(1); @@ -93,4 +94,22 @@ public class TestMBean System.clearProperty("com.zaxxer.hikari.housekeeping.periodMs"); } } + + @Test(expected = IllegalStateException.class) + public void testMBeanChange() { + HikariConfig config = newHikariConfig(); + config.setMinimumIdle(3); + config.setMaximumPoolSize(5); + config.setRegisterMbeans(true); + config.setConnectionTimeout(2800); + config.setConnectionTestQuery("VALUES 1"); + config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + + try (HikariDataSource ds = new HikariDataSource(config)) { + HikariConfigMXBean hikariConfigMXBean = ds.getHikariConfigMXBean(); + hikariConfigMXBean.setIdleTimeout(3000); + + ds.setIdleTimeout(1000); + } + } }