[ BAEL-5397 ] - Connect to Multiple Databases using Spring Data Mongodb (#12642)

* feat: multiple connections app, spring boot test, test resources

* rename to live test

* fix: build errors, clean code

* fix simplify test bootstratp

* fix: typo, rename account email to account domain

* fix: split db port

* fix: add boot config to test
This commit is contained in:
lucaCambi77 2022-09-03 04:52:36 +02:00 committed by GitHub
parent 2130df6ba9
commit ce556996a0
14 changed files with 446 additions and 16 deletions

View File

@ -0,0 +1,13 @@
package com.baeldung.logging;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootLoggingApplication {
public static void main(String... args) {
SpringApplication.run(SpringBootLoggingApplication.class, args);
}
}

View File

@ -0,0 +1,14 @@
package com.baeldung.multipledb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration;
@SpringBootApplication(exclude = EmbeddedMongoAutoConfiguration.class)
public class SpringBootMultipleDbApplication {
public static void main(String... args) {
SpringApplication.run(SpringBootMultipleDbApplication.class, args);
}
}

View File

@ -0,0 +1,59 @@
package com.baeldung.multipledb.config;
import static java.util.Collections.singletonList;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
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.repository.config.EnableMongoRepositories;
import com.baeldung.multipledb.repository.primary.UserRepository;
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
@Configuration
@EnableMongoRepositories(basePackageClasses = UserRepository.class, mongoTemplateRef = "primaryMongoTemplate")
@EnableConfigurationProperties
public class PrimaryConfig {
@Bean(name = "primaryProperties")
@ConfigurationProperties(prefix = "mongodb.primary")
@Primary
public MongoProperties primaryProperties() {
return new MongoProperties();
}
@Bean(name = "primaryMongoClient")
public MongoClient mongoClient(@Qualifier("primaryProperties") MongoProperties mongoProperties) {
MongoCredential credential = MongoCredential.createCredential(mongoProperties.getUsername(), mongoProperties.getAuthenticationDatabase(), mongoProperties.getPassword());
return MongoClients.create(MongoClientSettings.builder()
.applyToClusterSettings(builder -> builder.hosts(singletonList(new ServerAddress(mongoProperties.getHost(), mongoProperties.getPort()))))
.credential(credential)
.build());
}
@Primary
@Bean(name = "primaryMongoDBFactory")
public MongoDatabaseFactory mongoDatabaseFactory(@Qualifier("primaryMongoClient") MongoClient mongoClient, @Qualifier("primaryProperties") MongoProperties mongoProperties) {
return new SimpleMongoClientDatabaseFactory(mongoClient, mongoProperties.getDatabase());
}
@Primary
@Bean(name = "primaryMongoTemplate")
public MongoTemplate mongoTemplate(@Qualifier("primaryMongoDBFactory") MongoDatabaseFactory mongoDatabaseFactory) {
return new MongoTemplate(mongoDatabaseFactory);
}
}

View File

@ -0,0 +1,55 @@
package com.baeldung.multipledb.config;
import static java.util.Collections.singletonList;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.repository.config.EnableMongoRepositories;
import com.baeldung.multipledb.repository.secondary.AccountRepository;
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
@Configuration
@EnableMongoRepositories(basePackageClasses = AccountRepository.class, mongoTemplateRef = "secondaryMongoTemplate")
@EnableConfigurationProperties
public class SecondaryConfig {
@Bean(name = "secondaryProperties")
@ConfigurationProperties(prefix = "mongodb.secondary")
public MongoProperties secondaryProperties() {
return new MongoProperties();
}
@Bean(name = "secondaryMongoClient")
public MongoClient mongoClient(@Qualifier("secondaryProperties") MongoProperties mongoProperties) {
MongoCredential credential = MongoCredential.createCredential(mongoProperties.getUsername(), mongoProperties.getAuthenticationDatabase(), mongoProperties.getPassword());
return MongoClients.create(MongoClientSettings.builder()
.applyToClusterSettings(builder -> builder.hosts(singletonList(new ServerAddress(mongoProperties.getHost(), mongoProperties.getPort()))))
.credential(credential)
.build());
}
@Bean(name = "secondaryMongoDBFactory")
public MongoDatabaseFactory mongoDatabaseFactory(@Qualifier("secondaryMongoClient") MongoClient mongoClient, @Qualifier("secondaryProperties") MongoProperties mongoProperties) {
return new SimpleMongoClientDatabaseFactory(mongoClient, mongoProperties.getDatabase());
}
@Bean(name = "secondaryMongoTemplate")
public MongoTemplate mongoTemplate(@Qualifier("secondaryMongoDBFactory") MongoDatabaseFactory mongoDatabaseFactory) {
return new MongoTemplate(mongoDatabaseFactory);
}
}

View File

@ -0,0 +1,73 @@
package com.baeldung.multipledb.model;
import java.util.Objects;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.MongoId;
@Document(collection = "account")
public class Account {
@MongoId
private ObjectId id;
private String userEmail;
private String nickName;
private String accountDomain;
private String password;
public ObjectId getId() {
return id;
}
public String getUserEmail() {
return userEmail;
}
public void setUserEmail(String userEmail) {
this.userEmail = userEmail;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getAccountDomain() {
return accountDomain;
}
public void setAccountDomain(String accountDomain) {
this.accountDomain = accountDomain;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Account book = (Account) o;
return Objects.equals(id, book.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}

View File

@ -0,0 +1,73 @@
package com.baeldung.multipledb.model;
import java.util.Objects;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.MongoId;
@Document(collection = "user")
public class User {
@MongoId
private ObjectId id;
private String name;
private String surname;
private String email;
private int age;
public ObjectId getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
User book = (User) o;
return Objects.equals(id, book.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}

View File

@ -0,0 +1,12 @@
package com.baeldung.multipledb.repository.primary;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import com.baeldung.multipledb.model.User;
@Repository
public interface UserRepository extends MongoRepository<User, String> {
User findByEmail(String email);
}

View File

@ -0,0 +1,12 @@
package com.baeldung.multipledb.repository.secondary;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import com.baeldung.multipledb.model.Account;
@Repository
public interface AccountRepository extends MongoRepository<Account, String> {
Account findByAccountDomain(String account);
}

View File

@ -21,7 +21,6 @@ import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.GroupOperation;
import org.springframework.test.context.TestPropertySource;
import org.springframework.util.SocketUtils;
import com.baeldung.logging.model.Book;
import com.mongodb.client.MongoClients;
@ -34,8 +33,8 @@ import de.flapdoodle.embed.mongo.config.Net;
import de.flapdoodle.embed.mongo.distribution.Version;
import de.flapdoodle.embed.process.runtime.Network;
@SpringBootTest
@TestPropertySource(properties = { "logging.level.org.springframework.data.mongodb.core.MongoTemplate=INFO" })
@SpringBootTest(classes = SpringBootLoggingApplication.class)
@TestPropertySource(properties = {"logging.level.org.springframework.data.mongodb.core.MongoTemplate=INFO"}, value = "/embedded.properties")
public class LoggingUnitTest {
private static final String CONNECTION_STRING = "mongodb://%s:%d";
@ -54,9 +53,9 @@ public class LoggingUnitTest {
int port = Network.freeServerPort(Network.getLocalHost());
ImmutableMongodConfig mongodConfig = MongodConfig.builder()
.version(Version.Main.PRODUCTION)
.net(new Net(ip, port, Network.localhostIsIPv6()))
.build();
.version(Version.Main.PRODUCTION)
.net(new Net(ip, port, Network.localhostIsIPv6()))
.build();
MongodStarter starter = MongodStarter.getDefaultInstance();
mongodExecutable = starter.prepare(mongodConfig);
@ -89,7 +88,7 @@ public class LoggingUnitTest {
mongoTemplate.updateFirst(query(where("bookName").is("Book")), update("authorName", authorNameUpdate), Book.class);
assertThat(mongoTemplate.findById(book.getId(), Book.class)).extracting(Book::getAuthorName)
.isEqualTo(authorNameUpdate);
.isEqualTo(authorNameUpdate);
}
@Test
@ -105,7 +104,7 @@ public class LoggingUnitTest {
mongoTemplate.insert(Arrays.asList(book, book1), Book.class);
assertThat(mongoTemplate.findAll(Book.class)
.size()).isEqualTo(2);
.size()).isEqualTo(2);
}
@Test
@ -119,7 +118,7 @@ public class LoggingUnitTest {
mongoTemplate.remove(book);
assertThat(mongoTemplate.findAll(Book.class)
.size()).isEqualTo(0);
.size()).isEqualTo(0);
}
@Test
@ -139,21 +138,21 @@ public class LoggingUnitTest {
mongoTemplate.insert(Arrays.asList(book, book1, book2), Book.class);
GroupOperation groupByAuthor = group("authorName").count()
.as("authCount");
.as("authCount");
Aggregation aggregation = newAggregation(groupByAuthor);
AggregationResults<GroupByAuthor> aggregationResults = mongoTemplate.aggregate(aggregation, "book", GroupByAuthor.class);
List<GroupByAuthor> groupByAuthorList = StreamSupport.stream(aggregationResults.spliterator(), false)
.collect(Collectors.toList());
.collect(Collectors.toList());
assertThat(groupByAuthorList.stream()
.filter(l -> l.getAuthorName()
.equals("Author"))
.findFirst()
.orElse(null)).extracting(GroupByAuthor::getAuthCount)
.isEqualTo(3);
.filter(l -> l.getAuthorName()
.equals("Author"))
.findFirst()
.orElse(null)).extracting(GroupByAuthor::getAuthCount)
.isEqualTo(3);
}
}

View File

@ -0,0 +1,77 @@
package com.baeldung.multipledb;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Arrays;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import com.baeldung.multipledb.model.Account;
import com.baeldung.multipledb.model.User;
import com.baeldung.multipledb.repository.primary.UserRepository;
import com.baeldung.multipledb.repository.secondary.AccountRepository;
@SpringBootTest(classes = SpringBootMultipleDbApplication.class)
@TestPropertySource("/multipledb/multidb.properties")
public class MultipleDbLiveTest {
@Autowired
private UserRepository userRepository;
@Autowired
private AccountRepository accountRepository;
@BeforeEach
public void setUp() {
userRepository.deleteAll();
accountRepository.deleteAll();
dbSetup();
}
private void dbSetup() {
User person = new User();
person.setName("name");
person.setSurname("surname");
person.setEmail("user@gmail.com");
person.setAge(50);
User another_person = new User();
another_person.setName("another_name");
another_person.setSurname("another_surname");
another_person.setEmail("another_user@hotmail.com");
another_person.setAge(40);
userRepository.saveAll(Arrays.asList(person, another_person));
Account account = new Account();
account.setUserEmail("user@gmail.com");
account.setAccountDomain("account@jira.baeldung.com");
account.setNickName("nickname");
account.setPassword("password");
Account another_account = new Account();
another_account.setUserEmail("another_user@yahoo.com");
another_account.setAccountDomain("another_account@slack.com");
another_account.setNickName("another_nickname");
another_account.setPassword("another_password");
accountRepository.saveAll(Arrays.asList(account, another_account));
}
@Test
void whenFindUserByEmail_thenNameOk() {
assertEquals("name", userRepository.findByEmail("user@gmail.com")
.getName());
}
@Test
void whenFindAccountByDomain_thenNickNameOk() {
assertEquals("nickname", accountRepository.findByAccountDomain("account@jira.baeldung.com")
.getNickName());
}
}

View File

@ -0,0 +1,15 @@
services:
mongo:
hostname: localhost
container_name: 'mongo'
image: 'mongo:latest'
expose:
- 27017
ports:
- 27017:27017
environment:
- MONGO_INITDB_DATABASE=admin
- MONGO_INITDB_ROOT_USERNAME=admin
- MONGO_INITDB_ROOT_PASSWORD=admin
volumes:
- ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js

View File

@ -0,0 +1,15 @@
db.createUser(
{
user: "user1",
pwd: "password",
roles: [{role: "readWrite", db: "db1"}]
}
)
db.createUser(
{
user: "user2",
pwd: "password",
roles: [{role: "readWrite", db: "db2"}]
}
)

View File

@ -0,0 +1,13 @@
mongodb.primary.host=localhost
mongodb.primary.database=db1
mongodb.primary.authenticationDatabase=admin
mongodb.primary.username=user1
mongodb.primary.password=password
mongodb.primary.port=27017
mongodb.secondary.host=localhost
mongodb.secondary.database=db2
mongodb.secondary.authenticationDatabase=admin
mongodb.secondary.username=user2
mongodb.secondary.password=password
mongodb.secondary.port=27017