1414
1515package org .eclipse .edc .sql .pool .commons ;
1616
17+ import org .eclipse .edc .runtime .metamodel .annotation .Configuration ;
1718import org .eclipse .edc .runtime .metamodel .annotation .Extension ;
1819import org .eclipse .edc .runtime .metamodel .annotation .Inject ;
1920import 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 ;
2023import org .eclipse .edc .spi .EdcException ;
2124import org .eclipse .edc .spi .monitor .Monitor ;
2225import org .eclipse .edc .spi .security .Vault ;
3033
3134import java .util .LinkedList ;
3235import java .util .List ;
36+ import java .util .Map ;
3337import java .util .Optional ;
3438import java .util .Properties ;
35- import java .util .function .BiFunction ;
3639import java .util .function .Consumer ;
40+ import java .util .function .Supplier ;
3741import javax .sql .DataSource ;
3842
3943import 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}
0 commit comments