Skip to content

Commit

Permalink
Use proper package for @MongoClientName
Browse files Browse the repository at this point in the history
For now we just deprecate the one annotation and support both

Relates to: quarkusio#11568 (comment)
  • Loading branch information
geoand committed Aug 27, 2020
1 parent b87ea49 commit 45af8ef
Show file tree
Hide file tree
Showing 9 changed files with 238 additions and 11 deletions.
11 changes: 8 additions & 3 deletions docs/src/main/asciidoc/mongodb.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,11 @@ multiple clients are **not** necessary as a single client is able to access all

=== Named Mongo client Injection

When using multiple clients, each `MongoClient`, you can select the client to inject using the `io.quarkus.mongodb.runtime.MongoClientName` qualifier.
When using multiple clients, each `MongoClient`, you can select the client to inject using the `io.quarkus.mongodb.MongoClientName` qualifier.
Using the above properties to configure three different clients, you can also inject each one as follows:

[source,java,indent=0]
--
----
@Inject
MongoClient defaultMongoClient;
Expand All @@ -275,7 +275,12 @@ MongoClient mongoClient1;
@Inject
@MongoClientName("inventory")
ReactiveMongoClient mongoClient2;
--
----

[NOTE]
====
The old `io.quarkus.mongodb.runtime.MongoClientName` has been deprecated. It still works, but will soon be removed, therefore users are encouraged to not use it.
====

== Running a MongoDB Database
As by default, `MongoClient` is configured to access a local MongoDB database on port 27017 (the default MongoDB port), if you have a local running database on this port, there is nothing more to do before being able to test it!
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.quarkus.mongodb.deployment;

import io.quarkus.builder.item.MultiBuildItem;
import io.quarkus.mongodb.runtime.MongoClientName;
import io.quarkus.mongodb.MongoClientName;

