Skip to content

Commit 4e62892

Browse files
committed
CredentialsProvider API should be asynchronous
Closes #32021 The synchronous method is deprecated and is invoked by the asynchronous variant. Extensions must be updated to invoke the asynchronous variant.
1 parent 12292ec commit 4e62892

File tree

13 files changed

+68
-66
lines changed

13 files changed

+68
-66
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public AgroalVaultCredentialsProviderPassword(String credentialsProviderName, Cr
1818
@Override
1919
public Properties asProperties() {
2020
Properties properties = new Properties();
21-
Map<String, String> credentials = credentialsProvider.getCredentials(getWord());
21+
Map<String, String> credentials = credentialsProvider.getCredentialsAsync(getWord()).await().indefinitely();
2222
credentials.forEach((key, value) -> properties.setProperty(key, value));
2323
return properties;
2424
}

extensions/credentials/runtime/src/main/java/io/quarkus/credentials/CredentialsProvider.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,15 @@
22

33
import java.util.Map;
44

5+
import io.smallrye.mutiny.Uni;
6+
import io.smallrye.mutiny.infrastructure.Infrastructure;
7+
58
/**
69
* Provides an indirection between credentials consumers such as Agroal and implementers such as Vault.
10+
* <p>
11+
* While not mandatory, it is recommended to implement the asynchronous {@link #getCredentialsAsync(String)} rather than
12+
* {@link #getCredentials(String)}.
13+
* Indeed, the synchronous variant may be removed in a future version.
714
*/
815
public interface CredentialsProvider {
916

@@ -12,11 +19,25 @@ public interface CredentialsProvider {
1219
String EXPIRATION_TIMESTAMP_PROPERTY_NAME = "expires-at";
1320

1421
/**
15-
* Returns the credentials for a given credentials provider
22+
* Returns the credentials for a given credentials provider.
1623
*
1724
* @param credentialsProviderName the name of the credentials provider, which can be used to retrieve custom configuration
1825
* @return the credentials
26+
* @deprecated invoke {@link #getCredentialsAsync(String)} instead
1927
*/
20-
Map<String, String> getCredentials(String credentialsProviderName);
28+
@Deprecated
29+
default Map<String, String> getCredentials(String credentialsProviderName) {
30+
throw new UnsupportedOperationException("Either `getCredentials` or `getCredentialsAsync` must be implemented`");
31+
}
2132

33+
/**
34+
* Returns the credentials for a given credentials provider.
35+
*
36+
* @param credentialsProviderName the name of the credentials provider, which can be used to retrieve custom configuration
37+
* @return a {@link Uni} completed with the credentials, or failed
38+
*/
39+
default Uni<Map<String, String>> getCredentialsAsync(String credentialsProviderName) {
40+
return Uni.createFrom().item(() -> getCredentials(credentialsProviderName))
41+
.runSubscriptionOn(Infrastructure.getDefaultExecutor());
42+
}
2243
}

extensions/mongodb-client/runtime/src/main/java/io/quarkus/mongodb/runtime/MongoClients.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ private UsernamePassword determineUserNamePassword(CredentialConfig config) {
527527
String beanName = config.credentialsProviderName().orElse(null);
528528
CredentialsProvider credentialsProvider = CredentialsProviderFinder.find(beanName);
529529
String name = config.credentialsProvider().get();
530-
Map<String, String> credentials = credentialsProvider.getCredentials(name);
530+
Map<String, String> credentials = credentialsProvider.getCredentialsAsync(name).await().indefinitely();
531531
String user = credentials.get(USER_PROPERTY_NAME);
532532
String password = credentials.get(PASSWORD_PROPERTY_NAME);
533533
return new UsernamePassword(user, password.toCharArray());

extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ public String get() {
393393
String providerName = provider.name().orElse(null);
394394
String keyringName = provider.keyringName().orElse(null);
395395
CredentialsProvider credentialsProvider = CredentialsProviderFinder.find(providerName);
396+
// getCredentials invocation may block the event loop
396397
return credentialsProvider.getCredentials(keyringName).get(provider.key().get());
397398
}
398399
return null;

extensions/reactive-datasource/runtime/src/main/java/io/quarkus/reactive/datasource/runtime/ConnectOptionsSupplier.java

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,63 +4,45 @@
44
import static io.quarkus.credentials.CredentialsProvider.USER_PROPERTY_NAME;
55

66
import java.util.List;
7-
import java.util.Map;
8-
import java.util.concurrent.Callable;
97
import java.util.concurrent.atomic.AtomicInteger;
10-
import java.util.function.IntUnaryOperator;
118
import java.util.function.Supplier;
129
import java.util.function.UnaryOperator;
1310

1411
import io.quarkus.credentials.CredentialsProvider;
12+
import io.smallrye.mutiny.Uni;
13+
import io.smallrye.mutiny.vertx.UniHelper;
1514
import io.vertx.core.Future;
16-
import io.vertx.core.Vertx;
1715
import io.vertx.sqlclient.SqlConnectOptions;
1816

1917
public class ConnectOptionsSupplier<CO extends SqlConnectOptions> implements Supplier<Future<CO>> {
2018

21-
private final Vertx vertx;
2219
private final CredentialsProvider credentialsProvider;
2320
private final String credentialsProviderName;
2421
private final List<CO> connectOptionsList;
2522
private final UnaryOperator<CO> connectOptionsCopy;
26-
private final Callable<CO> blockingCodeHandler;
23+
private final AtomicInteger idx = new AtomicInteger();
2724

28-
public ConnectOptionsSupplier(Vertx vertx, CredentialsProvider credentialsProvider, String credentialsProviderName,
25+
public ConnectOptionsSupplier(CredentialsProvider credentialsProvider, String credentialsProviderName,
2926
List<CO> connectOptionsList, UnaryOperator<CO> connectOptionsCopy) {
30-
this.vertx = vertx;
3127
this.credentialsProvider = credentialsProvider;
3228
this.credentialsProviderName = credentialsProviderName;
3329
this.connectOptionsList = connectOptionsList;
3430
this.connectOptionsCopy = connectOptionsCopy;
35-
this.blockingCodeHandler = new BlockingCodeHandler();
3631
}
3732

3833
@Override
3934
public Future<CO> get() {
40-
return vertx.executeBlocking(blockingCodeHandler, false);
41-
}
42-
43-
private class BlockingCodeHandler implements Callable<CO>, IntUnaryOperator {
44-
45-
final AtomicInteger idx = new AtomicInteger();
46-
47-
@Override
48-
public CO call() {
49-
Map<String, String> credentials = credentialsProvider.getCredentials(credentialsProviderName);
50-
String user = credentials.get(USER_PROPERTY_NAME);
51-
String password = credentials.get(PASSWORD_PROPERTY_NAME);
52-
53-
int nextIdx = idx.getAndUpdate(this);
54-
55-
CO connectOptions = connectOptionsCopy.apply(connectOptionsList.get(nextIdx));
56-
connectOptions.setUser(user).setPassword(password);
57-
58-
return connectOptions;
59-
}
60-
61-
@Override
62-
public int applyAsInt(int previousIdx) {
63-
return previousIdx == connectOptionsList.size() - 1 ? 0 : previousIdx + 1;
64-
}
35+
int nextIdx = idx.getAndUpdate(previousIdx -> previousIdx == connectOptionsList.size() - 1 ? 0 : previousIdx + 1);
36+
CO connectOptions = connectOptionsCopy.apply(connectOptionsList.get(nextIdx));
37+
return Uni.combine()
38+
.all()
39+
.unis(credentialsProvider.getCredentialsAsync(credentialsProviderName), Uni.createFrom().item(connectOptions))
40+
.with((credentials, co) -> {
41+
co.setUser(credentials.get(USER_PROPERTY_NAME));
42+
co.setPassword(credentials.get(PASSWORD_PROPERTY_NAME));
43+
return co;
44+
})
45+
.convert()
46+
.with(UniHelper::toFuture);
6547
}
6648
}

extensions/reactive-db2-client/runtime/src/main/java/io/quarkus/reactive/db2/client/runtime/DB2PoolRecorder.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,19 +124,19 @@ private DB2Pool initialize(VertxInternal vertx,
124124
PoolOptions poolOptions = toPoolOptions(eventLoopCount, dataSourceReactiveRuntimeConfig);
125125
DB2ConnectOptions db2ConnectOptions = toConnectOptions(dataSourceName, dataSourceRuntimeConfig,
126126
dataSourceReactiveRuntimeConfig, dataSourceReactiveDB2Config);
127-
Supplier<Future<DB2ConnectOptions>> databasesSupplier = toDatabasesSupplier(vertx, List.of(db2ConnectOptions),
127+
Supplier<Future<DB2ConnectOptions>> databasesSupplier = toDatabasesSupplier(List.of(db2ConnectOptions),
128128
dataSourceRuntimeConfig);
129129
return createPool(vertx, poolOptions, db2ConnectOptions, dataSourceName, databasesSupplier, context);
130130
}
131131

132-
private Supplier<Future<DB2ConnectOptions>> toDatabasesSupplier(Vertx vertx, List<DB2ConnectOptions> db2ConnectOptionsList,
132+
private Supplier<Future<DB2ConnectOptions>> toDatabasesSupplier(List<DB2ConnectOptions> db2ConnectOptionsList,
133133
DataSourceRuntimeConfig dataSourceRuntimeConfig) {
134134
Supplier<Future<DB2ConnectOptions>> supplier;
135135
if (dataSourceRuntimeConfig.credentialsProvider().isPresent()) {
136136
String beanName = dataSourceRuntimeConfig.credentialsProviderName().orElse(null);
137137
CredentialsProvider credentialsProvider = CredentialsProviderFinder.find(beanName);
138138
String name = dataSourceRuntimeConfig.credentialsProvider().get();
139-
supplier = new ConnectOptionsSupplier<>(vertx, credentialsProvider, name, db2ConnectOptionsList,
139+
supplier = new ConnectOptionsSupplier<>(credentialsProvider, name, db2ConnectOptionsList,
140140
DB2ConnectOptions::new);
141141
} else {
142142
supplier = Utils.roundRobinSupplier(db2ConnectOptionsList);
@@ -210,7 +210,7 @@ private DB2ConnectOptions toConnectOptions(String dataSourceName, DataSourceRunt
210210
String beanName = dataSourceRuntimeConfig.credentialsProviderName().orElse(null);
211211
CredentialsProvider credentialsProvider = CredentialsProviderFinder.find(beanName);
212212
String name = dataSourceRuntimeConfig.credentialsProvider().get();
213-
Map<String, String> credentials = credentialsProvider.getCredentials(name);
213+
Map<String, String> credentials = credentialsProvider.getCredentialsAsync(name).await().indefinitely();
214214
String user = credentials.get(USER_PROPERTY_NAME);
215215
String password = credentials.get(PASSWORD_PROPERTY_NAME);
216216
if (user != null) {

extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/MSSQLPoolRecorder.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,20 +124,19 @@ private MSSQLPool initialize(VertxInternal vertx,
124124
PoolOptions poolOptions = toPoolOptions(eventLoopCount, dataSourceReactiveRuntimeConfig);
125125
MSSQLConnectOptions mssqlConnectOptions = toMSSQLConnectOptions(dataSourceName, dataSourceRuntimeConfig,
126126
dataSourceReactiveRuntimeConfig, dataSourceReactiveMSSQLConfig);
127-
Supplier<Future<MSSQLConnectOptions>> databasesSupplier = toDatabasesSupplier(vertx, List.of(mssqlConnectOptions),
127+
Supplier<Future<MSSQLConnectOptions>> databasesSupplier = toDatabasesSupplier(List.of(mssqlConnectOptions),
128128
dataSourceRuntimeConfig);
129129
return createPool(vertx, poolOptions, mssqlConnectOptions, dataSourceName, databasesSupplier, context);
130130
}
131131

132-
private Supplier<Future<MSSQLConnectOptions>> toDatabasesSupplier(Vertx vertx,
133-
List<MSSQLConnectOptions> mssqlConnectOptionsList,
132+
private Supplier<Future<MSSQLConnectOptions>> toDatabasesSupplier(List<MSSQLConnectOptions> mssqlConnectOptionsList,
134133
DataSourceRuntimeConfig dataSourceRuntimeConfig) {
135134
Supplier<Future<MSSQLConnectOptions>> supplier;
136135
if (dataSourceRuntimeConfig.credentialsProvider().isPresent()) {
137136
String beanName = dataSourceRuntimeConfig.credentialsProviderName().orElse(null);
138137
CredentialsProvider credentialsProvider = CredentialsProviderFinder.find(beanName);
139138
String name = dataSourceRuntimeConfig.credentialsProvider().get();
140-
supplier = new ConnectOptionsSupplier<>(vertx, credentialsProvider, name, mssqlConnectOptionsList,
139+
supplier = new ConnectOptionsSupplier<>(credentialsProvider, name, mssqlConnectOptionsList,
141140
MSSQLConnectOptions::new);
142141
} else {
143142
supplier = Utils.roundRobinSupplier(mssqlConnectOptionsList);
@@ -214,7 +213,7 @@ private MSSQLConnectOptions toMSSQLConnectOptions(String dataSourceName, DataSou
214213
String beanName = dataSourceRuntimeConfig.credentialsProviderName().orElse(null);
215214
CredentialsProvider credentialsProvider = CredentialsProviderFinder.find(beanName);
216215
String name = dataSourceRuntimeConfig.credentialsProvider().get();
217-
Map<String, String> credentials = credentialsProvider.getCredentials(name);
216+
Map<String, String> credentials = credentialsProvider.getCredentialsAsync(name).await().indefinitely();
218217
String user = credentials.get(USER_PROPERTY_NAME);
219218
String password = credentials.get(PASSWORD_PROPERTY_NAME);
220219
if (user != null) {

extensions/reactive-mysql-client/runtime/src/main/java/io/quarkus/reactive/mysql/client/runtime/MySQLPoolRecorder.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,20 +125,19 @@ private MySQLPool initialize(VertxInternal vertx,
125125
dataSourceReactiveMySQLConfig);
126126
List<MySQLConnectOptions> mySQLConnectOptions = toMySQLConnectOptions(dataSourceName, dataSourceRuntimeConfig,
127127
dataSourceReactiveRuntimeConfig, dataSourceReactiveMySQLConfig);
128-
Supplier<Future<MySQLConnectOptions>> databasesSupplier = toDatabasesSupplier(vertx, mySQLConnectOptions,
128+
Supplier<Future<MySQLConnectOptions>> databasesSupplier = toDatabasesSupplier(mySQLConnectOptions,
129129
dataSourceRuntimeConfig);
130130
return createPool(vertx, poolOptions, mySQLConnectOptions, dataSourceName, databasesSupplier, context);
131131
}
132132

133-
private Supplier<Future<MySQLConnectOptions>> toDatabasesSupplier(Vertx vertx,
134-
List<MySQLConnectOptions> mySQLConnectOptions,
133+
private Supplier<Future<MySQLConnectOptions>> toDatabasesSupplier(List<MySQLConnectOptions> mySQLConnectOptions,
135134
DataSourceRuntimeConfig dataSourceRuntimeConfig) {
136135
Supplier<Future<MySQLConnectOptions>> supplier;
137136
if (dataSourceRuntimeConfig.credentialsProvider().isPresent()) {
138137
String beanName = dataSourceRuntimeConfig.credentialsProviderName().orElse(null);
139138
CredentialsProvider credentialsProvider = CredentialsProviderFinder.find(beanName);
140139
String name = dataSourceRuntimeConfig.credentialsProvider().get();
141-
supplier = new ConnectOptionsSupplier<>(vertx, credentialsProvider, name, mySQLConnectOptions,
140+
supplier = new ConnectOptionsSupplier<>(credentialsProvider, name, mySQLConnectOptions,
142141
MySQLConnectOptions::new);
143142
} else {
144143
supplier = Utils.roundRobinSupplier(mySQLConnectOptions);
@@ -213,7 +212,7 @@ private List<MySQLConnectOptions> toMySQLConnectOptions(String dataSourceName,
213212
String beanName = dataSourceRuntimeConfig.credentialsProviderName().orElse(null);
214213
CredentialsProvider credentialsProvider = CredentialsProviderFinder.find(beanName);
215214
String name = dataSourceRuntimeConfig.credentialsProvider().get();
216-
Map<String, String> credentials = credentialsProvider.getCredentials(name);
215+
Map<String, String> credentials = credentialsProvider.getCredentialsAsync(name).await().indefinitely();
217216
String user = credentials.get(USER_PROPERTY_NAME);
218217
String password = credentials.get(PASSWORD_PROPERTY_NAME);
219218
if (user != null) {

extensions/reactive-oracle-client/runtime/src/main/java/io/quarkus/reactive/oracle/client/runtime/OraclePoolRecorder.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,20 +119,19 @@ private OraclePool initialize(VertxInternal vertx,
119119
PoolOptions poolOptions = toPoolOptions(eventLoopCount, dataSourceReactiveRuntimeConfig);
120120
OracleConnectOptions oracleConnectOptions = toOracleConnectOptions(dataSourceName, dataSourceRuntimeConfig,
121121
dataSourceReactiveRuntimeConfig, dataSourceReactiveOracleConfig);
122-
Supplier<Future<OracleConnectOptions>> databasesSupplier = toDatabasesSupplier(vertx, List.of(oracleConnectOptions),
122+
Supplier<Future<OracleConnectOptions>> databasesSupplier = toDatabasesSupplier(List.of(oracleConnectOptions),
123123
dataSourceRuntimeConfig);
124124
return createPool(vertx, poolOptions, oracleConnectOptions, dataSourceName, databasesSupplier, context);
125125
}
126126

127-
private Supplier<Future<OracleConnectOptions>> toDatabasesSupplier(Vertx vertx,
128-
List<OracleConnectOptions> oracleConnectOptions,
127+
private Supplier<Future<OracleConnectOptions>> toDatabasesSupplier(List<OracleConnectOptions> oracleConnectOptions,
129128
DataSourceRuntimeConfig dataSourceRuntimeConfig) {
130129
Supplier<Future<OracleConnectOptions>> supplier;
131130
if (dataSourceRuntimeConfig.credentialsProvider().isPresent()) {
132131
String beanName = dataSourceRuntimeConfig.credentialsProviderName().orElse(null);
133132
CredentialsProvider credentialsProvider = CredentialsProviderFinder.find(beanName);
134133
String name = dataSourceRuntimeConfig.credentialsProvider().get();
135-
supplier = new ConnectOptionsSupplier<>(vertx, credentialsProvider, name, oracleConnectOptions,
134+
supplier = new ConnectOptionsSupplier<>(credentialsProvider, name, oracleConnectOptions,
136135
OracleConnectOptions::new);
137136
} else {
138137
supplier = Utils.roundRobinSupplier(oracleConnectOptions);
@@ -205,7 +204,7 @@ private OracleConnectOptions toOracleConnectOptions(String dataSourceName, DataS
205204
String beanName = dataSourceRuntimeConfig.credentialsProviderName().orElse(null);
206205
CredentialsProvider credentialsProvider = CredentialsProviderFinder.find(beanName);
207206
String name = dataSourceRuntimeConfig.credentialsProvider().get();
208-
Map<String, String> credentials = credentialsProvider.getCredentials(name);
207+
Map<String, String> credentials = credentialsProvider.getCredentialsAsync(name).await().indefinitely();
209208
String user = credentials.get(USER_PROPERTY_NAME);
210209
String password = credentials.get(PASSWORD_PROPERTY_NAME);
211210
if (user != null) {

extensions/reactive-pg-client/runtime/src/main/java/io/quarkus/reactive/pg/client/runtime/PgPoolRecorder.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,19 +123,19 @@ private PgPool initialize(VertxInternal vertx,
123123
PoolOptions poolOptions = toPoolOptions(eventLoopCount, dataSourceReactiveRuntimeConfig);
124124
List<PgConnectOptions> pgConnectOptionsList = toPgConnectOptions(dataSourceName, dataSourceRuntimeConfig,
125125
dataSourceReactiveRuntimeConfig, dataSourceReactivePostgreSQLConfig);
126-
Supplier<Future<PgConnectOptions>> databasesSupplier = toDatabasesSupplier(vertx, pgConnectOptionsList,
126+
Supplier<Future<PgConnectOptions>> databasesSupplier = toDatabasesSupplier(pgConnectOptionsList,
127127
dataSourceRuntimeConfig);
128128
return createPool(vertx, poolOptions, pgConnectOptionsList, dataSourceName, databasesSupplier, context);
129129
}
130130

131-
private Supplier<Future<PgConnectOptions>> toDatabasesSupplier(Vertx vertx, List<PgConnectOptions> pgConnectOptionsList,
131+
private Supplier<Future<PgConnectOptions>> toDatabasesSupplier(List<PgConnectOptions> pgConnectOptionsList,
132132
DataSourceRuntimeConfig dataSourceRuntimeConfig) {
133133
Supplier<Future<PgConnectOptions>> supplier;
134134
if (dataSourceRuntimeConfig.credentialsProvider().isPresent()) {
135135
String beanName = dataSourceRuntimeConfig.credentialsProviderName().orElse(null);
136136
CredentialsProvider credentialsProvider = CredentialsProviderFinder.find(beanName);
137137
String name = dataSourceRuntimeConfig.credentialsProvider().get();
138-
supplier = new ConnectOptionsSupplier<>(vertx, credentialsProvider, name, pgConnectOptionsList,
138+
supplier = new ConnectOptionsSupplier<>(credentialsProvider, name, pgConnectOptionsList,
139139
PgConnectOptions::new);
140140
} else {
141141
supplier = Utils.roundRobinSupplier(pgConnectOptionsList);
@@ -204,7 +204,7 @@ private List<PgConnectOptions> toPgConnectOptions(String dataSourceName, DataSou
204204
String beanName = dataSourceRuntimeConfig.credentialsProviderName().orElse(null);
205205
CredentialsProvider credentialsProvider = CredentialsProviderFinder.find(beanName);
206206
String name = dataSourceRuntimeConfig.credentialsProvider().get();
207-
Map<String, String> credentials = credentialsProvider.getCredentials(name);
207+
Map<String, String> credentials = credentialsProvider.getCredentialsAsync(name).await().indefinitely();
208208
String user = credentials.get(USER_PROPERTY_NAME);
209209
String password = credentials.get(PASSWORD_PROPERTY_NAME);
210210
if (user != null) {

0 commit comments

Comments
 (0)