Skip to content

Commit 339ee13

Browse files
authored
Merge pull request quarkusio#52151 from nconcetti/mongodb-panache-fix-for-multiple-client-beans
Support multiple named mongoclients while using panache
2 parents f9f80af + 0d877b0 commit 339ee13

File tree

3 files changed

+122
-14
lines changed

3 files changed

+122
-14
lines changed

extensions/panache/mongodb-panache-common/runtime/src/main/java/io/quarkus/mongodb/panache/common/runtime/BeanUtils.java

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import io.quarkus.arc.InjectableBean;
1313
import io.quarkus.arc.InjectableInstance;
1414
import io.quarkus.arc.InstanceHandle;
15+
import io.quarkus.mongodb.MongoClientName;
1516
import io.quarkus.mongodb.panache.common.MongoDatabaseResolver;
1617
import io.quarkus.mongodb.panache.common.MongoEntity;
1718
import io.quarkus.mongodb.runtime.MongoClientBeanUtil;
@@ -34,26 +35,19 @@ public static String beanName(MongoEntity entity) {
3435

3536
public static <T> T clientFromArc(MongoEntity entity,
3637
Class<T> clientClass, boolean isReactive) {
37-
T mongoClient = Arc.container()
38-
.instance(clientClass, MongoClientBeanUtil.clientLiteral(beanName(entity), isReactive))
39-
.get();
38+
// we must consider multiple instances if @MongoClientName is used in client code
39+
T mongoClient = firstInstanceWithoutQualifier(
40+
Arc.container().select(clientClass, MongoClientBeanUtil.clientLiteral(beanName(entity), isReactive)).handles(),
41+
MongoClientName.class);
4042
if (mongoClient != null) {
4143
return mongoClient;
4244
}
4345

4446
if ((entity == null || entity.clientName().isEmpty())) {
4547
// this case happens when there are multiple instances because they are all annotated with @Named
46-
for (InstanceHandle<T> handle : Arc.container().select(clientClass).handles()) {
47-
InjectableBean<T> bean = handle.getBean();
48-
boolean hasNamed = false;
49-
for (Annotation qualifier : bean.getQualifiers()) {
50-
if (qualifier.annotationType().equals(Named.class)) {
51-
hasNamed = true;
52-
}
53-
}
54-
if (!hasNamed) {
55-
return handle.get();
56-
}
48+
mongoClient = firstInstanceWithoutQualifier(Arc.container().select(clientClass).handles(), Named.class);
49+
if (mongoClient != null) {
50+
return mongoClient;
5751
}
5852
throw new IllegalStateException(String.format("Unable to find default %s bean", clientClass.getSimpleName()));
5953
} else {
@@ -94,4 +88,21 @@ public static Optional<String> getDatabaseNameFromResolver() {
9488
.map(MongoDatabaseResolver::resolve)
9589
.filter(Predicate.not(String::isBlank));
9690
}
91+
92+
private static <T> T firstInstanceWithoutQualifier(Iterable<InstanceHandle<T>> handles,
93+
Class<? extends Annotation> qualifier) {
94+
for (InstanceHandle<T> handle : handles) {
95+
InjectableBean<T> bean = handle.getBean();
96+
boolean match = false;
97+
for (Annotation q : bean.getQualifiers()) {
98+
if (q.annotationType().equals(qualifier)) {
99+
match = true;
100+
}
101+
}
102+
if (!match) {
103+
return handle.get();
104+
}
105+
}
106+
return null;
107+
}
97108
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package io.quarkus.mongodb.panache;
2+
3+
import static org.junit.jupiter.api.Assertions.assertAll;
4+
import static org.junit.jupiter.api.Assertions.assertEquals;
5+
import static org.junit.jupiter.api.Assertions.assertNotNull;
6+
7+
import jakarta.enterprise.context.ApplicationScoped;
8+
import jakarta.inject.Inject;
9+
10+
import org.junit.jupiter.api.Test;
11+
import org.junit.jupiter.api.extension.RegisterExtension;
12+
13+
import com.mongodb.client.MongoClient;
14+
15+
import io.quarkus.mongodb.MongoClientName;
16+
import io.quarkus.mongodb.panache.common.MongoEntity;
17+
import io.quarkus.mongodb.reactive.ReactiveMongoClient;
18+
import io.quarkus.test.QuarkusUnitTest;
19+
20+
public class MultipleMongoClientsTest {
21+
@RegisterExtension
22+
static QuarkusUnitTest runner = new QuarkusUnitTest()
23+
.overrideConfigKey("quarkus.mongodb.devservices.enabled", "false")
24+
.withApplicationRoot((jar) -> jar
25+
.addAsResource("named-clients.properties"));
26+
27+
@Inject
28+
WithDefaultMongoClientEntityRepository withDefaultMongoClientEntityRepository;
29+
30+
@Inject
31+
WithMongoClient1EntityRepository withMongoClient1EntityRepository;
32+
33+
@Inject
34+
WithMongoClient2EntityRepository withMongoClient2EntityRepository;
35+
36+
@Inject
37+
@MongoClientName("mongoclient1")
38+
MongoClient mongoClient1;
39+
40+
@Inject
41+
@MongoClientName("mongoclient1")
42+
ReactiveMongoClient reactiveMongoClient1;
43+
44+
@Inject
45+
@MongoClientName("mongoclient2")
46+
MongoClient mongoClient2;
47+
48+
@Inject
49+
@MongoClientName("mongoclient2")
50+
ReactiveMongoClient reactiveMongoClient2;
51+
52+
@Test
53+
public void testMongoEntity() {
54+
assertAll(
55+
() -> assertEquals("default-mongoclient-db", withDefaultMongoClientEntityRepository.mongoDatabase().getName()),
56+
() -> assertEquals("mongoclient1-db", withMongoClient1EntityRepository.mongoDatabase().getName()),
57+
() -> assertEquals("mongoclient2-db", withMongoClient2EntityRepository.mongoDatabase().getName()),
58+
() -> assertNotNull(reactiveMongoClient1),
59+
() -> assertNotNull(reactiveMongoClient2));
60+
}
61+
62+
@MongoEntity(database = "default-mongoclient-db")
63+
public static class WithDefaultMongoClientEntity extends PanacheMongoEntity {
64+
public String field;
65+
}
66+
67+
@MongoEntity(database = "mongoclient1-db", clientName = "mongoclient1")
68+
public static class WithMongoClient1Entity extends PanacheMongoEntity {
69+
public String field;
70+
}
71+
72+
@MongoEntity(database = "mongoclient2-db", clientName = "mongoclient2")
73+
public static class WithMongoClient2Entity extends PanacheMongoEntity {
74+
public String field;
75+
}
76+
77+
@ApplicationScoped
78+
public static class WithDefaultMongoClientEntityRepository implements PanacheMongoRepository<WithDefaultMongoClientEntity> {
79+
}
80+
81+
@ApplicationScoped
82+
public static class WithMongoClient1EntityRepository implements PanacheMongoRepository<WithMongoClient1Entity> {
83+
}
84+
85+
@ApplicationScoped
86+
public static class WithMongoClient2EntityRepository implements PanacheMongoRepository<WithMongoClient2Entity> {
87+
}
88+
89+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
quarkus.mongodb.devservices.enabled=false
2+
3+
quarkus.mongodb.connection-string=mongodb://localhost:27018
4+
quarkus.mongodb.database=default-mongoclient-db
5+
quarkus.mongodb.mongoclient1.connection-string=mongodb://localhost:27018
6+
quarkus.mongodb.mongoclient1.database=mongoclient1-db
7+
quarkus.mongodb.mongoclient2.connection-string=mongodb://localhost:27018
8+
quarkus.mongodb.mongoclient2.database=mongoclient2-db

0 commit comments

Comments
 (0)