/**
* Represents the values of the {@link MongoClientName}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,20 @@
import io.quarkus.deployment.builditem.SslNativeConfigBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.metrics.MetricsCapabilityBuildItem;
import io.quarkus.mongodb.MongoClientName;
import io.quarkus.mongodb.reactive.ReactiveMongoClient;
import io.quarkus.mongodb.runtime.MongoClientBeanUtil;
import io.quarkus.mongodb.runtime.MongoClientName;
import io.quarkus.mongodb.runtime.MongoClientRecorder;
import io.quarkus.mongodb.runtime.MongoClientSupport;
import io.quarkus.mongodb.runtime.MongoClients;
import io.quarkus.mongodb.runtime.MongodbConfig;
import io.quarkus.smallrye.health.deployment.spi.HealthBuildItem;

public class MongoClientProcessor {
private static final DotName LEGACY_MONGO_CLIENT_ANNOTATION = DotName
.createSimple(io.quarkus.mongodb.runtime.MongoClientName.class.getName());
private static final DotName MONGO_CLIENT_ANNOTATION = DotName.createSimple(MongoClientName.class.getName());

private static final DotName MONGO_CLIENT = DotName.createSimple(MongoClient.class.getName());
private static final DotName REACTIVE_MONGO_CLIENT = DotName.createSimple(ReactiveMongoClient.class.getName());

Expand Down Expand Up @@ -93,15 +96,20 @@ public void mongoClientNames(ApplicationArchivesBuildItem applicationArchivesBui
BuildProducer<MongoClientNameBuildItem> mongoClientName) {
Set<String> values = new HashSet<>();
IndexView indexView = applicationArchivesBuildItem.getRootArchive().getIndex();
Collection<AnnotationInstance> mongoClientAnnotations = indexView.getAnnotations(MONGO_CLIENT_ANNOTATION);
for (AnnotationInstance annotation : mongoClientAnnotations) {
values.add(annotation.value().asString());
}
addMongoClientNameValues(LEGACY_MONGO_CLIENT_ANNOTATION, indexView, values);
addMongoClientNameValues(MONGO_CLIENT_ANNOTATION, indexView, values);
for (String value : values) {
mongoClientName.produce(new MongoClientNameBuildItem(value));
}
}

private void addMongoClientNameValues(DotName annotationName, IndexView indexView, Set<String> values) {
Collection<AnnotationInstance> mongoClientAnnotations = indexView.getAnnotations(annotationName);
for (AnnotationInstance annotation : mongoClientAnnotations) {
values.add(annotation.value().asString());
}
}

@BuildStep
FeatureBuildItem feature() {
return new FeatureBuildItem(Feature.MONGODB_CLIENT);
Expand Down Expand Up @@ -139,6 +147,8 @@ void build(
BuildProducer<AdditionalBeanBuildItem> additionalBeans) {

// add the @MongoClientName class otherwise it won't registered as a qualifier
additionalBeans.produce(
AdditionalBeanBuildItem.builder().addBeanClass(io.quarkus.mongodb.runtime.MongoClientName.class).build());
additionalBeans.produce(AdditionalBeanBuildItem.builder().addBeanClass(MongoClientName.class).build());

List<ConnectionPoolListener> poolListenerList = connectionPoolListenerProvider.stream()
Expand Down Expand Up @@ -260,6 +270,7 @@ private SyntheticBeanBuildItem applyCommonBeanConfig(boolean makeUnremovable, St
configurator.addQualifier().annotation(DotNames.NAMED).addValue("value", namedQualifier).done();
if (addMongoClientQualifier) {
configurator.addQualifier().annotation(MONGO_CLIENT_ANNOTATION).addValue("value", clientName).done();
configurator.addQualifier().annotation(LEGACY_MONGO_CLIENT_ANNOTATION).addValue("value", clientName).done();
}
}
return configurator.done();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package io.quarkus.mongodb;

import static org.assertj.core.api.Assertions.assertThat;

import java.lang.annotation.Annotation;

import javax.enterprise.inject.Default;
import javax.inject.Inject;

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import com.mongodb.client.MongoClient;

import io.quarkus.arc.Arc;
import io.quarkus.arc.InjectableBean;
import io.quarkus.arc.InstanceHandle;
import io.quarkus.mongodb.runtime.MongoClientName;
import io.quarkus.test.QuarkusUnitTest;

public class LegacyNamedMongoClientConfigTest extends MongoWithReplicasTestBase {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class).addClasses(MongoTestBase.class))
.withConfigurationResource("application-named-mongoclient.properties");

@Inject
@MongoClientName("cluster1")
MongoClient client;

@Inject
@MongoClientName("cluster2")
MongoClient client2;

@AfterEach
void cleanup() {
if (client != null) {
client.close();
}
if (client2 != null) {
client2.close();
}
}

@Test
public void testNamedDataSourceInjection() {
assertThat(client.listDatabases().first()).isNotEmpty();
assertThat(client2.listDatabases().first()).isNotEmpty();

assertNoDefaultClient();
}

private void assertNoDefaultClient() {
boolean hasDefault = false;
for (InstanceHandle<MongoClient> handle : Arc.container().select(MongoClient.class).handles()) {
InjectableBean<MongoClient> bean = handle.getBean();
for (Annotation qualifier : bean.getQualifiers()) {
if (qualifier.annotationType().equals(Default.class)) {
hasDefault = true;
}
}
}
Assertions.assertFalse(hasDefault,
"The default mongo client should not have been present as it is not used in any injection point");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package io.quarkus.mongodb;

import static org.assertj.core.api.Assertions.assertThat;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

import javax.enterprise.inject.Default;
import javax.inject.Inject;

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import com.mongodb.reactivestreams.client.MongoClient;
import com.mongodb.reactivestreams.client.internal.MongoClientImpl;

import io.quarkus.arc.Arc;
import io.quarkus.arc.InjectableBean;
import io.quarkus.arc.InstanceHandle;
import io.quarkus.mongodb.impl.ReactiveMongoClientImpl;
import io.quarkus.mongodb.reactive.ReactiveMongoClient;
import io.quarkus.mongodb.runtime.MongoClientName;
import io.quarkus.test.QuarkusUnitTest;

public class LegacyNamedReactiveMongoClientConfigTest extends MongoWithReplicasTestBase {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class).addClasses(MongoTestBase.class))
.withConfigurationResource("application-named-mongoclient.properties");

@Inject
@MongoClientName("cluster1")
ReactiveMongoClient client;

@Inject
@MongoClientName("cluster2")
ReactiveMongoClient client2;

@AfterEach
void cleanup() {
if (client != null) {
client.close();
}
if (client2 != null) {
client2.close();
}
}

@Test
public void testNamedDataSourceInjection() {
assertProperConnection(client, 27018);
assertProperConnection(client2, 27019);

assertThat(client.listDatabases().collectItems().first().await().indefinitely()).isNotEmpty();
assertThat(client2.listDatabases().collectItems().first().await().indefinitely()).isNotEmpty();

assertNoDefaultClient();
}

private void assertProperConnection(ReactiveMongoClient client, int expectedPort) {
assertThat(client).isInstanceOfSatisfying(ReactiveMongoClientImpl.class, rc -> {
Field mongoClientField;
try {
mongoClientField = ReactiveMongoClientImpl.class.getDeclaredField("client");
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
mongoClientField.setAccessible(true);
MongoClient c;
try {
c = (MongoClientImpl) mongoClientField.get(rc);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
assertThat(c.getClusterDescription().getClusterSettings().getHosts()).hasOnlyOneElementSatisfying(sa -> {
assertThat(sa.getPort()).isEqualTo(expectedPort);
});
});
}

private void assertNoDefaultClient() {
boolean hasDefault = false;
for (InstanceHandle<ReactiveMongoClient> handle : Arc.container().select(ReactiveMongoClient.class).handles()) {
InjectableBean<ReactiveMongoClient> bean = handle.getBean();
for (Annotation qualifier : bean.getQualifiers()) {
if (qualifier.annotationType().equals(Default.class)) {
hasDefault = true;
}
}
}
Assertions.assertFalse(hasDefault,
"The default reactive mongo client should not have been present as it is not used in any injection point");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import io.quarkus.arc.Arc;
import io.quarkus.arc.InjectableBean;
import io.quarkus.arc.InstanceHandle;
import io.quarkus.mongodb.runtime.MongoClientName;
import io.quarkus.test.QuarkusUnitTest;

public class NamedMongoClientConfigTest extends MongoWithReplicasTestBase {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import io.quarkus.arc.InstanceHandle;
import io.quarkus.mongodb.impl.ReactiveMongoClientImpl;
import io.quarkus.mongodb.reactive.ReactiveMongoClient;
import io.quarkus.mongodb.runtime.MongoClientName;
import io.quarkus.test.QuarkusUnitTest;

public class NamedReactiveMongoClientConfigTest extends MongoWithReplicasTestBase {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package io.quarkus.mongodb;

import javax.inject.Qualifier;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Marker annotation to select mongo connection of cluster configuration
* Use name parameter to select it
*
* For example, if a mongo connection is configured like so in {@code application.properties}:
*
* <pre>
* quarkus.mongodb.cluster1.connection-string=mongodb://localhost:27018
* </pre>
*
* Then to inject the proper {@code MongoClient}, you would need to use {@code MongoClientName} like so:
*
* <pre>
* &#64Inject
* &#64MongoClientName("cluster1")
* MongoClient client;
* </pre>
*/
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
@Retention(RUNTIME)
@Documented
@Qualifier
public @interface MongoClientName {
/**
* Specify the cluster name of the connection.
*
* @return the value
*/
String value() default "";
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@
/**
* Marker annotation to select mongo connection of cluster configuration
* Use name parameter to select it
*
* @deprecated in favor of {@link io.quarkus.mongodb.MongoClientName}
*/
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
@Retention(RUNTIME)
@Documented
@Qualifier
@Deprecated
public @interface MongoClientName {
/**
* Specify the cluster name of the connection.
Expand Down

0 comments on commit 45af8ef

Please sign in to comment.