From 5d316380ea306f79109a96384a3a627a0db17046 Mon Sep 17 00:00:00 2001 From: "A.Fink" Date: Mon, 15 Apr 2024 02:46:33 +0300 Subject: [PATCH] =?UTF-8?q?=C3=97=20quarkus=E2=86=92optional/explicit;=20e?= =?UTF-8?q?xplicit=20config;=20fix=20default=20db=20config;=20=E2=88=9A=20?= =?UTF-8?q?spring=20compatible?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HikariEbeanConnectionPoolFactory.java | 3 +- .../hibean/HikariEbeanDataSourcePool.java | 13 ++- .../hibean/HikariEbeanDataSourcePoolTest.java | 107 ++++++++++++++++-- src/test/resources/application-test.yaml | 17 +-- 4 files changed, 116 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/github/magicprinc/hibean/HikariEbeanConnectionPoolFactory.java b/src/main/java/com/github/magicprinc/hibean/HikariEbeanConnectionPoolFactory.java index 458cc3e..2dcfcb5 100644 --- a/src/main/java/com/github/magicprinc/hibean/HikariEbeanConnectionPoolFactory.java +++ b/src/main/java/com/github/magicprinc/hibean/HikariEbeanConnectionPoolFactory.java @@ -1,5 +1,6 @@ package com.github.magicprinc.hibean; +import io.avaje.config.Config; import io.ebean.datasource.DataSourceConfig; import io.ebean.datasource.DataSourceFactory; import io.ebean.datasource.DataSourcePool; @@ -15,6 +16,6 @@ public class HikariEbeanConnectionPoolFactory implements DataSourceFactory { @Override public DataSourcePool createPool (String name, DataSourceConfig config) { - return new HikariEbeanDataSourcePool(name, config); + return new HikariEbeanDataSourcePool(name, config, Config.asProperties()); } } \ No newline at end of file diff --git a/src/main/java/com/github/magicprinc/hibean/HikariEbeanDataSourcePool.java b/src/main/java/com/github/magicprinc/hibean/HikariEbeanDataSourcePool.java index c5aa24f..cd62c67 100644 --- a/src/main/java/com/github/magicprinc/hibean/HikariEbeanDataSourcePool.java +++ b/src/main/java/com/github/magicprinc/hibean/HikariEbeanDataSourcePool.java @@ -74,13 +74,13 @@ public class HikariEbeanDataSourcePool implements DataSourcePool { final HikariDataSource ds; - public HikariEbeanDataSourcePool (String callerPoolName, DataSourceConfig config) { + public HikariEbeanDataSourcePool (String callerPoolName, DataSourceConfig config, Properties configAsProperties) { val defaultDatabaseName = determineDefaultServerName();// usually "db" val tmpTrimPoolName = trim(callerPoolName); val hikariPoolName = tmpTrimPoolName.isEmpty() || tmpTrimPoolName.equals(defaultDatabaseName) ? "ebean" : "ebean."+ tmpTrimPoolName; - val cfg = SmartConfig.of(Config.asProperties());// System.properties overwrite file.properties + val cfg = SmartConfig.of(configAsProperties);// System.properties overwrite file.properties val databaseName = makeDatabaseNamePrefix(tmpTrimPoolName, defaultDatabaseName, cfg); Map aliasMap = alias(); val prefixes = collectPrefixes(cfg); @@ -133,7 +133,7 @@ private static String makeDatabaseNamePrefix (String trimCallerPoolName, String cfg.getProperty("ebean.hikari.defaultDb"))); if (db == null){ - return defaultDatabaseName;// default prefix for default database (usually db) + return defaultDatabaseName +'.';// default prefix for default database (usually db) } else { db = trim(db); return db.isEmpty() ? "" @@ -360,7 +360,7 @@ private static List collectPrefixes (SmartConfig cfg){ p[5] = "spring.datasource.%db%hikari."; p[7] = cfg.getProperty("ebean.hikari.prefix"); p[9] = "spring.datasource.%db%"; - p[11] = "quarkus.datasource.%db%"; + // p[11] = "quarkus.datasource.%db%"; for (int i=0; i aliasMap, SmartConfig src, Properties dst, Strin val db = dbName + (dbName.isEmpty() || dbName.endsWith(".") ? "" : ".");// "", "db.", "mycoolbase.", "toosmart." final String[] prefixes; - if ((db.isEmpty() || db.equals(defaultDatabaseName)) && !defaultDatabaseName.isEmpty()){// for default db we must generate both variants: spring.datasource.url and spring.datasource.db.url + // for default db we must generate both variants: spring.datasource.url and spring.datasource.db.url + if ((dbName.isEmpty() || dbName.equals(defaultDatabaseName) || dbName.equals(defaultDatabaseName+'.')) && !defaultDatabaseName.isEmpty()){ var set = new LinkedHashSet(prefixTemplates.size() * 8 / 3 + 1); prefixTemplates.stream() @@ -397,7 +398,7 @@ void filter (Map aliasMap, SmartConfig src, Properties dst, Strin .forEach(set::add); prefixTemplates.stream() - .map(pre->trim(pre).toLowerCase(Locale.ENGLISH).replace("%db%", defaultDatabaseName)) + .map(pre->trim(pre).toLowerCase(Locale.ENGLISH).replace("%db%", defaultDatabaseName+'.')) .filter(pre->pre.length() > 1) .forEach(set::add); diff --git a/src/test/java/com/github/magicprinc/hibean/HikariEbeanDataSourcePoolTest.java b/src/test/java/com/github/magicprinc/hibean/HikariEbeanDataSourcePoolTest.java index dbb7fe5..b940dc4 100644 --- a/src/test/java/com/github/magicprinc/hibean/HikariEbeanDataSourcePoolTest.java +++ b/src/test/java/com/github/magicprinc/hibean/HikariEbeanDataSourcePoolTest.java @@ -5,6 +5,7 @@ import io.ebean.Database; import io.ebean.datasource.DataSourceConfig; import io.ebean.datasource.DataSourceFactory; +import lombok.val; import org.junit.jupiter.api.Test; import javax.sql.DataSource; @@ -17,12 +18,17 @@ import static com.github.magicprinc.hibean.HikariEbeanDataSourcePool.isNumeric; import static com.github.magicprinc.hibean.HikariEbeanDataSourcePool.normValue; +import static com.github.magicprinc.hibean.HikariEbeanDataSourcePool.trim; import static java.util.stream.Collectors.joining; import static org.junit.jupiter.api.Assertions.*; +/** + @see HikariEbeanDataSourcePool + @see com.zaxxer.hikari.HikariConfig + */ class HikariEbeanDataSourcePoolTest { - - @Test void numeric () { + @Test + void numeric () { assertFalse(isNumeric("")); assertFalse(isNumeric(" _")); @@ -95,7 +101,7 @@ class HikariEbeanDataSourcePoolTest { @Test void testAnotherPrefix () { try { - System.setProperty("ebean.hikari.prefix", "spring.datasource."); + System.setProperty("ebean.hikari.prefix", "spring.datasource.testAnotherPrefix."); var db = DB.byName("test_spring"); var pool = (HikariEbeanDataSourcePool) db.dataSource(); @@ -106,9 +112,9 @@ class HikariEbeanDataSourcePoolTest { assertEquals(54321, pool.ds.getMaxLifetime()); System.setProperty("ebean.hikari.prefix.9", "");// disable spring - System.setProperty("ebean.hikari.prefix", "quarkus.datasource."); + System.setProperty("ebean.hikari.prefix", "quarkus.datasource.%db%"); System.setProperty("ebean.hikari.default-Db", ""); - var dataSourcePool = (HikariEbeanDataSourcePool) new HikariEbeanConnectionPoolFactory().createPool(null, new DataSourceConfig()); + var dataSourcePool = (HikariEbeanDataSourcePool) new HikariEbeanConnectionPoolFactory().createPool("myQuarkusDS", new DataSourceConfig()); assertEquals("jdbc:h2:mem:evenQuarkus", dataSourcePool.ds.getJdbcUrl()); assertEquals("org.h2.Driver", dataSourcePool.ds.getDriverClassName()); assertEquals("test", dataSourcePool.ds.getUsername()); @@ -117,21 +123,22 @@ class HikariEbeanDataSourcePoolTest { } finally { Properties p = System.getProperties(); + p.remove("ebean.hikari.prefix.9"); p.remove("ebean.hikari.prefix"); p.remove("ebean.hikari.default-Db"); } } - - @Test void _emptyPropertyIsNotAbsentProperty () { + @Test + void _emptyPropertyIsNotAbsentProperty () { System.setProperty("fake_empty_prop", ""); assertTrue(System.getProperties().containsKey("fake_empty_prop")); assertEquals("", System.getProperty("fake_empty_prop")); assertEquals("", System.getProperty("fake_empty_prop", "default")); } - - @Test void _checkDefaultDbProperties () { + @Test + void _checkDefaultDbProperties () { var ds = (HikariEbeanDataSourcePool) DB.getDefault().dataSource(); assertEquals("jdbc:h2:mem:my_app", ds.ds.getJdbcUrl());// from ebean-test platform assertEquals("org.h2.Driver", ds.ds.getDriverClassName()); @@ -145,4 +152,86 @@ class HikariEbeanDataSourcePoolTest { assertEquals(61_000, ds.ds.getIdleTimeout()); assertNull(ds.ds.getConnectionInitSql()); } + + @Test + void testSpringCompatability () { + // val prev = (Properties) System.getProperties().clone(); + var s = """ + spring.datasource.ccbbaa.type=com.zaxxer.hikari.HikariDataSource + spring.datasource.ccbbaa.url=jdbc:h2:mem:FooBazYum + spring.datasource.ccbbaa.username=myLogin + spring.datasource.ccbbaa.password=mySecret + spring.datasource.ccbbaa.hikari.maximum-pool-size=10 + spring.datasource.ccbbaa.hikari.connection-timeout=+30000 + spring.datasource.ccbbaa.hikari.data-source-properties.DB_CLOSE_ON_EXIT=true + spring.datasource.ccbbaa.hikari.data-source-properties.NETWORK_TIMEOUT=42 + """; + for (var line : s.split("\n")){ + line = line.trim(); + if (line.isEmpty()){ continue; } + var keyValue = line.split("="); + if (keyValue.length != 2){ continue; } + System.setProperty(keyValue[0].trim(), keyValue[1].trim()); + } + assertEquals("10", System.getProperty("spring.datasource.ccbbaa.hikari.maximum-pool-size")); + assertEquals("jdbc:h2:mem:FooBazYum", System.getProperty("spring.datasource.ccbbaa.url")); + + var db = DB.byName("CcBbAa"); + assertEquals("HikariEbeanDataSourcePool:HikariDataSource (ebean.CcBbAa)", db.dataSource().toString()); + assertEquals("CcBbAa", db.name()); + var ds = (HikariEbeanDataSourcePool) db.dataSource(); + assertEquals("ebean.CcBbAa", ds.name()); + assertEquals("jdbc:h2:mem:FooBazYum", ds.ds.getJdbcUrl()); + assertEquals("myLogin", ds.ds.getUsername()); + assertEquals("mySecret", ds.ds.getPassword()); + assertEquals(10, ds.ds.getMaximumPoolSize()); + assertEquals(30_000, ds.ds.getConnectionTimeout()); + assertEquals("{DB_CLOSE_ON_EXIT=true, NETWORK_TIMEOUT=42}", ds.ds.getDataSourceProperties().toString()); + assertNull(ds.ds.getDataSource()); + assertNull(ds.ds.getDataSourceClassName()); + assertNull(ds.ds.getDriverClassName()); + var sqlRow = db.sqlQuery("select 123").findOne(); + assertEquals("{123=123}", sqlRow.toString()); + assertNull(ds.ds.getDataSource()); + assertNull(ds.ds.getDataSourceClassName()); + assertNull(ds.ds.getDriverClassName()); + + + // "default" We can't replace the already created, but we can check how it could be + var fakeConfig = new Properties(); + System.getProperties().forEach((key, value)->{ + var propertyName = trim(key); + if (propertyName.startsWith("spring.datasource.ccbbaa.")){ + propertyName = propertyName.replace(".ccbbaa", ""); + fakeConfig.setProperty(propertyName, value.toString()); + } + }); + assertEquals("10", fakeConfig.getProperty("spring.datasource.hikari.maximum-pool-size")); + assertEquals("jdbc:h2:mem:FooBazYum", fakeConfig.getProperty("spring.datasource.url")); + + // DatabaseFactory.create("db" or "") + ds = new HikariEbeanDataSourcePool("db", new DataSourceConfig(), fakeConfig); + + assertEquals("HikariEbeanDataSourcePool:HikariDataSource (ebean)", ds.toString()); + assertEquals("ebean", ds.name()); + assertEquals("jdbc:h2:mem:FooBazYum", ds.ds.getJdbcUrl()); + assertEquals("myLogin", ds.ds.getUsername()); + assertEquals("mySecret", ds.ds.getPassword()); + assertEquals(10, ds.ds.getMaximumPoolSize()); + assertEquals(30_000, ds.ds.getConnectionTimeout()); + assertEquals("{DB_CLOSE_ON_EXIT=true, NETWORK_TIMEOUT=42}", ds.ds.getDataSourceProperties().toString()); + assertNull(ds.ds.getDataSource()); + assertNull(ds.ds.getDataSourceClassName()); + assertNull(ds.ds.getDriverClassName()); + + // remove settings + System.getProperties().keySet().removeIf(k->{ + val propertyName = trim(k); + return propertyName.startsWith("spring.datasource."); + }); + assertNull(System.getProperty("spring.datasource.ccbbaa.hikari.maximum-pool-size")); + assertNull(System.getProperty("spring.datasource.ccbbaa.url")); + assertNull(System.getProperty("spring.datasource.hikari.maximum-pool-size")); + assertNull(System.getProperty("spring.datasource.url")); + } } \ No newline at end of file diff --git a/src/test/resources/application-test.yaml b/src/test/resources/application-test.yaml index 850e3e3..3a9c6ab 100644 --- a/src/test/resources/application-test.yaml +++ b/src/test/resources/application-test.yaml @@ -41,16 +41,17 @@ external: spring: datasource: - url: jdbc:h2:mem:fromSprng - username: ufoo - password: pbar + testAnotherPrefix: + url: jdbc:h2:mem:fromSprng + username: ufoo + password: pbar spring.DataSource.test_spring.HiKari: max-lifetime: 54321 ReadOnly: true -quarkus.datasource.url: jdbc:h2:mem:evenQuarkus -quarkus.datasource.driver: org.h2.Driver -quarkus.datasource.username: test -quarkus.datasource.password: 1234 -quarkus.datasource.max-size: 93 \ No newline at end of file +quarkus.datasource.myQuarkusDS.url: jdbc:h2:mem:evenQuarkus +quarkus.datasource.myQuarkusDS.driver: org.h2.Driver +quarkus.datasource.myQuarkusDS.username: test +quarkus.datasource.myQuarkusDS.password: 1234 +quarkus.datasource.myQuarkusDS.max-size: 93 \ No newline at end of file