From 15e2f328234c7e7afe550e90f1936f076269020e Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Mon, 24 Feb 2020 15:12:39 +0200 Subject: [PATCH] Fix broken MongoClientBuildItem support Fixes: #7378 --- .../deployment/MongoClientNameBuildItem.java | 20 +++ .../deployment/MongoClientProcessor.java | 134 ++++++++++++------ .../MongoConnectionNameBuildItem.java | 19 +++ .../MongoUnremovableClientsBuildItem.java | 10 ++ .../MongoClientBuildItemConsumerTest.java | 52 +++++++ .../io/quarkus/mongodb/MongoMetricsTest.java | 8 ++ .../mongodb/runtime/MongoClientRecorder.java | 20 ++- .../mongodb/runtime/MongodbConfig.java | 5 +- 8 files changed, 216 insertions(+), 52 deletions(-) create mode 100644 extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoClientNameBuildItem.java create mode 100644 extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoConnectionNameBuildItem.java create mode 100644 extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoUnremovableClientsBuildItem.java create mode 100644 extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/MongoClientBuildItemConsumerTest.java diff --git a/extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoClientNameBuildItem.java b/extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoClientNameBuildItem.java new file mode 100644 index 0000000000000..06537b0259221 --- /dev/null +++ b/extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoClientNameBuildItem.java @@ -0,0 +1,20 @@ +package io.quarkus.mongodb.deployment; + +import io.quarkus.builder.item.MultiBuildItem; +import io.quarkus.mongodb.runtime.MongoClientName; + +/** + * Represents the values of the {@link MongoClientName} + */ +final class MongoClientNameBuildItem extends MultiBuildItem { + + private final String name; + + public MongoClientNameBuildItem(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoClientProcessor.java b/extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoClientProcessor.java index 2004e43f2c00f..24fcbf3db905d 100644 --- a/extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoClientProcessor.java +++ b/extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoClientProcessor.java @@ -7,7 +7,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; -import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -37,8 +37,10 @@ import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.annotations.Record; +import io.quarkus.deployment.annotations.Weak; import io.quarkus.deployment.builditem.ApplicationArchivesBuildItem; import io.quarkus.deployment.builditem.CombinedIndexBuildItem; +import io.quarkus.deployment.builditem.ConfigurationBuildItem; import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem; import io.quarkus.deployment.builditem.FeatureBuildItem; import io.quarkus.deployment.builditem.SslNativeConfigBuildItem; @@ -73,23 +75,6 @@ UnremovableBeanBuildItem markBeansAsUnremovable() { return new UnremovableBeanBuildItem(new UnremovableBeanBuildItem.BeanTypeExclusion(UNREMOVABLE_BEAN)); } - @Record(RUNTIME_INIT) - @BuildStep - void configureRuntimeProperties(MongoClientRecorder recorder, - CodecProviderBuildItem codecProvider, - BsonDiscriminatorBuildItem bsonDiscriminator, - MongodbConfig config, - List connectionPoolListenerProvider) { - List poolListenerList = connectionPoolListenerProvider.stream() - .map(MongoConnectionPoolListenerBuildItem::getConnectionPoolListener) - .collect(Collectors.toList()); - - recorder.configureRuntimeProperties(codecProvider.getCodecProviderClassNames(), - bsonDiscriminator.getBsonDiscriminatorClassNames(), - config, - poolListenerList); - } - @BuildStep CodecProviderBuildItem collectCodecProviders(CombinedIndexBuildItem indexBuildItem) { Collection codecProviderClasses = indexBuildItem.getIndex() @@ -120,6 +105,20 @@ List addCodecsAndDiscriminatorsToNative(CodecProviderB .collect(Collectors.toList()); } + @BuildStep + public void mongoClientNames(ApplicationArchivesBuildItem applicationArchivesBuildItem, + BuildProducer mongoClientName) { + Set values = new HashSet<>(); + IndexView indexView = applicationArchivesBuildItem.getRootArchive().getIndex(); + Collection mongoClientAnnotations = indexView.getAnnotations(MONGOCLIENT_ANNOTATION); + for (AnnotationInstance annotation : mongoClientAnnotations) { + values.add(annotation.value().asString()); + } + for (String value : values) { + mongoClientName.produce(new MongoClientNameBuildItem(value)); + } + } + /** * Create a producer bean managing the lifecycle of the MongoClient. *

