Create spring-boot-data-mongodb module

This commit is contained in:
Andy Wilkinson
2025-03-26 14:40:05 +00:00
committed by Phillip Webb
parent 254f901f14
commit 9434f7d05b
47 changed files with 167 additions and 296 deletions

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure;
import com.mongodb.client.MongoClient;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.mongodb.autoconfigure.MongoAutoConfiguration;
import org.springframework.boot.mongodb.autoconfigure.MongoConnectionDetails;
import org.springframework.boot.mongodb.autoconfigure.MongoProperties;
import org.springframework.boot.mongodb.autoconfigure.PropertiesMongoConnectionDetails;
import org.springframework.boot.ssl.SslBundles;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's mongo support.
* <p>
* Registers a {@link MongoTemplate} and {@link GridFsTemplate} beans if no other beans of
* the same type are configured.
* <p>
* Honors the {@literal spring.data.mongodb.database} property if set, otherwise connects
* to the {@literal test} database.
*
* @author Dave Syer
* @author Oliver Gierke
* @author Josh Long
* @author Phillip Webb
* @author Eddú Meléndez
* @author Stephane Nicoll
* @author Christoph Strobl
* @since 4.0.0
*/
@AutoConfiguration(after = MongoAutoConfiguration.class)
@ConditionalOnClass({ MongoClient.class, MongoTemplate.class })
@EnableConfigurationProperties(MongoProperties.class)
@Import({ MongoDataConfiguration.class, MongoDatabaseFactoryConfiguration.class,
MongoDatabaseFactoryDependentConfiguration.class })
public class MongoDataAutoConfiguration {
@Bean
@ConditionalOnMissingBean(MongoConnectionDetails.class)
PropertiesMongoConnectionDetails mongoConnectionDetails(MongoProperties properties,
ObjectProvider<SslBundles> sslBundles) {
return new PropertiesMongoConnectionDetails(properties, sslBundles.getIfAvailable());
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure;
import java.util.Collections;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.domain.EntityScanner;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.boot.mongodb.autoconfigure.MongoProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mapping.model.FieldNamingStrategy;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.MongoManagedTypes;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
/**
* Base configuration class for Spring Data's mongo support.
*
* @author Madhura Bhave
* @author Artsiom Yudovin
* @author Scott Fredericks
*/
@Configuration(proxyBeanMethods = false)
class MongoDataConfiguration {
@Bean
@ConditionalOnMissingBean
static MongoManagedTypes mongoManagedTypes(ApplicationContext applicationContext) throws ClassNotFoundException {
return MongoManagedTypes.fromIterable(new EntityScanner(applicationContext).scan(Document.class));
}
@Bean
@ConditionalOnMissingBean
MongoMappingContext mongoMappingContext(MongoProperties properties, MongoCustomConversions conversions,
MongoManagedTypes managedTypes) {
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
MongoMappingContext context = new MongoMappingContext();
map.from(properties.isAutoIndexCreation()).to(context::setAutoIndexCreation);
context.setManagedTypes(managedTypes);
Class<?> strategyClass = properties.getFieldNamingStrategy();
if (strategyClass != null) {
context.setFieldNamingStrategy((FieldNamingStrategy) BeanUtils.instantiateClass(strategyClass));
}
context.setSimpleTypeHolder(conversions.getSimpleTypeHolder());
return context;
}
@Bean
@ConditionalOnMissingBean
MongoCustomConversions mongoCustomConversions() {
return new MongoCustomConversions(Collections.emptyList());
}
@Bean
@ConditionalOnMissingBean(MongoConverter.class)
MappingMongoConverter mappingMongoConverter(ObjectProvider<MongoDatabaseFactory> factory,
MongoMappingContext context, MongoCustomConversions conversions) {
MongoDatabaseFactory mongoDatabaseFactory = factory.getIfAvailable();
DbRefResolver dbRefResolver = (mongoDatabaseFactory != null) ? new DefaultDbRefResolver(mongoDatabaseFactory)
: NoOpDbRefResolver.INSTANCE;
MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
mappingConverter.setCustomConversions(conversions);
return mappingConverter;
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure;
import com.mongodb.client.MongoClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.mongodb.autoconfigure.MongoConnectionDetails;
import org.springframework.boot.mongodb.autoconfigure.MongoProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoDatabaseFactorySupport;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
/**
* Configuration for a {@link MongoDatabaseFactory}.
*
* @author Andy Wilkinson
* @author Stephane Nicoll
* @author Moritz Halbritter
* @author Phillip Webb
* @author Scott Frederick
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(MongoDatabaseFactory.class)
@ConditionalOnSingleCandidate(MongoClient.class)
class MongoDatabaseFactoryConfiguration {
@Bean
MongoDatabaseFactorySupport<?> mongoDatabaseFactory(MongoClient mongoClient, MongoProperties properties,
MongoConnectionDetails connectionDetails) {
String database = properties.getDatabase();
if (database == null) {
database = connectionDetails.getConnectionString().getDatabase();
}
return new SimpleMongoClientDatabaseFactory(mongoClient, database);
}
}

View File

@@ -0,0 +1,121 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure;
import com.mongodb.ClientSessionOptions;
import com.mongodb.client.ClientSession;
import com.mongodb.client.MongoDatabase;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.mongodb.autoconfigure.MongoConnectionDetails;
import org.springframework.boot.mongodb.autoconfigure.MongoConnectionDetails.GridFs;
import org.springframework.boot.mongodb.autoconfigure.MongoProperties;
import org.springframework.boot.mongodb.autoconfigure.MongoProperties.Gridfs;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.gridfs.GridFsOperations;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Configuration for Mongo-related beans that depend on a {@link MongoDatabaseFactory}.
*
* @author Andy Wilkinson
* @author Moritz Halbritter
* @author Phillip Webb
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(MongoDatabaseFactory.class)
class MongoDatabaseFactoryDependentConfiguration {
@Bean
@ConditionalOnMissingBean(MongoOperations.class)
MongoTemplate mongoTemplate(MongoDatabaseFactory factory, MongoConverter converter) {
return new MongoTemplate(factory, converter);
}
@Bean
@ConditionalOnMissingBean(GridFsOperations.class)
GridFsTemplate gridFsTemplate(MongoProperties properties, MongoDatabaseFactory factory, MongoTemplate mongoTemplate,
MongoConnectionDetails connectionDetails) {
return new GridFsTemplate(new GridFsMongoDatabaseFactory(factory, connectionDetails),
mongoTemplate.getConverter(),
(connectionDetails.getGridFs() != null) ? connectionDetails.getGridFs().getBucket() : null);
}
/**
* {@link MongoDatabaseFactory} decorator to respect {@link Gridfs#getDatabase()} or
* {@link GridFs#getGridFs()} from the {@link MongoConnectionDetails} if set.
*/
static class GridFsMongoDatabaseFactory implements MongoDatabaseFactory {
private final MongoDatabaseFactory mongoDatabaseFactory;
private final MongoConnectionDetails connectionDetails;
GridFsMongoDatabaseFactory(MongoDatabaseFactory mongoDatabaseFactory,
MongoConnectionDetails connectionDetails) {
Assert.notNull(mongoDatabaseFactory, "'mongoDatabaseFactory' must not be null");
Assert.notNull(connectionDetails, "'connectionDetails' must not be null");
this.mongoDatabaseFactory = mongoDatabaseFactory;
this.connectionDetails = connectionDetails;
}
@Override
public MongoDatabase getMongoDatabase() throws DataAccessException {
String gridFsDatabase = getGridFsDatabase(this.connectionDetails);
if (StringUtils.hasText(gridFsDatabase)) {
return this.mongoDatabaseFactory.getMongoDatabase(gridFsDatabase);
}
return this.mongoDatabaseFactory.getMongoDatabase();
}
@Override
public MongoDatabase getMongoDatabase(String dbName) throws DataAccessException {
return this.mongoDatabaseFactory.getMongoDatabase(dbName);
}
@Override
public PersistenceExceptionTranslator getExceptionTranslator() {
return this.mongoDatabaseFactory.getExceptionTranslator();
}
@Override
public ClientSession getSession(ClientSessionOptions options) {
return this.mongoDatabaseFactory.getSession(options);
}
@Override
public MongoDatabaseFactory withSession(ClientSession session) {
return this.mongoDatabaseFactory.withSession(session);
}
private String getGridFsDatabase(MongoConnectionDetails connectionDetails) {
return (connectionDetails.getGridFs() != null) ? connectionDetails.getGridFs().getDatabase() : null;
}
}
}

View File

@@ -0,0 +1,188 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure;
import java.util.Optional;
import com.mongodb.ClientSessionOptions;
import com.mongodb.reactivestreams.client.ClientSession;
import com.mongodb.reactivestreams.client.MongoClient;
import com.mongodb.reactivestreams.client.MongoDatabase;
import org.bson.codecs.Codec;
import org.bson.codecs.configuration.CodecRegistry;
import reactor.core.publisher.Mono;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.mongodb.autoconfigure.MongoConnectionDetails;
import org.springframework.boot.mongodb.autoconfigure.MongoConnectionDetails.GridFs;
import org.springframework.boot.mongodb.autoconfigure.MongoProperties;
import org.springframework.boot.mongodb.autoconfigure.MongoReactiveAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory;
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.gridfs.ReactiveGridFsOperations;
import org.springframework.data.mongodb.gridfs.ReactiveGridFsTemplate;
import org.springframework.util.StringUtils;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's reactive mongo
* support.
* <p>
* Registers a {@link ReactiveMongoTemplate} bean if no other bean of the same type is
* configured.
*
* @author Mark Paluch
* @author Artsiom Yudovin
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
* @author Scott Frederick
* @since 4.0.0
*/
@AutoConfiguration(after = MongoReactiveAutoConfiguration.class)
@ConditionalOnClass({ MongoClient.class, ReactiveMongoTemplate.class })
@ConditionalOnBean(MongoClient.class)
@EnableConfigurationProperties(MongoProperties.class)
@Import(MongoDataConfiguration.class)
public class MongoReactiveDataAutoConfiguration {
private final MongoConnectionDetails connectionDetails;
MongoReactiveDataAutoConfiguration(MongoConnectionDetails connectionDetails) {
this.connectionDetails = connectionDetails;
}
@Bean
@ConditionalOnMissingBean(ReactiveMongoDatabaseFactory.class)
public SimpleReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory(MongoClient mongo,
MongoProperties properties) {
String database = properties.getDatabase();
if (database == null) {
database = this.connectionDetails.getConnectionString().getDatabase();
}
return new SimpleReactiveMongoDatabaseFactory(mongo, database);
}
@Bean
@ConditionalOnMissingBean(ReactiveMongoOperations.class)
public ReactiveMongoTemplate reactiveMongoTemplate(ReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory,
MongoConverter converter) {
return new ReactiveMongoTemplate(reactiveMongoDatabaseFactory, converter);
}
@Bean
@ConditionalOnMissingBean(DataBufferFactory.class)
public DefaultDataBufferFactory dataBufferFactory() {
return new DefaultDataBufferFactory();
}
@Bean
@ConditionalOnMissingBean(ReactiveGridFsOperations.class)
public ReactiveGridFsTemplate reactiveGridFsTemplate(ReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory,
MappingMongoConverter mappingMongoConverter, DataBufferFactory dataBufferFactory) {
return new ReactiveGridFsTemplate(dataBufferFactory,
new GridFsReactiveMongoDatabaseFactory(reactiveMongoDatabaseFactory, this.connectionDetails),
mappingMongoConverter,
(this.connectionDetails.getGridFs() != null) ? this.connectionDetails.getGridFs().getBucket() : null);
}
/**
* {@link ReactiveMongoDatabaseFactory} decorator to use {@link GridFs#getGridFs()}
* from the {@link MongoConnectionDetails} when set.
*/
static class GridFsReactiveMongoDatabaseFactory implements ReactiveMongoDatabaseFactory {
private final ReactiveMongoDatabaseFactory delegate;
private final MongoConnectionDetails connectionDetails;
GridFsReactiveMongoDatabaseFactory(ReactiveMongoDatabaseFactory delegate,
MongoConnectionDetails connectionDetails) {
this.delegate = delegate;
this.connectionDetails = connectionDetails;
}
@Override
public boolean hasCodecFor(Class<?> type) {
return this.delegate.hasCodecFor(type);
}
@Override
public Mono<MongoDatabase> getMongoDatabase() throws DataAccessException {
String gridFsDatabase = getGridFsDatabase(this.connectionDetails);
if (StringUtils.hasText(gridFsDatabase)) {
return this.delegate.getMongoDatabase(gridFsDatabase);
}
return this.delegate.getMongoDatabase();
}
private String getGridFsDatabase(MongoConnectionDetails connectionDetails) {
return (connectionDetails.getGridFs() != null) ? connectionDetails.getGridFs().getDatabase() : null;
}
@Override
public Mono<MongoDatabase> getMongoDatabase(String dbName) throws DataAccessException {
return this.delegate.getMongoDatabase(dbName);
}
@Override
public <T> Optional<Codec<T>> getCodecFor(Class<T> type) {
return this.delegate.getCodecFor(type);
}
@Override
public PersistenceExceptionTranslator getExceptionTranslator() {
return this.delegate.getExceptionTranslator();
}
@Override
public CodecRegistry getCodecRegistry() {
return this.delegate.getCodecRegistry();
}
@Override
public Mono<ClientSession> getSession(ClientSessionOptions options) {
return this.delegate.getSession(options);
}
@Override
public ReactiveMongoDatabaseFactory withSession(ClientSession session) {
return this.delegate.withSession(session);
}
@Override
public boolean isTransactionActive() {
return this.delegate.isTransactionActive();
}
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure;
import com.mongodb.reactivestreams.client.MongoClient;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.ConditionalOnRepositoryType;
import org.springframework.boot.autoconfigure.data.RepositoryType;
import org.springframework.context.annotation.Import;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;
import org.springframework.data.mongodb.repository.config.ReactiveMongoRepositoryConfigurationExtension;
import org.springframework.data.mongodb.repository.support.ReactiveMongoRepositoryFactoryBean;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Mongo Reactive
* Repositories.
* <p>
* Activates when there is no bean of type
* {@link org.springframework.data.mongodb.repository.support.ReactiveMongoRepositoryFactoryBean}
* configured in the context, the Spring Data Mongo {@link ReactiveMongoRepository} type
* is on the classpath, the ReactiveStreams Mongo client driver API is on the classpath,
* and there is no other configured {@link ReactiveMongoRepository}.
* <p>
* Once in effect, the auto-configuration is the equivalent of enabling Mongo repositories
* using the {@link EnableReactiveMongoRepositories @EnableReactiveMongoRepositories}
* annotation.
*
* @author Mark Paluch
* @since 4.0.0
* @see EnableReactiveMongoRepositories
*/
@AutoConfiguration(after = MongoReactiveDataAutoConfiguration.class)
@ConditionalOnClass({ MongoClient.class, ReactiveMongoRepository.class })
@ConditionalOnMissingBean({ ReactiveMongoRepositoryFactoryBean.class,
ReactiveMongoRepositoryConfigurationExtension.class })
@ConditionalOnRepositoryType(store = "mongodb", type = RepositoryType.REACTIVE)
@Import(MongoReactiveRepositoriesRegistrar.class)
public class MongoReactiveRepositoriesAutoConfiguration {
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure;
import java.lang.annotation.Annotation;
import org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;
import org.springframework.data.mongodb.repository.config.ReactiveMongoRepositoryConfigurationExtension;
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
/**
* {@link ImportBeanDefinitionRegistrar} used to auto-configure Spring Data Mongo Reactive
* Repositories.
*
* @author Mark Paluch
*/
class MongoReactiveRepositoriesRegistrar extends AbstractRepositoryConfigurationSourceSupport {
@Override
protected Class<? extends Annotation> getAnnotation() {
return EnableReactiveMongoRepositories.class;
}
@Override
protected Class<?> getConfiguration() {
return EnableReactiveMongoRepositoriesConfiguration.class;
}
@Override
protected RepositoryConfigurationExtension getRepositoryConfigurationExtension() {
return new ReactiveMongoRepositoryConfigurationExtension();
}
@EnableReactiveMongoRepositories
private static final class EnableReactiveMongoRepositoriesConfiguration {
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure;
import com.mongodb.client.MongoClient;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.ConditionalOnRepositoryType;
import org.springframework.boot.autoconfigure.data.RepositoryType;
import org.springframework.context.annotation.Import;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.data.mongodb.repository.config.MongoRepositoryConfigurationExtension;
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Mongo
* Repositories.
* <p>
* Activates when there is no bean of type
* {@link org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean}
* configured in the context, the Spring Data Mongo
* {@link org.springframework.data.mongodb.repository.MongoRepository} type is on the
* classpath, the Mongo client driver API is on the classpath, and there is no other
* configured {@link org.springframework.data.mongodb.repository.MongoRepository}.
* <p>
* Once in effect, the auto-configuration is the equivalent of enabling Mongo repositories
* using the {@link EnableMongoRepositories @EnableMongoRepositories} annotation.
*
* @author Dave Syer
* @author Oliver Gierke
* @author Josh Long
* @since 4.0.0
* @see EnableMongoRepositories
*/
@AutoConfiguration(after = MongoDataAutoConfiguration.class)
@ConditionalOnClass({ MongoClient.class, MongoRepository.class })
@ConditionalOnMissingBean({ MongoRepositoryFactoryBean.class, MongoRepositoryConfigurationExtension.class })
@ConditionalOnRepositoryType(store = "mongodb", type = RepositoryType.IMPERATIVE)
@Import(MongoRepositoriesRegistrar.class)
public class MongoRepositoriesAutoConfiguration {
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure;
import java.lang.annotation.Annotation;
import org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.data.mongodb.repository.config.MongoRepositoryConfigurationExtension;
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
/**
* {@link ImportBeanDefinitionRegistrar} used to auto-configure Spring Data Mongo
* Repositories.
*
* @author Dave Syer
*/
class MongoRepositoriesRegistrar extends AbstractRepositoryConfigurationSourceSupport {
@Override
protected Class<? extends Annotation> getAnnotation() {
return EnableMongoRepositories.class;
}
@Override
protected Class<?> getConfiguration() {
return EnableMongoRepositoriesConfiguration.class;
}
@Override
protected RepositoryConfigurationExtension getRepositoryConfigurationExtension() {
return new MongoRepositoryConfigurationExtension();
}
@EnableMongoRepositories
private static final class EnableMongoRepositoriesConfiguration {
}
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Auto-configuration for Spring Data MongoDB.
*/
package org.springframework.boot.data.mongodb.autoconfigure;

View File

@@ -0,0 +1,31 @@
{
"hints": [
{
"name": "spring.data.mongodb.field-naming-strategy",
"providers": [
{
"name": "class-reference",
"parameters": {
"target": "org.springframework.data.mapping.model.FieldNamingStrategy"
}
}
]
},
{
"name": "spring.data.mongodb.protocol",
"values": [
{
"value": "mongodb"
},
{
"value": "mongodb+srv"
}
],
"providers": [
{
"name": "any"
}
]
}
]
}

View File

@@ -0,0 +1,4 @@
org.springframework.boot.data.mongodb.autoconfigure.MongoDataAutoConfiguration
org.springframework.boot.data.mongodb.autoconfigure.MongoReactiveDataAutoConfiguration
org.springframework.boot.data.mongodb.autoconfigure.MongoReactiveRepositoriesAutoConfiguration
org.springframework.boot.data.mongodb.autoconfigure.MongoRepositoriesAutoConfiguration

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.alt;
import org.springframework.boot.data.mongodb.autoconfigure.domain.city.City;
import org.springframework.data.repository.Repository;
public interface CityMongoDbRepository extends Repository<City, Long> {
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.alt;
import org.springframework.boot.data.mongodb.autoconfigure.domain.city.City;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
public interface ReactiveCityMongoDbRepository extends ReactiveCrudRepository<City, Long> {
}

View File

@@ -0,0 +1,410 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.function.Supplier;
import com.mongodb.ConnectionString;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.gridfs.GridFSBucket;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.data.mongodb.autoconfigure.domain.city.City;
import org.springframework.boot.data.mongodb.autoconfigure.domain.country.Country;
import org.springframework.boot.mongodb.autoconfigure.MongoAutoConfiguration;
import org.springframework.boot.mongodb.autoconfigure.MongoConnectionDetails;
import org.springframework.boot.mongodb.autoconfigure.PropertiesMongoConnectionDetails;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.domain.ManagedTypes;
import org.springframework.data.mapping.model.CamelCaseAbbreviatingFieldNamingStrategy;
import org.springframework.data.mapping.model.FieldNamingStrategy;
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link MongoDataAutoConfiguration}.
*
* @author Josh Long
* @author Oliver Gierke
* @author Mark Paluch
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
* @author Scott Frederick
*/
class MongoDataAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(PropertyPlaceholderAutoConfiguration.class,
MongoAutoConfiguration.class, MongoDataAutoConfiguration.class));
@Test
void templateExists() {
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(MongoTemplate.class));
}
@Test
@SuppressWarnings("unchecked")
void whenGridFsDatabaseIsConfiguredThenGridFsTemplateIsAutoConfiguredAndUsesIt() {
this.contextRunner.withPropertyValues("spring.data.mongodb.gridfs.database:grid").run((context) -> {
assertThat(context).hasSingleBean(GridFsTemplate.class);
GridFsTemplate template = context.getBean(GridFsTemplate.class);
GridFSBucket bucket = ((Supplier<GridFSBucket>) ReflectionTestUtils.getField(template, "bucketSupplier"))
.get();
assertThat(bucket).extracting("filesCollection", InstanceOfAssertFactories.type(MongoCollection.class))
.extracting((collection) -> collection.getNamespace().getDatabaseName())
.isEqualTo("grid");
});
}
@Test
@SuppressWarnings("unchecked")
void usesMongoConnectionDetailsIfAvailable() {
this.contextRunner.withUserConfiguration(ConnectionDetailsConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(GridFsTemplate.class);
GridFsTemplate template = context.getBean(GridFsTemplate.class);
GridFSBucket bucket = ((Supplier<GridFSBucket>) ReflectionTestUtils.getField(template, "bucketSupplier"))
.get();
assertThat(bucket.getBucketName()).isEqualTo("connection-details-bucket");
assertThat(bucket).extracting("filesCollection", InstanceOfAssertFactories.type(MongoCollection.class))
.extracting((collection) -> collection.getNamespace().getDatabaseName())
.isEqualTo("grid-database-1");
});
}
@Test
@SuppressWarnings("unchecked")
void whenGridFsBucketIsConfiguredThenGridFsTemplateIsAutoConfiguredAndUsesIt() {
this.contextRunner.withPropertyValues("spring.data.mongodb.gridfs.bucket:test-bucket").run((context) -> {
assertThat(context).hasSingleBean(GridFsTemplate.class);
GridFsTemplate template = context.getBean(GridFsTemplate.class);
GridFSBucket bucket = ((Supplier<GridFSBucket>) ReflectionTestUtils.getField(template, "bucketSupplier"))
.get();
assertThat(bucket.getBucketName()).isEqualTo("test-bucket");
});
}
@Test
void customConversions() {
this.contextRunner.withUserConfiguration(CustomConversionsConfig.class).run((context) -> {
MongoTemplate template = context.getBean(MongoTemplate.class);
assertThat(template.getConverter().getConversionService().canConvert(MongoClient.class, Boolean.class))
.isTrue();
});
}
@Test
void usesAutoConfigurationPackageToPickUpDocumentTypes() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
String cityPackage = City.class.getPackage().getName();
AutoConfigurationPackages.register(context, cityPackage);
context.register(MongoAutoConfiguration.class, MongoDataAutoConfiguration.class);
try {
context.refresh();
assertDomainTypesDiscovered(context.getBean(MongoMappingContext.class), City.class);
}
finally {
context.close();
}
}
@Test
void defaultFieldNamingStrategy() {
this.contextRunner.run((context) -> {
MongoMappingContext mappingContext = context.getBean(MongoMappingContext.class);
FieldNamingStrategy fieldNamingStrategy = (FieldNamingStrategy) ReflectionTestUtils.getField(mappingContext,
"fieldNamingStrategy");
assertThat(fieldNamingStrategy.getClass()).isEqualTo(PropertyNameFieldNamingStrategy.class);
});
}
@Test
void customFieldNamingStrategy() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.field-naming-strategy:"
+ CamelCaseAbbreviatingFieldNamingStrategy.class.getName())
.run((context) -> {
MongoMappingContext mappingContext = context.getBean(MongoMappingContext.class);
FieldNamingStrategy fieldNamingStrategy = (FieldNamingStrategy) ReflectionTestUtils
.getField(mappingContext, "fieldNamingStrategy");
assertThat(fieldNamingStrategy.getClass()).isEqualTo(CamelCaseAbbreviatingFieldNamingStrategy.class);
});
}
@Test
void defaultAutoIndexCreation() {
this.contextRunner.run((context) -> {
MongoMappingContext mappingContext = context.getBean(MongoMappingContext.class);
assertThat(mappingContext.isAutoIndexCreation()).isFalse();
});
}
@Test
void customAutoIndexCreation() {
this.contextRunner.withPropertyValues("spring.data.mongodb.autoIndexCreation:true").run((context) -> {
MongoMappingContext mappingContext = context.getBean(MongoMappingContext.class);
assertThat(mappingContext.isAutoIndexCreation()).isTrue();
});
}
@Test
void interfaceFieldNamingStrategy() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.field-naming-strategy:" + FieldNamingStrategy.class.getName())
.run((context) -> assertThat(context).getFailure().isInstanceOf(BeanCreationException.class));
}
@Test
void entityScanShouldSetManagedTypes() {
this.contextRunner.withUserConfiguration(EntityScanConfig.class).run((context) -> {
MongoMappingContext mappingContext = context.getBean(MongoMappingContext.class);
ManagedTypes managedTypes = (ManagedTypes) ReflectionTestUtils.getField(mappingContext, "managedTypes");
assertThat(managedTypes.toList()).containsOnly(City.class, Country.class);
});
}
@Test
void registersDefaultSimpleTypesWithMappingContext() {
this.contextRunner.run((context) -> {
MongoMappingContext mappingContext = context.getBean(MongoMappingContext.class);
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(Sample.class);
MongoPersistentProperty dateProperty = entity.getPersistentProperty("date");
assertThat(dateProperty.isEntity()).isFalse();
});
}
@Test
void backsOffIfMongoClientBeanIsNotPresent() {
ApplicationContextRunner runner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(MongoDataAutoConfiguration.class));
runner.run((context) -> assertThat(context).doesNotHaveBean(MongoTemplate.class));
}
@Test
void createsMongoDatabaseFactoryForPreferredMongoClient() {
this.contextRunner.run((context) -> {
MongoDatabaseFactory dbFactory = context.getBean(MongoDatabaseFactory.class);
assertThat(dbFactory).isInstanceOf(SimpleMongoClientDatabaseFactory.class);
});
}
@Test
void createsMongoDatabaseFactoryForFallbackMongoClient() {
this.contextRunner.withUserConfiguration(FallbackMongoClientConfiguration.class).run((context) -> {
MongoDatabaseFactory dbFactory = context.getBean(MongoDatabaseFactory.class);
assertThat(dbFactory).isInstanceOf(SimpleMongoClientDatabaseFactory.class);
});
}
@Test
void autoConfiguresIfUserProvidesMongoDatabaseFactoryButNoClient() {
this.contextRunner.withUserConfiguration(MongoDatabaseFactoryConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(MongoTemplate.class));
}
@Test
void databaseHasDefault() {
this.contextRunner.run((context) -> {
MongoDatabaseFactory factory = context.getBean(MongoDatabaseFactory.class);
assertThat(factory).isInstanceOf(SimpleMongoClientDatabaseFactory.class);
assertThat(factory.getMongoDatabase().getName()).isEqualTo("test");
});
}
@Test
void databasePropertyIsUsed() {
this.contextRunner.withPropertyValues("spring.data.mongodb.database=mydb").run((context) -> {
MongoDatabaseFactory factory = context.getBean(MongoDatabaseFactory.class);
assertThat(factory).isInstanceOf(SimpleMongoClientDatabaseFactory.class);
assertThat(factory.getMongoDatabase().getName()).isEqualTo("mydb");
});
}
@Test
void databaseInUriPropertyIsUsed() {
this.contextRunner.withPropertyValues("spring.data.mongodb.uri=mongodb://mongo.example.com/mydb")
.run((context) -> {
MongoDatabaseFactory factory = context.getBean(MongoDatabaseFactory.class);
assertThat(factory).isInstanceOf(SimpleMongoClientDatabaseFactory.class);
assertThat(factory.getMongoDatabase().getName()).isEqualTo("mydb");
});
}
@Test
void databasePropertyOverridesUriProperty() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.uri=mongodb://mongo.example.com/notused",
"spring.data.mongodb.database=mydb")
.run((context) -> {
MongoDatabaseFactory factory = context.getBean(MongoDatabaseFactory.class);
assertThat(factory).isInstanceOf(SimpleMongoClientDatabaseFactory.class);
assertThat(factory.getMongoDatabase().getName()).isEqualTo("mydb");
});
}
@Test
void databasePropertyIsUsedWhenNoDatabaseInUri() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.uri=mongodb://mongo.example.com/",
"spring.data.mongodb.database=mydb")
.run((context) -> {
MongoDatabaseFactory factory = context.getBean(MongoDatabaseFactory.class);
assertThat(factory).isInstanceOf(SimpleMongoClientDatabaseFactory.class);
assertThat(factory.getMongoDatabase().getName()).isEqualTo("mydb");
});
}
@Test
void contextFailsWhenDatabaseNotSet() {
this.contextRunner.withPropertyValues("spring.data.mongodb.uri=mongodb://mongo.example.com/")
.run((context) -> assertThat(context).getFailure().hasMessageContaining("Database name must not be empty"));
}
@Test
void definesPropertiesBasedConnectionDetailsByDefault() {
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(PropertiesMongoConnectionDetails.class));
}
@Test
void shouldUseCustomConnectionDetailsWhenDefined() {
this.contextRunner.withBean(MongoConnectionDetails.class, () -> new MongoConnectionDetails() {
@Override
public ConnectionString getConnectionString() {
return new ConnectionString("mongodb://localhost/testdb");
}
})
.run((context) -> assertThat(context).hasSingleBean(MongoConnectionDetails.class)
.doesNotHaveBean(PropertiesMongoConnectionDetails.class));
}
@Test
void mappingMongoConverterHasADefaultDbRefResolver() {
this.contextRunner.run((context) -> {
MappingMongoConverter converter = context.getBean(MappingMongoConverter.class);
assertThat(converter).extracting("dbRefResolver").isInstanceOf(DefaultDbRefResolver.class);
});
}
private static void assertDomainTypesDiscovered(MongoMappingContext mappingContext, Class<?>... types) {
ManagedTypes managedTypes = (ManagedTypes) ReflectionTestUtils.getField(mappingContext, "managedTypes");
assertThat(managedTypes.toList()).containsOnly(types);
}
@Configuration(proxyBeanMethods = false)
static class CustomConversionsConfig {
@Bean
MongoCustomConversions customConversions() {
return new MongoCustomConversions(Arrays.asList(new MyConverter()));
}
}
@Configuration(proxyBeanMethods = false)
@EntityScan("org.springframework.boot.data.mongodb.autoconfigure")
static class EntityScanConfig {
}
@Configuration(proxyBeanMethods = false)
static class FallbackMongoClientConfiguration {
@Bean
com.mongodb.client.MongoClient fallbackMongoClient() {
return MongoClients.create();
}
}
@Configuration(proxyBeanMethods = false)
static class MongoDatabaseFactoryConfiguration {
@Bean
MongoDatabaseFactory mongoDatabaseFactory() {
return new SimpleMongoClientDatabaseFactory(MongoClients.create(), "test");
}
}
@Configuration(proxyBeanMethods = false)
static class ConnectionDetailsConfiguration {
@Bean
MongoConnectionDetails mongoConnectionDetails() {
return new MongoConnectionDetails() {
@Override
public ConnectionString getConnectionString() {
return new ConnectionString("mongodb://localhost/db");
}
@Override
public GridFs getGridFs() {
return GridFs.of("grid-database-1", "connection-details-bucket");
}
};
}
}
static class MyConverter implements Converter<MongoClient, Boolean> {
@Override
public Boolean convert(MongoClient source) {
return null;
}
}
static class Sample {
LocalDateTime date;
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.data.mongodb.autoconfigure.domain.city.CityRepository;
import org.springframework.boot.data.mongodb.autoconfigure.domain.city.ReactiveCityRepository;
import org.springframework.boot.mongodb.autoconfigure.MongoAutoConfiguration;
import org.springframework.boot.mongodb.autoconfigure.MongoReactiveAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;
import org.springframework.util.StringUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link MongoRepositoriesAutoConfiguration} and
* {@link MongoReactiveRepositoriesAutoConfiguration}.
*
* @author Mark Paluch
*/
class MongoReactiveAndBlockingRepositoriesAutoConfigurationTests {
private AnnotationConfigApplicationContext context;
@AfterEach
void close() {
this.context.close();
}
@Test
void shouldCreateInstancesForReactiveAndBlockingRepositories() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(BlockingAndReactiveConfiguration.class, BaseConfiguration.class);
this.context.refresh();
assertThat(this.context.getBean(CityRepository.class)).isNotNull();
assertThat(this.context.getBean(ReactiveCityRepository.class)).isNotNull();
}
@Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(MongoAutoConfiguration.class)
@EnableMongoRepositories(basePackageClasses = ReactiveCityRepository.class)
@EnableReactiveMongoRepositories(basePackageClasses = ReactiveCityRepository.class)
static class BlockingAndReactiveConfiguration {
}
@Configuration(proxyBeanMethods = false)
@Import(Registrar.class)
static class BaseConfiguration {
}
static class Registrar implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
List<String> names = new ArrayList<>();
for (Class<?> type : new Class<?>[] { MongoAutoConfiguration.class, MongoReactiveAutoConfiguration.class,
MongoDataAutoConfiguration.class, MongoRepositoriesAutoConfiguration.class,
MongoReactiveDataAutoConfiguration.class, MongoReactiveRepositoriesAutoConfiguration.class }) {
names.add(type.getName());
}
return StringUtils.toStringArray(names);
}
}
}

