Skip to content

Commit cf23f6b

Browse files
authored
refactor: switch pool config to the new format (#5667)
1 parent 1b79293 commit cf23f6b

2 files changed

Lines changed: 121 additions & 69 deletions

File tree

extensions/common/sql/sql-pool/sql-pool-apache-commons/src/main/java/org/eclipse/edc/sql/pool/commons/CommonsConnectionPoolServiceExtension.java

Lines changed: 96 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@
1414

1515
package org.eclipse.edc.sql.pool.commons;
1616

17+
import org.eclipse.edc.runtime.metamodel.annotation.Configuration;
1718
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
1819
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
1920
import org.eclipse.edc.runtime.metamodel.annotation.Setting;
21+
import org.eclipse.edc.runtime.metamodel.annotation.SettingContext;
22+
import org.eclipse.edc.runtime.metamodel.annotation.Settings;
2023
import org.eclipse.edc.spi.EdcException;
2124
import org.eclipse.edc.spi.monitor.Monitor;
2225
import org.eclipse.edc.spi.security.Vault;
@@ -30,10 +33,11 @@
3033

3134
import java.util.LinkedList;
3235
import java.util.List;
36+
import java.util.Map;
3337
import java.util.Optional;
3438
import java.util.Properties;
35-
import java.util.function.BiFunction;
3639
import java.util.function.Consumer;
40+
import java.util.function.Supplier;
3741
import javax.sql.DataSource;
3842

3943
import static java.util.Optional.ofNullable;
@@ -44,41 +48,28 @@ public class CommonsConnectionPoolServiceExtension implements ServiceExtension {
4448
public static final String NAME = "Commons Connection Pool";
4549

4650
public static final String EDC_DATASOURCE_PREFIX = "edc.datasource";
47-
private static final String EDC_DATASOURCE_CONFIG_CONTEXT = EDC_DATASOURCE_PREFIX + ".<name>";
48-
49-
@Setting(description = "JDBC url", required = true, context = EDC_DATASOURCE_CONFIG_CONTEXT)
5051
public static final String URL = "url";
51-
@Setting(description = "Username to be used for the JDBC connection. Can be omitted if not required, or if the user is encoded in the JDBC url.", context = EDC_DATASOURCE_CONFIG_CONTEXT)
5252
public static final String USER = "user";
53-
@Setting(description = "Username to be used for the JDBC connection. Can be omitted if not required, or if the password is encoded in the JDBC url.", context = EDC_DATASOURCE_CONFIG_CONTEXT)
5453
public static final String PASSWORD = "password";
55-
56-
@Setting(description = "Pool max idle connections", context = EDC_DATASOURCE_CONFIG_CONTEXT)
5754
public static final String POOL_CONNECTIONS_MAX_IDLE = "pool.connections.max-idle";
58-
@Setting(description = "Pool max total connections", context = EDC_DATASOURCE_CONFIG_CONTEXT)
5955
public static final String POOL_CONNECTIONS_MAX_TOTAL = "pool.connections.max-total";
60-
@Setting(description = "Pool min idle connections", context = EDC_DATASOURCE_CONFIG_CONTEXT)
6156
public static final String POOL_CONNECTIONS_MIN_IDLE = "pool.connections.min-idle";
62-
@Setting(description = "Pool test on borrow", context = EDC_DATASOURCE_CONFIG_CONTEXT)
6357
public static final String POOL_CONNECTION_TEST_ON_BORROW = "pool.connection.test.on-borrow";
64-
@Setting(description = "Pool test on create", context = EDC_DATASOURCE_CONFIG_CONTEXT)
6558
public static final String POOL_CONNECTION_TEST_ON_CREATE = "pool.connection.test.on-create";
66-
@Setting(description = "Pool test on return", context = EDC_DATASOURCE_CONFIG_CONTEXT)
6759
public static final String POOL_CONNECTION_TEST_ON_RETURN = "pool.connection.test.on-return";
68-
@Setting(description = "Pool test while idle", context = EDC_DATASOURCE_CONFIG_CONTEXT)
6960
public static final String POOL_CONNECTION_TEST_WHILE_IDLE = "pool.connection.test.while-idle";
70-
@Setting(description = "Pool test query", context = EDC_DATASOURCE_CONFIG_CONTEXT)
7161
public static final String POOL_CONNECTION_TEST_QUERY = "pool.connection.test.query";
7262

63+
@SettingContext(EDC_DATASOURCE_PREFIX)
64+
@Configuration
65+
private Map<String, DatasourceConfiguration> datasources;
66+
7367
@Inject
7468
private DataSourceRegistry dataSourceRegistry;
75-
7669
@Inject
7770
private Monitor monitor;
78-
7971
@Inject
8072
private ConnectionFactory connectionFactory;
81-
8273
@Inject
8374
private Vault vault;
8475

@@ -91,13 +82,13 @@ public String name() {
9182

9283
@Override
9384
public void initialize(ServiceExtensionContext context) {
94-
context.getConfig(EDC_DATASOURCE_PREFIX).partition().forEach(config -> {
95-
var dataSourceName = config.currentNode();
96-
var dataSource = createDataSource(config);
97-
var connectionPool = createConnectionPool(dataSource, config);
85+
datasources.forEach((name, configuration) -> {
86+
var rootPath = EDC_DATASOURCE_PREFIX + "." + name;
87+
var dataSource = createDataSource(rootPath, configuration, context.getConfig(rootPath));
88+
var connectionPool = createConnectionPool(dataSource, configuration);
9889
commonsConnectionPools.add(connectionPool);
9990
var connectionPoolDataSource = new ConnectionPoolDataSource(connectionPool);
100-
dataSourceRegistry.register(dataSourceName, connectionPoolDataSource);
91+
dataSourceRegistry.register(name, connectionPoolDataSource);
10192
});
10293
}
10394

@@ -106,51 +97,111 @@ public void cleanup() {
10697
commonsConnectionPools.forEach(CommonsConnectionPool::close);
10798
}
10899

109-
private DataSource createDataSource(Config config) {
110-
var rootPath = EDC_DATASOURCE_PREFIX + "." + config.currentNode();
111-
112-
var jdbcUrl = getSecretOrSetting(rootPath, URL, config)
113-
.orElseThrow(() -> new EdcException("Mandatory url for datasource '%s' not found. Please provide a value for it, either as a secret in the vault or an application property.".formatted(config.currentNode())));
114-
var jdbcUser = getSecretOrSetting(rootPath, USER, config);
115-
var jdbcPassword = getSecretOrSetting(rootPath, PASSWORD, config);
100+
private DataSource createDataSource(String rootPath, DatasourceConfiguration configuration, Config currentNode) {
101+
var jdbcUrl = getSecretOrSetting(rootPath, URL, configuration.url())
102+
.orElseThrow(() -> new EdcException("Mandatory url for datasource '%s' not found. Please provide a value for it, either as a secret in the vault or an application property.".formatted(currentNode.currentNode())));
103+
var jdbcUser = getSecretOrSetting(rootPath, USER, configuration.user());
104+
var jdbcPassword = getSecretOrSetting(rootPath, PASSWORD, configuration.password());
116105

117106
var properties = new Properties();
118-
properties.putAll(config.getRelativeEntries());
107+
properties.putAll(currentNode.getRelativeEntries());
119108

120109
jdbcUser.ifPresent(u -> properties.put(USER, u));
121110
jdbcPassword.ifPresent(p -> properties.put(PASSWORD, p));
122111

123112
return new ConnectionFactoryDataSource(connectionFactory, jdbcUrl, properties);
124113
}
125114

126-
private Optional<String> getSecretOrSetting(String rootPath, String key, Config config) {
115+
private Optional<String> getSecretOrSetting(String rootPath, String key, String configValue) {
127116
var fullKey = rootPath + "." + key;
128117
return ofNullable(vault.resolveSecret(fullKey))
129118
.or(() -> {
130119
monitor.warning("Datasource configuration value '%s' not found in vault, will fall back to Config. Please consider putting datasource configuration into the vault.".formatted(fullKey));
131-
return Optional.ofNullable(config.getString(key, null));
120+
return Optional.ofNullable(configValue);
132121
});
133122
}
134123

135-
private CommonsConnectionPool createConnectionPool(DataSource unPooledDataSource, Config config) {
124+
private CommonsConnectionPool createConnectionPool(DataSource dataSource, DatasourceConfiguration configuration) {
136125
var builder = CommonsConnectionPoolConfig.Builder.newInstance();
137126

138-
setIfProvided(POOL_CONNECTIONS_MAX_IDLE, config::getInteger, builder::maxIdleConnections);
139-
setIfProvided(POOL_CONNECTIONS_MAX_TOTAL, config::getInteger, builder::maxTotalConnections);
140-
setIfProvided(POOL_CONNECTIONS_MIN_IDLE, config::getInteger, builder::minIdleConnections);
141-
setIfProvided(POOL_CONNECTION_TEST_ON_BORROW, config::getBoolean, builder::testConnectionOnBorrow);
142-
setIfProvided(POOL_CONNECTION_TEST_ON_CREATE, config::getBoolean, builder::testConnectionOnCreate);
143-
setIfProvided(POOL_CONNECTION_TEST_ON_RETURN, config::getBoolean, builder::testConnectionOnReturn);
144-
setIfProvided(POOL_CONNECTION_TEST_WHILE_IDLE, config::getBoolean, builder::testConnectionWhileIdle);
145-
setIfProvided(POOL_CONNECTION_TEST_QUERY, config::getString, builder::testQuery);
127+
setIfProvided(configuration::poolConnectionsMaxIdle, builder::maxIdleConnections);
128+
setIfProvided(configuration::poolConnectionsMaxTotal, builder::maxTotalConnections);
129+
setIfProvided(configuration::poolConnectionsMinIdle, builder::minIdleConnections);
130+
setIfProvided(configuration::poolConnectionTestOnBorrow, builder::testConnectionOnBorrow);
131+
setIfProvided(configuration::poolConnectionTestOnCreate, builder::testConnectionOnCreate);
132+
setIfProvided(configuration::poolConnectionTestOnReturn, builder::testConnectionOnReturn);
133+
setIfProvided(configuration::poolConnectionTestWhileIdle, builder::testConnectionWhileIdle);
134+
setIfProvided(configuration::poolConnectionTestQuery, builder::testQuery);
146135

147-
return new CommonsConnectionPool(unPooledDataSource, builder.build(), monitor);
136+
return new CommonsConnectionPool(dataSource, builder.build(), monitor);
148137
}
149138

150-
private <T> void setIfProvided(String key, BiFunction<String, T, T> getter, Consumer<T> setter) {
151-
var value = getter.apply(key, null);
139+
private <T> void setIfProvided(Supplier<T> supplier, Consumer<T> setter) {
140+
var value = supplier.get();
152141
if (value != null) {
153142
setter.accept(value);
154143
}
155144
}
145+
146+
@Settings
147+
private record DatasourceConfiguration(
148+
@Setting(
149+
key = URL,
150+
description = "JDBC url",
151+
required = false)
152+
String url,
153+
@Setting(
154+
key = USER,
155+
description = "Username to be used for the JDBC connection. Can be omitted if not required, or if the user is encoded in the JDBC url.",
156+
required = false)
157+
String user,
158+
@Setting(
159+
key = PASSWORD,
160+
description = "Username to be used for the JDBC connection. Can be omitted if not required, or if the password is encoded in the JDBC url.",
161+
required = false)
162+
String password,
163+
164+
@Setting(
165+
key = POOL_CONNECTIONS_MAX_IDLE,
166+
description = "Pool max idle connections",
167+
required = false)
168+
Integer poolConnectionsMaxIdle,
169+
@Setting(
170+
key = POOL_CONNECTIONS_MAX_TOTAL,
171+
description = "Pool max total connections",
172+
required = false)
173+
Integer poolConnectionsMaxTotal,
174+
@Setting(
175+
key = POOL_CONNECTIONS_MIN_IDLE,
176+
description = "Pool min idle connections",
177+
required = false)
178+
Integer poolConnectionsMinIdle,
179+
@Setting(
180+
key = POOL_CONNECTION_TEST_ON_BORROW,
181+
description = "Pool test on borrow",
182+
required = false)
183+
Boolean poolConnectionTestOnBorrow,
184+
@Setting(
185+
key = POOL_CONNECTION_TEST_ON_CREATE,
186+
description = "Pool test on create",
187+
required = false)
188+
Boolean poolConnectionTestOnCreate,
189+
@Setting(
190+
key = POOL_CONNECTION_TEST_ON_RETURN,
191+
description = "Pool test on return",
192+
required = false)
193+
Boolean poolConnectionTestOnReturn,
194+
@Setting(
195+
key = POOL_CONNECTION_TEST_WHILE_IDLE,
196+
description = "Pool test while idle",
197+
required = false)
198+
Boolean poolConnectionTestWhileIdle,
199+
@Setting(
200+
key = POOL_CONNECTION_TEST_QUERY,
201+
description = "Pool test query",
202+
required = false)
203+
String poolConnectionTestQuery
204+
) {
205+
206+
}
156207
}

extensions/common/sql/sql-pool/sql-pool-apache-commons/src/test/java/org/eclipse/edc/sql/pool/commons/CommonsConnectionPoolServiceExtensionTest.java

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@
1515
package org.eclipse.edc.sql.pool.commons;
1616

1717
import org.assertj.core.api.ThrowingConsumer;
18+
import org.eclipse.edc.boot.system.injection.ObjectFactory;
1819
import org.eclipse.edc.boot.vault.InMemoryVault;
1920
import org.eclipse.edc.junit.extensions.DependencyInjectionExtension;
21+
import org.eclipse.edc.junit.extensions.TestExtensionContext;
2022
import org.eclipse.edc.spi.EdcException;
2123
import org.eclipse.edc.spi.security.Vault;
22-
import org.eclipse.edc.spi.system.ServiceExtensionContext;
2324
import org.eclipse.edc.spi.system.configuration.ConfigFactory;
2425
import org.eclipse.edc.sql.ConnectionFactory;
2526
import org.eclipse.edc.sql.datasource.ConnectionPoolDataSource;
@@ -54,7 +55,6 @@
5455
import static org.mockito.ArgumentMatchers.eq;
5556
import static org.mockito.Mockito.mock;
5657
import static org.mockito.Mockito.verify;
57-
import static org.mockito.Mockito.when;
5858

5959
@ExtendWith(DependencyInjectionExtension.class)
6060
class CommonsConnectionPoolServiceExtensionTest {
@@ -63,7 +63,7 @@ class CommonsConnectionPoolServiceExtensionTest {
6363
private final ConnectionFactory connectionFactory = mock();
6464

6565
@BeforeEach
66-
void setUp(ServiceExtensionContext context) {
66+
void setUp(TestExtensionContext context) {
6767
context.registerService(DataSourceRegistry.class, dataSourceRegistry);
6868
context.registerService(Vault.class, new InMemoryVault(mock(), null));
6969
context.registerService(ConnectionFactory.class, connectionFactory);
@@ -73,9 +73,10 @@ void setUp(ServiceExtensionContext context) {
7373
@ArgumentsSource(ConfigProvider.class)
7474
void initialize_withConfig(Map<String, String> configuration, ThrowingConsumer<CommonsConnectionPoolConfig> checker,
7575
boolean isEnv,
76-
CommonsConnectionPoolServiceExtension extension, ServiceExtensionContext context) {
76+
ObjectFactory factory, TestExtensionContext context) {
7777
var config = isEnv ? ConfigFactory.fromEnvironment(configuration) : ConfigFactory.fromMap(configuration);
78-
when(context.getConfig(EDC_DATASOURCE_PREFIX)).thenReturn(config);
78+
context.setConfig(config);
79+
var extension = factory.constructInstance(CommonsConnectionPoolServiceExtension.class);
7980

8081
extension.initialize(context);
8182

@@ -87,14 +88,14 @@ void initialize_withConfig(Map<String, String> configuration, ThrowingConsumer<C
8788
}
8889

8990
@Test
90-
void initialize_fromVault(CommonsConnectionPoolServiceExtension extension, ServiceExtensionContext context) {
91-
when(context.getConfig(EDC_DATASOURCE_PREFIX))
92-
.thenReturn(ConfigFactory.fromMap(Map.of("ds1.name", "ds1")));
91+
void initialize_fromVault(ObjectFactory factory, TestExtensionContext context) {
92+
context.setConfig(ConfigFactory.fromMap(Map.of(EDC_DATASOURCE_PREFIX + ".ds1.name", "ds1")));
9393
var vault = context.getService(Vault.class);
9494

9595
vault.storeSecret("edc.datasource." + DS_1_NAME + ".user", "test-user");
9696
vault.storeSecret("edc.datasource." + DS_1_NAME + ".password", "test-pwd");
9797
vault.storeSecret("edc.datasource." + DS_1_NAME + ".url", "jdbc://whatever");
98+
var extension = factory.constructInstance(CommonsConnectionPoolServiceExtension.class);
9899

99100
extension.initialize(context);
100101

@@ -112,17 +113,17 @@ void initialize_fromVault(CommonsConnectionPoolServiceExtension extension, Servi
112113
}
113114

114115
@Test
115-
void initialize_fromVault_shouldOverrideConfig(CommonsConnectionPoolServiceExtension extension, ServiceExtensionContext context) {
116-
when(context.getConfig(EDC_DATASOURCE_PREFIX))
117-
.thenReturn(ConfigFactory.fromMap(
118-
Map.of("ds1.name", "ds1",
119-
"ds1.user", "this-should-be-ignored",
120-
"ds1.password", "this-as-well")));
116+
void initialize_fromVault_shouldOverrideConfig(ObjectFactory factory, TestExtensionContext context) {
117+
context.setConfig(ConfigFactory.fromMap(Map.of(
118+
EDC_DATASOURCE_PREFIX + ".ds1.name", "ds1",
119+
EDC_DATASOURCE_PREFIX + ".ds1.user", "this-should-be-ignored",
120+
EDC_DATASOURCE_PREFIX + ".ds1.password", "this-as-well")));
121121
var vault = context.getService(Vault.class);
122122

123123
vault.storeSecret("edc.datasource." + DS_1_NAME + ".user", "test-user");
124124
vault.storeSecret("edc.datasource." + DS_1_NAME + ".password", "test-pwd");
125125
vault.storeSecret("edc.datasource." + DS_1_NAME + ".url", "jdbc://whatever");
126+
var extension = factory.constructInstance(CommonsConnectionPoolServiceExtension.class);
126127

127128
extension.initialize(context);
128129

@@ -141,18 +142,18 @@ void initialize_fromVault_shouldOverrideConfig(CommonsConnectionPoolServiceExten
141142

142143
static class ConfigProvider implements ArgumentsProvider {
143144

144-
private final Map<String, String> defaultConfig = Map.of(DS_1_NAME + ".url", DS_1_NAME);
145+
private final Map<String, String> defaultConfig = Map.of(EDC_DATASOURCE_PREFIX + "." + DS_1_NAME + ".url", DS_1_NAME);
145146

146147
private final Map<String, String> configuration = Map.of(
147-
DS_1_NAME + ".url", DS_1_NAME,
148-
DS_1_NAME + "." + POOL_CONNECTION_TEST_ON_CREATE, "false",
149-
DS_1_NAME + "." + POOL_CONNECTION_TEST_ON_BORROW, "false",
150-
DS_1_NAME + "." + POOL_CONNECTION_TEST_ON_RETURN, "true",
151-
DS_1_NAME + "." + POOL_CONNECTION_TEST_WHILE_IDLE, "true",
152-
DS_1_NAME + "." + POOL_CONNECTION_TEST_QUERY, "SELECT foo FROM bar;",
153-
DS_1_NAME + "." + POOL_CONNECTIONS_MIN_IDLE, "10",
154-
DS_1_NAME + "." + POOL_CONNECTIONS_MAX_IDLE, "10",
155-
DS_1_NAME + "." + POOL_CONNECTIONS_MAX_TOTAL, "10");
148+
EDC_DATASOURCE_PREFIX + "." + DS_1_NAME + ".url", DS_1_NAME,
149+
EDC_DATASOURCE_PREFIX + "." + DS_1_NAME + "." + POOL_CONNECTION_TEST_ON_CREATE, "false",
150+
EDC_DATASOURCE_PREFIX + "." + DS_1_NAME + "." + POOL_CONNECTION_TEST_ON_BORROW, "false",
151+
EDC_DATASOURCE_PREFIX + "." + DS_1_NAME + "." + POOL_CONNECTION_TEST_ON_RETURN, "true",
152+
EDC_DATASOURCE_PREFIX + "." + DS_1_NAME + "." + POOL_CONNECTION_TEST_WHILE_IDLE, "true",
153+
EDC_DATASOURCE_PREFIX + "." + DS_1_NAME + "." + POOL_CONNECTION_TEST_QUERY, "SELECT foo FROM bar;",
154+
EDC_DATASOURCE_PREFIX + "." + DS_1_NAME + "." + POOL_CONNECTIONS_MIN_IDLE, "10",
155+
EDC_DATASOURCE_PREFIX + "." + DS_1_NAME + "." + POOL_CONNECTIONS_MAX_IDLE, "10",
156+
EDC_DATASOURCE_PREFIX + "." + DS_1_NAME + "." + POOL_CONNECTIONS_MAX_TOTAL, "10");
156157

157158

158159
@Override

0 commit comments

Comments
 (0)