@@ -166,17 +165,10 @@ List addCodecsAndDiscriminatorsToNative(CodecProviderB * } * */ - private void createMongoClientProducerBean(ApplicationArchivesBuildItem applicationArchivesBuildItem, + private void createMongoClientProducerBean(List mongoClientNames, BuildProducer generatedBean, - String mongoClientProducerClassName) { + String mongoClientProducerClassName, boolean makeUnremovable) { - Set mongoClientNames = new HashSet<>(); - IndexView indexView = applicationArchivesBuildItem.getRootArchive().getIndex(); - Collection mongoClientAnnotations = indexView.getAnnotations(MONGOCLIENT_ANNOTATION); - for (AnnotationInstance annotation : mongoClientAnnotations) { - String mongoClientName = annotation.value().asString(); - mongoClientNames.add(mongoClientName); - } ClassOutput classOutput = new GeneratedBeanGizmoAdaptor(generatedBean); try (ClassCreator classCreator = ClassCreator.builder().classOutput(classOutput) @@ -184,13 +176,15 @@ private void createMongoClientProducerBean(ApplicationArchivesBuildItem applicat .superClass(AbstractMongoClientProducer.class) .build()) { classCreator.addAnnotation(ApplicationScoped.class); - classCreator.addAnnotation(Unremovable.class); try (MethodCreator defaultMongoClientMethodCreator = classCreator.getMethodCreator("createDefaultMongoClient", MongoClient.class)) { defaultMongoClientMethodCreator.addAnnotation(ApplicationScoped.class); defaultMongoClientMethodCreator.addAnnotation(Produces.class); defaultMongoClientMethodCreator.addAnnotation(Default.class); + if (makeUnremovable) { + defaultMongoClientMethodCreator.addAnnotation(Unremovable.class); + } ResultHandle mongoClientConfig = defaultMongoClientMethodCreator.invokeVirtualMethod( MethodDescriptor.ofMethod(AbstractMongoClientProducer.class, "getDefaultMongoClientConfig", @@ -208,7 +202,7 @@ private void createMongoClientProducerBean(ApplicationArchivesBuildItem applicat mongoClientConfig, defaultMongoClientNameRH)); } - // Default Legacy reactive client. + // Default Legacy reactive client - this is never made unremovable since it's not part of MongoClientBuildItem try (MethodCreator defaultReactiveMongoClientMethodCreator = classCreator.getMethodCreator( "createDefaultLegacyReactiveMongoClient", ReactiveMongoClient.class)) { @@ -239,6 +233,9 @@ private void createMongoClientProducerBean(ApplicationArchivesBuildItem applicat defaultReactiveMongoClientMethodCreator.addAnnotation(ApplicationScoped.class); defaultReactiveMongoClientMethodCreator.addAnnotation(Produces.class); defaultReactiveMongoClientMethodCreator.addAnnotation(Default.class); + if (makeUnremovable) { + defaultReactiveMongoClientMethodCreator.addAnnotation(Unremovable.class); + } ResultHandle mongoReactiveClientConfig = defaultReactiveMongoClientMethodCreator.invokeVirtualMethod( MethodDescriptor.ofMethod(AbstractMongoClientProducer.class, "getDefaultMongoClientConfig", @@ -256,7 +253,8 @@ private void createMongoClientProducerBean(ApplicationArchivesBuildItem applicat mongoReactiveClientConfig, defaultReactiveMongoClientNameRH)); } - for (String namedMongoClientName : mongoClientNames) { + for (MongoClientNameBuildItem bi : mongoClientNames) { + String namedMongoClientName = bi.getName(); try (MethodCreator namedMongoClientMethodCreator = classCreator.getMethodCreator( "createNamedMongoClient_" + HashUtil.sha1(namedMongoClientName), MongoClient.class)) { @@ -268,6 +266,9 @@ private void createMongoClientProducerBean(ApplicationArchivesBuildItem applicat .addAnnotation(AnnotationInstance.create(MONGOCLIENT_ANNOTATION, null, new AnnotationValue[] { AnnotationValue.createStringValue("value", namedMongoClientName) })); + if (makeUnremovable) { + namedMongoClientMethodCreator.addAnnotation(Unremovable.class); + } ResultHandle namedMongoClientNameRH = namedMongoClientMethodCreator.load(namedMongoClientName); @@ -285,7 +286,7 @@ private void createMongoClientProducerBean(ApplicationArchivesBuildItem applicat namedMongoClientConfig, namedMongoClientNameRH)); } - // Legacy reactive client + // Legacy reactive client - this is never made unremovable since it's not part of MongoClientBuildItem try (MethodCreator namedReactiveMongoClientMethodCreator = classCreator.getMethodCreator( "createNamedLegacyReactiveMongoClient_" + HashUtil.sha1(namedMongoClientName), ReactiveMongoClient.class)) { @@ -325,11 +326,15 @@ private void createMongoClientProducerBean(ApplicationArchivesBuildItem applicat namedReactiveMongoClientMethodCreator.addAnnotation(Produces.class); namedReactiveMongoClientMethodCreator.addAnnotation(AnnotationInstance.create(DotNames.NAMED, null, new AnnotationValue[] { - AnnotationValue.createStringValue("value", namedMongoClientName + "reactive") })); + AnnotationValue.createStringValue("value", + namedMongoClientName + MongoClientRecorder.REACTIVE_CLIENT_NAME_SUFFIX) })); namedReactiveMongoClientMethodCreator .addAnnotation(AnnotationInstance.create(MONGOCLIENT_ANNOTATION, null, new AnnotationValue[] { AnnotationValue.createStringValue("value", namedMongoClientName) })); + if (makeUnremovable) { + namedReactiveMongoClientMethodCreator.addAnnotation(Unremovable.class); + } ResultHandle namedReactiveMongoClientNameRH = namedReactiveMongoClientMethodCreator .load(namedMongoClientName); @@ -355,10 +360,11 @@ private void createMongoClientProducerBean(ApplicationArchivesBuildItem applicat @Record(STATIC_INIT) @BuildStep BeanContainerListenerBuildItem build( - ApplicationArchivesBuildItem applicationArchivesBuildItem, + List mongoClientNames, RecorderContext recorderContext, MongoClientRecorder recorder, BuildProducer feature, + Optional mongoUnremovableClientsBuildItem, SslNativeConfigBuildItem sslNativeConfig, BuildProducer sslNativeSupport, BuildProducer generatedBean) throws Exception { @@ -366,7 +372,8 @@ BeanContainerListenerBuildItem build( sslNativeSupport.produce(new ExtensionSslNativeSupportBuildItem(FeatureBuildItem.MONGODB_CLIENT)); String mongoClientProducerClassName = getMongoClientProducerClassName(); - createMongoClientProducerBean(applicationArchivesBuildItem, generatedBean, mongoClientProducerClassName); + createMongoClientProducerBean(mongoClientNames, generatedBean, mongoClientProducerClassName, + mongoUnremovableClientsBuildItem.isPresent()); return new BeanContainerListenerBuildItem(recorder.addMongoClient( (Class) recorderContext.classProxy(mongoClientProducerClassName), @@ -375,21 +382,54 @@ BeanContainerListenerBuildItem build( @Record(RUNTIME_INIT) @BuildStep - void build(MongoClientRecorder recorder, BuildProducer mongoClients, MongodbConfig config) { - if (config.mongoClientConfigs != null && !config.mongoClientConfigs.isEmpty()) { - for (Map.Entry namedDataSourceEntry : config.mongoClientConfigs.entrySet()) { - String name = namedDataSourceEntry.getKey(); - mongoClients - .produce(new MongoClientBuildItem(recorder.getClient(name), recorder.getReactiveClient(name), name)); - } + void configureRuntimePropertiesAndBuildClients(MongoClientRecorder recorder, + CodecProviderBuildItem codecProvider, BsonDiscriminatorBuildItem bsonDiscriminator, + List connectionPoolListenerProvider, + List mongoClientNames, + MongodbConfig mongodbConfig, ConfigurationBuildItem config, + BuildProducer mongoConnections) { + + List poolListenerList = connectionPoolListenerProvider.stream() + .map(MongoConnectionPoolListenerBuildItem::getConnectionPoolListener) + .collect(Collectors.toList()); + + recorder.configureRuntimeProperties(codecProvider.getCodecProviderClassNames(), + bsonDiscriminator.getBsonDiscriminatorClassNames(), + mongodbConfig, + poolListenerList); + + mongoConnections.produce(new MongoConnectionNameBuildItem(MongoClientRecorder.DEFAULT_MONGOCLIENT_NAME)); + for (MongoClientNameBuildItem bi : mongoClientNames) { + mongoConnections.produce(new MongoConnectionNameBuildItem(bi.getName())); } - if (config.defaultMongoClientConfig != null - && (config.defaultMongoClientConfig.connectionString.isPresent() - || !config.defaultMongoClientConfig.hosts.isEmpty())) { - mongoClients.produce(new MongoClientBuildItem(recorder.getClient(MongoClientRecorder.DEFAULT_MONGOCLIENT_NAME), - recorder.getReactiveClient(MongoClientRecorder.DEFAULT_MONGOCLIENT_NAME), - MongoClientRecorder.DEFAULT_MONGOCLIENT_NAME)); + } + + /** + * We only create the bytecode that returns Mongo clients when MongoClientBuildItem is used + * This is an optimization in order to avoid having to make all mongo client beans unremovable + * by default. + * When the build consumes MongoClientBuildItem, then we need to make the all clients unremovable + * by default, because they are not referenced by CDI injection points + */ + @BuildStep + @Record(value = RUNTIME_INIT, optional = true) + List mongoClients(MongoClientRecorder recorder, List mongoConnections) { + List result = new ArrayList<>(mongoConnections.size()); + for (MongoConnectionNameBuildItem mongoConnection : mongoConnections) { + String name = mongoConnection.getName(); + result.add(new MongoClientBuildItem(recorder.getClient(name), recorder.getReactiveClient(name), name)); } + return result; + } + + /** + * When MongoClientBuildItem is actually consumed by the build, then we need to make all the mongo beans unremovable + * because they can be potentially used by the consumers + */ + @BuildStep + @Weak + MongoUnremovableClientsBuildItem unremovable(@SuppressWarnings("unused") BuildProducer producer) { + return new MongoUnremovableClientsBuildItem(); } private String getMongoClientProducerClassName() { diff --git a/extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoConnectionNameBuildItem.java b/extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoConnectionNameBuildItem.java new file mode 100644 index 0000000000000..7cd1a3e9c7572 --- /dev/null +++ b/extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoConnectionNameBuildItem.java @@ -0,0 +1,19 @@ +package io.quarkus.mongodb.deployment; + +import io.quarkus.builder.item.MultiBuildItem; + +/** + * Holds a Mongo connection name + */ +final class MongoConnectionNameBuildItem extends MultiBuildItem { + + private final String name; + + public MongoConnectionNameBuildItem(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoUnremovableClientsBuildItem.java b/extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoUnremovableClientsBuildItem.java new file mode 100644 index 0000000000000..063f3a0a4ec1b --- /dev/null +++ b/extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoUnremovableClientsBuildItem.java @@ -0,0 +1,10 @@ +package io.quarkus.mongodb.deployment; + +import io.quarkus.builder.item.SimpleBuildItem; + +/** + * If generated, all the Mongo clients need to be unremovable + */ +final class MongoUnremovableClientsBuildItem extends SimpleBuildItem { + +} diff --git a/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/MongoClientBuildItemConsumerTest.java b/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/MongoClientBuildItemConsumerTest.java new file mode 100644 index 0000000000000..11b2c63afe746 --- /dev/null +++ b/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/MongoClientBuildItemConsumerTest.java @@ -0,0 +1,52 @@ +package io.quarkus.mongodb; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.function.Consumer; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +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.builder.BuildChainBuilder; +import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.mongodb.deployment.MongoClientBuildItem; +import io.quarkus.mongodb.reactive.ReactiveMongoClient; +import io.quarkus.test.QuarkusUnitTest; + +public class MongoClientBuildItemConsumerTest { + + @RegisterExtension + static QuarkusUnitTest runner = new QuarkusUnitTest() + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class).addClasses(MongoTestBase.class)) + .withConfigurationResource("default-mongoclient.properties") + .addBuildChainCustomizer(buildCustomizer()); + + @Test + public void testContainerHasBeans() { + assertThat(Arc.container().instance(MongoClient.class).get()).isNotNull(); + assertThat(Arc.container().instance(ReactiveMongoClient.class).get()).isNotNull(); + // this one hasn't been made un-removeable because it's not used in MongoClientBuildItem + assertThat(Arc.container().instance(io.quarkus.mongodb.ReactiveMongoClient.class).get()).isNull(); + } + + protected static Consumer buildCustomizer() { + return new Consumer() { + // This represents the extension. + @Override + public void accept(BuildChainBuilder builder) { + builder.addBuildStep(context -> { + List mongoClientBuildItems = context.consumeMulti(MongoClientBuildItem.class); + context.produce(new FeatureBuildItem("dummy")); + }).consumes(MongoClientBuildItem.class) + .produces(FeatureBuildItem.class) + .build(); + } + }; + } +} diff --git a/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/MongoMetricsTest.java b/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/MongoMetricsTest.java index a951a4d76102f..4baae9ebbb947 100644 --- a/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/MongoMetricsTest.java +++ b/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/MongoMetricsTest.java @@ -1,5 +1,6 @@ package io.quarkus.mongodb; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; @@ -18,7 +19,9 @@ import com.mongodb.client.MongoClient; +import io.quarkus.arc.Arc; import io.quarkus.mongodb.metrics.ConnectionPoolGauge; +import io.quarkus.mongodb.reactive.ReactiveMongoClient; import io.quarkus.test.QuarkusUnitTest; public class MongoMetricsTest extends MongoTestBase { @@ -56,6 +59,11 @@ void testMetricsInitialization() { client.close(); assertEquals(0L, getGaugeValueOrNull("mongodb.connection-pool.size", getTags())); assertEquals(0L, getGaugeValueOrNull("mongodb.connection-pool.checked-out-count", getTags())); + + // doing this here instead of in another method in order to avoid messing with the initialization stats + assertThat(Arc.container().instance(MongoClient.class).get()).isNotNull(); + assertThat(Arc.container().instance(ReactiveMongoClient.class).get()).isNull(); + assertThat(Arc.container().instance(io.quarkus.mongodb.ReactiveMongoClient.class).get()).isNull(); } private Long getGaugeValueOrNull(String metricName, Tag[] tags) { diff --git a/extensions/mongodb-client/runtime/src/main/java/io/quarkus/mongodb/runtime/MongoClientRecorder.java b/extensions/mongodb-client/runtime/src/main/java/io/quarkus/mongodb/runtime/MongoClientRecorder.java index 2298379976418..6e69bffe17285 100644 --- a/extensions/mongodb-client/runtime/src/main/java/io/quarkus/mongodb/runtime/MongoClientRecorder.java +++ b/extensions/mongodb-client/runtime/src/main/java/io/quarkus/mongodb/runtime/MongoClientRecorder.java @@ -2,6 +2,10 @@ import java.util.List; +import javax.enterprise.inject.Default; +import javax.enterprise.inject.literal.NamedLiteral; +import javax.enterprise.util.AnnotationLiteral; + import com.mongodb.client.MongoClient; import com.mongodb.event.ConnectionPoolListener; @@ -16,6 +20,7 @@ public class MongoClientRecorder { public static final String DEFAULT_MONGOCLIENT_NAME = ""; + public static final String REACTIVE_CLIENT_NAME_SUFFIX = "reactive"; public BeanContainerListener addMongoClient( Class mongoClientProducerClass, @@ -46,12 +51,19 @@ public void configureRuntimeProperties(List codecs, List bsonDis } public RuntimeValue getClient(String name) { - AbstractMongoClientProducer producer = Arc.container().instance(AbstractMongoClientProducer.class).get(); - return new RuntimeValue<>(producer.getClient(name)); + return new RuntimeValue<>(Arc.container().instance(MongoClient.class, literal(name)).get()); } public RuntimeValue getReactiveClient(String name) { - AbstractMongoClientProducer producer = Arc.container().instance(AbstractMongoClientProducer.class).get(); - return new RuntimeValue<>(producer.getReactiveClient(name)); + return new RuntimeValue<>( + Arc.container().instance(ReactiveMongoClient.class, literal(name + REACTIVE_CLIENT_NAME_SUFFIX)).get()); + } + + @SuppressWarnings("rawtypes") + private AnnotationLiteral literal(String name) { + if (name.startsWith(DEFAULT_MONGOCLIENT_NAME)) { + return Default.Literal.INSTANCE; + } + return NamedLiteral.of(name); } } diff --git a/extensions/mongodb-client/runtime/src/main/java/io/quarkus/mongodb/runtime/MongodbConfig.java b/extensions/mongodb-client/runtime/src/main/java/io/quarkus/mongodb/runtime/MongodbConfig.java index 8b7b72596a525..6786aa59011a8 100644 --- a/extensions/mongodb-client/runtime/src/main/java/io/quarkus/mongodb/runtime/MongodbConfig.java +++ b/extensions/mongodb-client/runtime/src/main/java/io/quarkus/mongodb/runtime/MongodbConfig.java @@ -6,8 +6,11 @@ import io.quarkus.runtime.annotations.ConfigPhase; import io.quarkus.runtime.annotations.ConfigRoot; -@ConfigRoot(name = "mongodb", phase = ConfigPhase.RUN_TIME) +@ConfigRoot(name = MongodbConfig.CONFIG_NAME, phase = ConfigPhase.RUN_TIME) public class MongodbConfig { + + public static final String CONFIG_NAME = "mongodb"; + /** * The default mongo client connection. */