View File

@@ -0,0 +1,218 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure;
import java.time.Duration;
import com.mongodb.ConnectionString;
import com.mongodb.reactivestreams.client.MongoCollection;
import com.mongodb.reactivestreams.client.gridfs.GridFSBucket;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.mongodb.autoconfigure.MongoConnectionDetails;
import org.springframework.boot.mongodb.autoconfigure.MongoReactiveAutoConfiguration;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver;
import org.springframework.data.mongodb.gridfs.ReactiveGridFsTemplate;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link MongoReactiveDataAutoConfiguration}.
*
* @author Mark Paluch
* @author Artsiom Yudovin
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
* @author Scott Frederick
*/
class MongoReactiveDataAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(PropertyPlaceholderAutoConfiguration.class,
MongoReactiveAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class));
@Test
void templateExists() {
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ReactiveMongoTemplate.class));
}
@Test
void whenNoGridFsDatabaseIsConfiguredTheGridFsTemplateUsesTheMainDatabase() {
this.contextRunner.run((context) -> assertThat(grisFsTemplateDatabaseName(context)).isEqualTo("test"));
}
@Test
void whenGridFsDatabaseIsConfiguredThenGridFsTemplateUsesIt() {
this.contextRunner.withPropertyValues("spring.data.mongodb.gridfs.database:grid")
.run((context) -> assertThat(grisFsTemplateDatabaseName(context)).isEqualTo("grid"));
}
@Test
@SuppressWarnings("unchecked")
void usesMongoConnectionDetailsIfAvailable() {
this.contextRunner.withUserConfiguration(ConnectionDetailsConfiguration.class).run((context) -> {
assertThat(grisFsTemplateDatabaseName(context)).isEqualTo("grid-database-1");
ReactiveGridFsTemplate template = context.getBean(ReactiveGridFsTemplate.class);
GridFSBucket bucket = ((Mono<GridFSBucket>) ReflectionTestUtils.getField(template, "bucketSupplier"))
.block(Duration.ofSeconds(30));
assertThat(bucket.getBucketName()).isEqualTo("connection-details-bucket");
});
}
@Test
@SuppressWarnings("unchecked")
void whenGridFsBucketIsConfiguredThenGridFsTemplateUsesIt() {
this.contextRunner.withPropertyValues("spring.data.mongodb.gridfs.bucket:test-bucket").run((context) -> {
assertThat(context).hasSingleBean(ReactiveGridFsTemplate.class);
ReactiveGridFsTemplate template = context.getBean(ReactiveGridFsTemplate.class);
GridFSBucket bucket = ((Mono<GridFSBucket>) ReflectionTestUtils.getField(template, "bucketSupplier"))
.block(Duration.ofSeconds(30));
assertThat(bucket.getBucketName()).isEqualTo("test-bucket");
});
}
@Test
void backsOffIfMongoClientBeanIsNotPresent() {
ApplicationContextRunner runner = new ApplicationContextRunner().withConfiguration(AutoConfigurations
.of(PropertyPlaceholderAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class));
runner.run((context) -> assertThat(context).doesNotHaveBean(MongoReactiveDataAutoConfiguration.class));
}
@Test
void databaseHasDefault() {
this.contextRunner.run((context) -> {
ReactiveMongoDatabaseFactory factory = context.getBean(ReactiveMongoDatabaseFactory.class);
assertThat(factory).isInstanceOf(SimpleReactiveMongoDatabaseFactory.class);
assertThat(factory.getMongoDatabase().block().getName()).isEqualTo("test");
});
}
@Test
void databasePropertyIsUsed() {
this.contextRunner.withPropertyValues("spring.data.mongodb.database=mydb").run((context) -> {
ReactiveMongoDatabaseFactory factory = context.getBean(ReactiveMongoDatabaseFactory.class);
assertThat(factory).isInstanceOf(SimpleReactiveMongoDatabaseFactory.class);
assertThat(factory.getMongoDatabase().block().getName()).isEqualTo("mydb");
});
}
@Test
void databaseInUriPropertyIsUsed() {
this.contextRunner.withPropertyValues("spring.data.mongodb.uri=mongodb://mongo.example.com/mydb")
.run((context) -> {
ReactiveMongoDatabaseFactory factory = context.getBean(ReactiveMongoDatabaseFactory.class);
assertThat(factory).isInstanceOf(SimpleReactiveMongoDatabaseFactory.class);
assertThat(factory.getMongoDatabase().block().getName()).isEqualTo("mydb");
});
}
@Test
void databasePropertyOverridesUriProperty() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.uri=mongodb://mongo.example.com/notused",
"spring.data.mongodb.database=mydb")
.run((context) -> {
ReactiveMongoDatabaseFactory factory = context.getBean(ReactiveMongoDatabaseFactory.class);
assertThat(factory).isInstanceOf(SimpleReactiveMongoDatabaseFactory.class);
assertThat(factory.getMongoDatabase().block().getName()).isEqualTo("mydb");
});
}
@Test
void databasePropertyIsUsedWhenNoDatabaseInUri() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.uri=mongodb://mongo.example.com/",
"spring.data.mongodb.database=mydb")
.run((context) -> {
ReactiveMongoDatabaseFactory factory = context.getBean(ReactiveMongoDatabaseFactory.class);
assertThat(factory).isInstanceOf(SimpleReactiveMongoDatabaseFactory.class);
assertThat(factory.getMongoDatabase().block().getName()).isEqualTo("mydb");
});
}
@Test
void contextFailsWhenDatabaseNotSet() {
this.contextRunner.withPropertyValues("spring.data.mongodb.uri=mongodb://mongo.example.com/")
.run((context) -> assertThat(context).getFailure().hasMessageContaining("Database name must not be empty"));
}
@Test
void mappingMongoConverterHasANoOpDbRefResolver() {
this.contextRunner.run((context) -> {
MappingMongoConverter converter = context.getBean(MappingMongoConverter.class);
assertThat(converter).extracting("dbRefResolver").isInstanceOf(NoOpDbRefResolver.class);
});
}
@SuppressWarnings("unchecked")
private String grisFsTemplateDatabaseName(AssertableApplicationContext context) {
assertThat(context).hasSingleBean(ReactiveGridFsTemplate.class);
ReactiveGridFsTemplate template = context.getBean(ReactiveGridFsTemplate.class);
GridFSBucket bucket = ((Mono<GridFSBucket>) ReflectionTestUtils.getField(template, "bucketSupplier"))
.block(Duration.ofSeconds(30));
MongoCollection<?> collection = (MongoCollection<?>) ReflectionTestUtils.getField(bucket, "filesCollection");
return collection.getNamespace().getDatabaseName();
}
@Configuration(proxyBeanMethods = false)
static class ConnectionDetailsConfiguration {
@Bean
MongoConnectionDetails mongoConnectionDetails() {
return new MongoConnectionDetails() {
@Override
public ConnectionString getConnectionString() {
return new ConnectionString("mongodb://localhost/db");
}
@Override
public GridFs getGridFs() {
return new GridFs() {
@Override
public String getDatabase() {
return "grid-database-1";
}
@Override
public String getBucket() {
return "connection-details-bucket";
}
};
}
};
}
}
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure;
import com.mongodb.reactivestreams.client.MongoClient;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.data.mongodb.alt.CityMongoDbRepository;
import org.springframework.boot.data.mongodb.alt.ReactiveCityMongoDbRepository;
import org.springframework.boot.data.mongodb.autoconfigure.domain.city.City;
import org.springframework.boot.data.mongodb.autoconfigure.domain.city.ReactiveCityRepository;
import org.springframework.boot.data.mongodb.autoconfigure.empty.EmptyDataPackage;
import org.springframework.boot.mongodb.autoconfigure.MongoAutoConfiguration;
import org.springframework.boot.mongodb.autoconfigure.MongoReactiveAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.ManagedTypes;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link MongoReactiveRepositoriesAutoConfiguration}.
*
* @author Mark Paluch
* @author Andy Wilkinson
*/
class MongoReactiveRepositoriesAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class, MongoDataAutoConfiguration.class,
MongoReactiveAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class,
MongoReactiveRepositoriesAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class));
@Test
void testDefaultRepositoryConfiguration() {
this.contextRunner.withUserConfiguration(TestConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(ReactiveCityRepository.class);
assertThat(context).hasSingleBean(MongoClient.class);
MongoMappingContext mappingContext = context.getBean(MongoMappingContext.class);
ManagedTypes managedTypes = (ManagedTypes) ReflectionTestUtils.getField(mappingContext, "managedTypes");
assertThat(managedTypes.toList()).hasSize(1);
});
}
@Test
void testNoRepositoryConfiguration() {
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(MongoClient.class));
}
@Test
void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
this.contextRunner.withUserConfiguration(CustomizedConfiguration.class)
.run((context) -> assertThat(context).doesNotHaveBean(ReactiveCityMongoDbRepository.class));
}
@Test
void autoConfigurationShouldNotKickInEvenIfManualConfigDidNotCreateAnyRepositories() {
this.contextRunner.withUserConfiguration(SortOfInvalidCustomConfiguration.class)
.run((context) -> assertThat(context).doesNotHaveBean(ReactiveCityRepository.class));
}
@Test
void enablingImperativeRepositoriesDisablesReactiveRepositories() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.data.mongodb.repositories.type=imperative")
.run((context) -> assertThat(context).doesNotHaveBean(ReactiveCityRepository.class));
}
@Test
void enablingNoRepositoriesDisablesReactiveRepositories() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.data.mongodb.repositories.type=none")
.run((context) -> assertThat(context).doesNotHaveBean(ReactiveCityRepository.class));
}
@Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(City.class)
static class TestConfiguration {
}
@Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(EmptyDataPackage.class)
static class EmptyConfiguration {
}
@Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(MongoReactiveRepositoriesAutoConfigurationTests.class)
@EnableMongoRepositories(basePackageClasses = CityMongoDbRepository.class)
static class CustomizedConfiguration {
}
@Configuration(proxyBeanMethods = false)
// To not find any repositories
@EnableReactiveMongoRepositories("foo.bar")
@TestAutoConfigurationPackage(MongoReactiveRepositoriesAutoConfigurationTests.class)
static class SortOfInvalidCustomConfiguration {
}
}

