Skip to content

Commit 7511eed

Browse files
author
Tomáš Kraus
authored
4.x: DB client JDBC connection pool separated to a standalone module. (helidon-io#7265)
* DB client JDBC connection pool separated to a standalone module. Signed-off-by: Tomáš Kraus <tomas.kraus@oracle.com> * Fixed typo in exception messages. Signed-off-by: Tomáš Kraus <tomas.kraus@oracle.com> * Review notes Signed-off-by: Tomáš Kraus <tomas.kraus@oracle.com> * Review notes Signed-off-by: Tomas Kraus <tomas.kraus@oracle.com> * Fixed build issue Signed-off-by: Tomas Kraus <tomas.kraus@oracle.com> --------- Signed-off-by: Tomáš Kraus <tomas.kraus@oracle.com> Signed-off-by: Tomas Kraus <tomas.kraus@oracle.com>
1 parent 5ac17bc commit 7511eed

37 files changed

Lines changed: 688 additions & 261 deletions

File tree

archetypes/helidon/src/main/archetype/se/custom/database.xml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,11 @@ docker run --rm --name mongo -p 27017:27017 mongo
284284
</map>
285285
<map if="${server} != 'mongodb'">
286286
<value key="groupId">io.helidon.dbclient</value>
287-
<value key="artifactId">helidon-dbclient-metrics-jdbc</value>
287+
<value key="artifactId">helidon-dbclient-hikari</value>
288+
</map>
289+
<map if="${server} != 'mongodb'">
290+
<value key="groupId">io.helidon.dbclient</value>
291+
<value key="artifactId">helidon-dbclient-metrics-hikari</value>
288292
</map>
289293
<map>
290294
<value key="groupId">io.helidon.dbclient</value>
@@ -356,6 +360,11 @@ docker run --rm --name mongo -p 27017:27017 mongo
356360
<value key="artifactId">helidon-dbclient-jdbc</value>
357361
<value key="scope">test</value>
358362
</map>
363+
<map if="${server} == 'mongodb'">
364+
<value key="groupId">io.helidon.dbclient</value>
365+
<value key="artifactId">helidon-dbclient-hikari</value>
366+
<value key="scope">test</value>
367+
</map>
359368
</list>
360369
<list key="Main-helidon-imports" if="${server} != 'mongo'">
361370
<value>io.helidon.dbclient.DbClient</value>

bom/pom.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,11 @@
542542
<artifactId>helidon-dbclient-jdbc</artifactId>
543543
<version>${helidon.version}</version>
544544
</dependency>
545+
<dependency>
546+
<groupId>io.helidon.dbclient</groupId>
547+
<artifactId>helidon-dbclient-hikari</artifactId>
548+
<version>${helidon.version}</version>
549+
</dependency>
545550
<dependency>
546551
<groupId>io.helidon.dbclient</groupId>
547552
<artifactId>helidon-dbclient-mongodb</artifactId>
@@ -564,7 +569,7 @@
564569
</dependency>
565570
<dependency>
566571
<groupId>io.helidon.dbclient</groupId>
567-
<artifactId>helidon-dbclient-metrics-jdbc</artifactId>
572+
<artifactId>helidon-dbclient-metrics-hikari</artifactId>
568573
<version>${helidon.version}</version>
569574
</dependency>
570575
<dependency>

dbclient/hikari/pom.xml

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Copyright (c) 2023 Oracle and/or its affiliates.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
18+
<project xmlns="http://maven.apache.org/POM/4.0.0"
19+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
21+
<modelVersion>4.0.0</modelVersion>
22+
<parent>
23+
<groupId>io.helidon.dbclient</groupId>
24+
<artifactId>helidon-dbclient-project</artifactId>
25+
<version>4.0.0-SNAPSHOT</version>
26+
<relativePath>../pom.xml</relativePath>
27+
</parent>
28+
<artifactId>helidon-dbclient-hikari</artifactId>
29+
<name>Helidon Database Client Hikari Connection Pool</name>
30+
<description>Hikari connection pool for JDBC DB client</description>
31+
32+
<dependencies>
33+
<dependency>
34+
<groupId>io.helidon.dbclient</groupId>
35+
<artifactId>helidon-dbclient-jdbc</artifactId>
36+
</dependency>
37+
<dependency>
38+
<groupId>io.helidon.common.features</groupId>
39+
<artifactId>helidon-common-features-api</artifactId>
40+
</dependency>
41+
<dependency>
42+
<groupId>io.helidon.builder</groupId>
43+
<artifactId>helidon-builder-api</artifactId>
44+
</dependency>
45+
<dependency>
46+
<groupId>io.helidon.config</groupId>
47+
<artifactId>helidon-config-metadata</artifactId>
48+
<optional>true</optional>
49+
</dependency>
50+
<dependency>
51+
<groupId>com.zaxxer</groupId>
52+
<artifactId>HikariCP</artifactId>
53+
</dependency>
54+
<dependency>
55+
<groupId>io.helidon.config</groupId>
56+
<artifactId>helidon-config</artifactId>
57+
<scope>test</scope>
58+
</dependency>
59+
<dependency>
60+
<groupId>io.helidon.config</groupId>
61+
<artifactId>helidon-config-yaml</artifactId>
62+
<scope>test</scope>
63+
</dependency>
64+
<dependency>
65+
<groupId>org.junit.jupiter</groupId>
66+
<artifactId>junit-jupiter-api</artifactId>
67+
<scope>test</scope>
68+
</dependency>
69+
<dependency>
70+
<groupId>org.hamcrest</groupId>
71+
<artifactId>hamcrest-all</artifactId>
72+
<scope>test</scope>
73+
</dependency>
74+
<dependency>
75+
<groupId>org.mockito</groupId>
76+
<artifactId>mockito-core</artifactId>
77+
<scope>test</scope>
78+
</dependency>
79+
</dependencies>
80+
81+
<build>
82+
<plugins>
83+
<plugin>
84+
<groupId>org.apache.maven.plugins</groupId>
85+
<artifactId>maven-compiler-plugin</artifactId>
86+
<configuration>
87+
<annotationProcessorPaths>
88+
<path>
89+
<groupId>io.helidon.common.features</groupId>
90+
<artifactId>helidon-common-features-processor</artifactId>
91+
<version>${helidon.version}</version>
92+
</path>
93+
<path>
94+
<groupId>io.helidon.config</groupId>
95+
<artifactId>helidon-config-metadata-processor</artifactId>
96+
<version>${helidon.version}</version>
97+
</path>
98+
<path>
99+
<groupId>io.helidon.builder</groupId>
100+
<artifactId>helidon-builder-processor</artifactId>
101+
<version>${helidon.version}</version>
102+
</path>
103+
</annotationProcessorPaths>
104+
</configuration>
105+
<dependencies>
106+
<dependency>
107+
<groupId>io.helidon.builder</groupId>
108+
<artifactId>helidon-builder-processor</artifactId>
109+
<version>${helidon.version}</version>
110+
</dependency>
111+
<dependency>
112+
<groupId>io.helidon.config</groupId>
113+
<artifactId>helidon-config-metadata-processor</artifactId>
114+
<version>${helidon.version}</version>
115+
</dependency>
116+
<dependency>
117+
<groupId>io.helidon.inject.configdriven</groupId>
118+
<artifactId>helidon-inject-configdriven-processor</artifactId>
119+
<version>${helidon.version}</version>
120+
</dependency>
121+
</dependencies>
122+
</plugin>
123+
</plugins>
124+
</build>
125+
</project>
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
* Copyright (c) 2023 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.helidon.dbclient.hikari;
17+
18+
import java.sql.Connection;
19+
import java.sql.SQLException;
20+
import java.util.List;
21+
import java.util.ServiceLoader;
22+
import java.util.regex.Matcher;
23+
import java.util.regex.Pattern;
24+
import java.util.stream.Collectors;
25+
26+
import io.helidon.common.HelidonServiceLoader;
27+
import io.helidon.common.config.Config;
28+
import io.helidon.dbclient.DbClientException;
29+
import io.helidon.dbclient.hikari.spi.HikariMetricsProvider;
30+
import io.helidon.dbclient.jdbc.JdbcConnectionPool;
31+
32+
import com.zaxxer.hikari.HikariConfig;
33+
import com.zaxxer.hikari.HikariDataSource;
34+
35+
class HikariConnectionPool implements JdbcConnectionPool {
36+
37+
private final HikariDataSource dataSource;
38+
private final String dbType;
39+
private final String serviceName;
40+
41+
private HikariConnectionPool(Builder builder, String dbType) {
42+
this.dbType = dbType;
43+
HikariConfig config = new HikariConfig(builder.properties());
44+
config.setJdbcUrl(builder.url());
45+
config.setUsername(builder.username());
46+
config.setPassword(builder.password());
47+
// Apply configuration update from extensions
48+
builder.extensions()
49+
.forEach(registry -> registry.register(config::setMetricRegistry));
50+
this.dataSource = new HikariDataSource(config);
51+
this.serviceName = builder.serviceName();
52+
}
53+
54+
@Override
55+
public String name() {
56+
return serviceName;
57+
}
58+
59+
@Override
60+
public String type() {
61+
return "hikari";
62+
}
63+
64+
@Override
65+
public Connection connection() {
66+
try {
67+
return dataSource.getConnection();
68+
} catch (SQLException ex) {
69+
throw new DbClientException(
70+
String.format("Failed to create a connection to %s", dataSource.getJdbcUrl()), ex);
71+
}
72+
}
73+
74+
@Override
75+
public String dbType() {
76+
return dbType;
77+
}
78+
79+
static Builder builder() {
80+
return new Builder();
81+
}
82+
83+
84+
/**
85+
* Fluent API builder for {@link JdbcConnectionPool}.
86+
* The builder will produce a connection pool based on Hikari connection pool and will support
87+
* {@link io.helidon.dbclient.hikari.spi.HikariMetricsProvider} to enhance the Hikari pool.
88+
*/
89+
static final class Builder extends JdbcConnectionPool.BuilderBase<Builder, HikariConnectionPool> {
90+
91+
/**
92+
* Database connection configuration key for Hikari specific properties.
93+
*/
94+
private static final String HIKARI_RESERVED_CONFIG_KEY = "hikari";
95+
96+
//jdbc:mysql://127.0.0.1:3306/pokemon?useSSL=false
97+
private static final Pattern URL_PATTERN = Pattern.compile("(\\w+:\\w+):.*");
98+
99+
private final List<HikariMetricsProvider> extensions;
100+
private Config extensionsConfig;
101+
102+
103+
private Builder() {
104+
super();
105+
this.extensions = HelidonServiceLoader
106+
.create(ServiceLoader.load(HikariMetricsProvider.class))
107+
.asList();
108+
}
109+
110+
@Override
111+
public Builder config(Config config) {
112+
super.config(config);
113+
extensionsConfig = config.get(HIKARI_RESERVED_CONFIG_KEY);
114+
return this;
115+
}
116+
117+
@Override
118+
public HikariConnectionPool build() {
119+
final Matcher matcher = URL_PATTERN.matcher(url());
120+
String dbType = matcher.matches()
121+
? matcher.group(1)
122+
: DEFAULT_DB_TYPE;
123+
124+
return new HikariConnectionPool(this, dbType);
125+
}
126+
127+
/**
128+
* Loaded connection pool extensions providers.
129+
*/
130+
public List<HikariMetricsRegistry> extensions() {
131+
if (null == extensionsConfig) {
132+
extensionsConfig = Config.empty();
133+
}
134+
return extensions.stream()
135+
.map(provider -> provider.extension(extensionsConfig.get(provider.configKey())))
136+
.collect(Collectors.toList());
137+
}
138+
139+
}
140+
141+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright (c) 2023 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.helidon.dbclient.hikari;
17+
18+
import io.helidon.common.config.Config;
19+
import io.helidon.dbclient.jdbc.JdbcConnectionPool;
20+
import io.helidon.dbclient.jdbc.spi.JdbcConnectionPoolProvider;
21+
22+
/**
23+
* Hikari connection pool {@link java.util.ServiceLoader} provider.
24+
*/
25+
public class HikariConnectionPoolProvider implements JdbcConnectionPoolProvider {
26+
27+
private static final String CONFIG_NAME = "hikari";
28+
29+
/**
30+
* Creates an instance of Hikari connection pool {@link java.util.ServiceLoader} provider.
31+
*/
32+
public HikariConnectionPoolProvider() {
33+
}
34+
35+
@Override
36+
public String configKey() {
37+
return CONFIG_NAME;
38+
}
39+
40+
@Override
41+
public JdbcConnectionPool create(Config config, String name) {
42+
return HikariConnectionPool.builder()
43+
.config(config)
44+
.serviceName(name)
45+
.build();
46+
}
47+
48+
}

dbclient/jdbc/src/main/java/io/helidon/dbclient/jdbc/HikariCpExtension.java renamed to dbclient/hikari/src/main/java/io/helidon/dbclient/hikari/HikariMetricsRegistry.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,21 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package io.helidon.dbclient.jdbc;
16+
package io.helidon.dbclient.hikari;
1717

18-
import com.zaxxer.hikari.HikariConfig;
18+
import java.util.function.Consumer;
1919

2020
/**
21-
* Interceptor to handle connection pool configuration.
21+
* Hikari connection pool metric extension registry.
2222
*/
23-
public interface HikariCpExtension {
23+
@FunctionalInterface
24+
public interface HikariMetricsRegistry {
2425

2526
/**
26-
* Set additional configuration option.
27+
* Process registry of metric instances on Hikari connection pool.
2728
*
28-
* @param poolConfig pool configuration
29+
* @param registry pool configuration
2930
*/
30-
void configure(HikariConfig poolConfig);
31+
void register(Consumer<Object> registry);
32+
3133
}

0 commit comments

Comments
 (0)