Skip to content

Commit 17478be

Browse files
authored
Merge pull request quarkusio#47552 from yrodiere/i46324
Restore loading of all JDBC drivers on datasource creation
2 parents 81f6bbc + ac251a6 commit 17478be

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

extensions/agroal/deployment/src/main/java/io/quarkus/agroal/deployment/AgroalProcessor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
6363
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBundleBuildItem;
6464
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
65+
import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem;
6566
import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem;
6667
import io.quarkus.narayana.jta.deployment.NarayanaInitBuildItem;
6768
import io.quarkus.runtime.configuration.ConfigurationException;
@@ -89,6 +90,7 @@ void build(
8990
List<JdbcDriverBuildItem> jdbcDriverBuildItems,
9091
BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
9192
BuildProducer<NativeImageResourceBuildItem> resource,
93+
BuildProducer<ServiceProviderBuildItem> service,
9294
Capabilities capabilities,
9395
BuildProducer<ExtensionSslNativeSupportBuildItem> sslNativeSupport,
9496
BuildProducer<AggregatedDataSourceBuildTimeConfigBuildItem> aggregatedConfig,
@@ -139,6 +141,9 @@ void build(
139141
resource.produce(new NativeImageResourceBuildItem(
140142
"META-INF/services/" + io.agroal.api.security.AgroalSecurityProvider.class.getName()));
141143

144+
// accessed through io.quarkus.agroal.runtime.DataSources.loadDriversInTCCL
145+
service.produce(ServiceProviderBuildItem.allProvidersFromClassPath(Driver.class.getName()));
146+
142147
reflectiveClass.produce(ReflectiveClassBuildItem.builder(io.agroal.pool.ConnectionHandler[].class.getName(),
143148
io.agroal.pool.ConnectionHandler.class.getName(),
144149
io.agroal.api.security.AgroalDefaultSecurityProvider.class.getName(),

extensions/agroal/runtime/src/main/java/io/quarkus/agroal/runtime/DataSources.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package io.quarkus.agroal.runtime;
22

33
import java.sql.Connection;
4+
import java.sql.Driver;
45
import java.sql.Statement;
56
import java.util.Collection;
7+
import java.util.Iterator;
68
import java.util.Map;
9+
import java.util.ServiceLoader;
710
import java.util.Set;
811
import java.util.stream.Collectors;
912

@@ -154,6 +157,9 @@ public AgroalDataSource createDataSource(String dataSourceName, boolean otelEnab
154157
"Datasource " + dataSourceName + " does not have a JDBC URL and should not be created");
155158
}
156159

160+
// we first make sure that all available JDBC drivers are loaded in the current TCCL
161+
loadDriversInTCCL();
162+
157163
AgroalDataSourceSupport.Entry matchingSupportEntry = agroalDataSourceSupport.entries.get(dataSourceName);
158164
String resolvedDriverClass = matchingSupportEntry.resolvedDriverClass;
159165
Class<?> driver;
@@ -359,4 +365,27 @@ public boolean isValid(Connection connection) {
359365
poolConfiguration.recoveryEnable(dataSourceJdbcRuntimeConfig.enableRecovery());
360366
}
361367

368+
/**
369+
* Uses the {@link ServiceLoader#load(Class) ServiceLoader to load the JDBC drivers} in context
370+
* of the current {@link Thread#getContextClassLoader() TCCL}.
371+
* <p>
372+
* This is necessary to have JDBC URLs work properly, in particular when using custom drivers,
373+
* and in particular when the app gets "restarted" in a single system (?) classloader,
374+
* because DriverManager's list of available drivers would get cleared on shutdown.
375+
* <p>
376+
* See also https://github.com/quarkusio/quarkus/issues/46324#issuecomment-2687615191
377+
*/
378+
private static void loadDriversInTCCL() {
379+
// load JDBC drivers in the current TCCL
380+
final ServiceLoader<Driver> drivers = ServiceLoader.load(Driver.class);
381+
final Iterator<Driver> iterator = drivers.iterator();
382+
while (iterator.hasNext()) {
383+
try {
384+
// load the driver
385+
iterator.next();
386+
} catch (Throwable t) {
387+
// ignore
388+
}
389+
}
390+
}
362391
}

0 commit comments

Comments
 (0)