View File

@@ -0,0 +1,121 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure;
import com.mongodb.client.MongoClient;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.data.mongodb.alt.CityMongoDbRepository;
import org.springframework.boot.data.mongodb.autoconfigure.domain.city.City;
import org.springframework.boot.data.mongodb.autoconfigure.domain.city.CityRepository;
import org.springframework.boot.data.mongodb.autoconfigure.empty.EmptyDataPackage;
import org.springframework.boot.mongodb.autoconfigure.MongoAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.ManagedTypes;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link MongoRepositoriesAutoConfiguration}.
*
* @author Dave Syer
* @author Oliver Gierke
*/
class MongoRepositoriesAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class, MongoDataAutoConfiguration.class,
MongoRepositoriesAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class));
@Test
void testDefaultRepositoryConfiguration() {
this.contextRunner.withUserConfiguration(TestConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(CityRepository.class);
assertThat(context).hasSingleBean(MongoClient.class);
MongoMappingContext mappingContext = context.getBean(MongoMappingContext.class);
ManagedTypes managedTypes = (ManagedTypes) ReflectionTestUtils.getField(mappingContext, "managedTypes");
assertThat(managedTypes.toList()).hasSize(1);
});
}
@Test
void testNoRepositoryConfiguration() {
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(MongoClient.class));
}
@Test
void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
this.contextRunner.withUserConfiguration(CustomizedConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(CityMongoDbRepository.class));
}
@Test
void autoConfigurationShouldNotKickInEvenIfManualConfigDidNotCreateAnyRepositories() {
this.contextRunner.withUserConfiguration(SortOfInvalidCustomConfiguration.class)
.run((context) -> assertThat(context).doesNotHaveBean(CityRepository.class));
}
@Test
void enablingReactiveRepositoriesDisablesImperativeRepositories() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.data.mongodb.repositories.type=reactive")
.run((context) -> assertThat(context).doesNotHaveBean(CityRepository.class));
}
@Test
void enablingNoRepositoriesDisablesImperativeRepositories() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.data.mongodb.repositories.type=none")
.run((context) -> assertThat(context).doesNotHaveBean(CityRepository.class));
}
@Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(City.class)
static class TestConfiguration {
}
@Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(EmptyDataPackage.class)
static class EmptyConfiguration {
}
@Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(MongoRepositoriesAutoConfigurationTests.class)
@EnableMongoRepositories(basePackageClasses = CityMongoDbRepository.class)
static class CustomizedConfiguration {
}
@Configuration(proxyBeanMethods = false)
// To not find any repositories
@EnableMongoRepositories("foo.bar")
@TestAutoConfigurationPackage(MongoRepositoriesAutoConfigurationTests.class)
static class SortOfInvalidCustomConfiguration {
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure.domain.city;
import java.io.Serializable;
import org.springframework.data.mongodb.core.mapping.Document;
@Document
public class City implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String state;
private String country;
private String map;
protected City() {
}
public City(String name, String country) {
this.name = name;
this.country = country;
}
public String getName() {
return this.name;
}
public String getState() {
return this.state;
}
public String getCountry() {
return this.country;
}
public String getMap() {
return this.map;
}
@Override
public String toString() {
return getName() + "," + getState() + "," + getCountry();
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure.domain.city;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
public interface CityRepository extends Repository<City, Long> {
Page<City> findAll(Pageable pageable);
Page<City> findByNameLikeAndCountryLikeAllIgnoringCase(String name, String country, Pageable pageable);
City findByNameAndCountryAllIgnoringCase(String name, String country);
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure.domain.city;
import java.io.Serializable;
import org.springframework.data.annotation.Persistent;
@Persistent
public class PersistentEntity implements Serializable {
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure.domain.city;
import reactor.core.publisher.Flux;
import org.springframework.data.repository.Repository;
public interface ReactiveCityRepository extends Repository<City, Long> {
Flux<City> findAll();
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure.domain.country;
import java.io.Serializable;
import org.springframework.data.mongodb.core.mapping.Document;
@Document
public class Country implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
protected Country() {
}
public Country(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
@Override
public String toString() {
return getName();
}
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure.domain.country;
import org.springframework.data.repository.Repository;
public interface CountryRepository extends Repository<Country, Long> {
}

View File

@@ -0,0 +1,21 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.data.mongodb.autoconfigure.empty;
public class EmptyDataPackage {
}