Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- As per my current knowledge of Spring, Spring-data and Spring-data-mongodb I've ended up whith this solution:
- ----------
- **config/MultipleMongoProperties.java**
- ```
- package com.mycompany.myapp.config;
- import lombok.Data;
- import org.springframework.boot.autoconfigure.mongo.MongoProperties;
- import org.springframework.boot.context.properties.ConfigurationProperties;
- @Data
- @ConfigurationProperties(prefix = "database.mongodb")
- public class MultipleMongoProperties {
- private MongoProperties orange = new MongoProperties();
- private MongoProperties banana = new MongoProperties();
- private MongoProperties peach = new MongoProperties();
- }
- ```
- **config/MultipleMongoConfig.java**
- ```
- package com.mycompany.myapp.config;
- import com.mongodb.*;
- import lombok.RequiredArgsConstructor;
- import org.apache.catalina.Server;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.boot.autoconfigure.mongo.MongoProperties;
- 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.MongoDbFactory;
- import org.springframework.data.mongodb.core.MongoTemplate;
- import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
- import static com.mongodb.WriteConcern.ACKNOWLEDGED;
- import static java.lang.String.format;
- import static java.util.Collections.singletonList;
- import java.util.Arrays;
- import java.util.Collections;
- import java.util.Optional;
- @Configuration
- @RequiredArgsConstructor
- @EnableConfigurationProperties(MultipleMongoProperties.class)
- public class MultipleMongoConfig {
- private final MultipleMongoProperties mongoProperties;
- private static final Logger LOGGER = LoggerFactory.getLogger(MultipleMongoConfig.class);
- @Primary
- @Bean(name = "orangeMongoTemplate")
- public MongoTemplate orangeMongoTemplate() {
- return new MongoTemplate(orangeFactory(this.mongoProperties.getOrange()));
- }
- @Bean(name = "bananaMongoTemplate")
- public MongoTemplate bananaMongoTemplate() {
- return new MongoTemplate(bananaFactory(this.mongoProperties.getBanana()));
- }
- @Bean(name = "peachMongoTemplate")
- public MongoTemplate peachMongoTemplate() {
- return new MongoTemplate(peachFactory(this.mongoProperties.getPeach()));
- }
- @Bean
- @Primary
- public MongoDbFactory orangeFactory(final MongoProperties mongo) {
- return getFactory(mongo);
- }
- @Bean
- public MongoDbFactory bananaFactory(final MongoProperties mongo) {
- return getFactory(mongo);
- }
- @Bean
- public MongoDbFactory peachFactory(final MongoProperties mongo) {
- return getFactory(mongo);
- }
- public SimpleMongoDbFactory getFactory(MongoProperties mongo){
- MongoClientOptions options = MongoClientOptions.builder()
- .connectTimeout(5000)
- .socketTimeout(8000)
- .readPreference(ReadPreference.secondaryPreferred())
- .writeConcern(ACKNOWLEDGED)
- .build();
- MongoCredential credential;
- MongoClient client;
- Optional<String> username= Optional.ofNullable(mongo.getUsername());
- Optional<char[]> password = Optional.ofNullable(mongo.getPassword());
- Optional<String> authDbName = Optional.ofNullable(mongo.getAuthenticationDatabase());
- Optional<String> database = Optional.ofNullable(mongo.getDatabase());
- Optional<String> uri = Optional.ofNullable(mongo.getUri());
- Optional<String> host = Optional.ofNullable(mongo.getHost());
- Optional<Integer> port = Optional.ofNullable(mongo.getPort());
- if (! database.isPresent()) {
- String msg = format("database parameter is required and was not specified. {%s}", mongo);
- LOGGER.error(msg);
- throw new RuntimeException(msg);
- }
- if (uri.isPresent()) {
- String url = uri.get();
- LOGGER.info("URI IS PRESENT. " + url);
- LOGGER.info(format("URI specified [%s]. This will take precedence over host and port settings.", url));
- Optional<String> authString=Optional.empty();
- if (username.isPresent() && password.isPresent()) {
- authString = Optional.of(format("%s:%s", username.get(), new String(password.get())));
- }
- StringBuilder sb = new StringBuilder();
- if ( ! url.matches("^mongodb://")) sb.append("mongodb://");
- if ( ! url.contains("@") && authString.isPresent()){
- sb.append(authString.get()).append("@");
- }
- sb.append(url);
- if ( ! url.contains("/") && authDbName.isPresent()){
- sb.append("/").append(authDbName.get());
- }
- LOGGER.info(format("URI resolved to: %s",sb.toString()));
- client = new MongoClient(new MongoClientURI(sb.toString()));
- return new SimpleMongoDbFactory(client, database.get());
- }
- ServerAddress a = new ServerAddress(host.orElse("localhost"), port.orElse(27017));
- LOGGER.debug(format("Address resolved to %s",a));
- if ( ! username.isPresent() || ! password.isPresent()) {
- String msg = format("Some of the auth parameters were not specified: {%s} will try connection without authentication", mongo);
- LOGGER.info(msg);
- client = new MongoClient(singletonList(a),options);
- return new SimpleMongoDbFactory(client,database.get());
- }
- MongoCredential cred = MongoCredential.createCredential(username.get(), authDbName.get(),password.get());
- client = new MongoClient(singletonList(a),cred,options);
- return new SimpleMongoDbFactory(client, database.get());
- }
- private static int sizeOfValue(String value){
- if (value == null) return 0;
- return value.length();
- }
- private static boolean valueIsMissing(String value){
- return sizeOfValue(value) == 0;
- }
- private static boolean valueIsPresent(String value){
- return ! valueIsMissing(value);
- }
- private static boolean valueIsPresent(char[] charSequence){
- return valueIsPresent(new String(charSequence));
- }
- }
- ```
- **config/CustomerOrangeMongoConfig.java**
- ```
- package com.mycompany.myapp.config;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
- @Configuration
- @EnableMongoRepositories(basePackages = "com.mycompany.myapp.model.orange",
- mongoTemplateRef = "orangeMongoTemplate")
- public class CustomerOrangeMongoConfig {
- }
- ```
- **config/CustomerBananaMongoConfig**
- ```
- package com.mycompany.myapp.config;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
- @Configuration
- @EnableMongoRepositories(basePackages = "com.mycompany.myapp.model.banana",
- mongoTemplateRef = "bananaMongoTemplate")
- public class CustomerBananaMongoConfig {
- }
- ```
- **config/PeachMongoConfig**
- ```
- package com.mycompany.myapp.config;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
- @Configuration
- @EnableMongoRepositories(basePackages = "com.mycompany.myapp.model.peach",
- mongoTemplateRef = "peachMongoTemplate")
- public class AlerterMongoConfig {
- }
- ```
- **model/Customer.java**
- ```
- package com.mycompany.myapp.model;
- import com.fasterxml.jackson.annotation.JsonInclude;
- import lombok.Data;
- import org.springframework.data.annotation.Id;
- import java.util.List;
- @Data
- @JsonInclude(JsonInclude.Include.NON_NULL)
- public class Customer {
- @Id
- String id;
- String fiscalId;
- String email;
- String gender;
- String birthdate;
- String lastName;
- String firstName;
- //and so on...
- }
- ```
- **model/banana/BananaCustomer.java**
- ```
- package com.mycompany.myapp.model.banana;
- import com.mycompany.myapp.model.Customer;
- import org.springframework.data.mongodb.core.mapping.Document;
- @Document(collection = "customers")
- public class BananaCustomer extends Customer {
- }
- ```
- **model/banana/CustomerBananaRepository.java**
- ```
- package com.mycompany.myapp.model.banana;
- import org.springframework.data.mongodb.repository.MongoRepository;
- import org.springframework.data.mongodb.repository.Query;
- import java.util.List;
- public interface CustomerBananaRepository extends MongoRepository<BananaCustomer, String> {
- List<BananaCustomer> findAllByFiscalId(String fiscalId);
- List<BananaCustomer> findAllByEmail(String email);
- }
- ```
- **model/orange/OrangeCustomer.java**
- ```
- package com.mycompany.myapp.model.orange;
- import com.mycompany.myapp.model.Customer;
- import org.springframework.data.mongodb.core.mapping.Document;
- @Document(collection = "customers")
- public class OrangeCustomer extends Customer {
- }
- ```
- **model/orange/CustomerOrangeRepo.java**
- ```
- package com.mycompany.myapp.model.orange;
- import org.springframework.data.mongodb.repository.MongoRepository;
- import org.springframework.data.mongodb.repository.Query;
- import java.util.List;
- public interface CustomerOrangeRepo extends MongoRepository<OrangeCustomer, String> {
- List<OrangeCustomer> findAllByFiscalId(String fiscalId);
- List<OrangeCustomer> findAllByEmail(String email);
- }
- ```
- And last, but not least
- **service/CustomerService.java**
- ```
- package com.mycompany.myapp.service;
- import com.mycompany.myapp.model.Customer;
- import com.mycompany.myapp.model.banana.CustomerBananaRepository;
- import com.mycompany.myapp.model.orange.CustomerOrangeRepo;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import java.time.LocalDateTime;
- import java.util.Collection;
- import java.util.List;
- import java.util.Optional;
- import java.util.stream.Collectors;
- import java.util.stream.Stream;
- @Service
- public class CustomerService {
- private final CustomerOrangeRepo customerOrangeRepo;
- private final CustomerBananaRepository customerBananaRepository;
- @Autowired
- public CustomerService(CustomerOrangeRepo customerOrangeRepo, CustomerBananaRepository customerBananaRepository) {
- this.customerOrangeRepo = customerOrangeRepo;
- this.customerBananaRepository = customerBananaRepository;
- }
- public List<? extends Customer> findAllByEmail(String email) {
- return Stream.concat(
- customerOrangeRepo.findAllByEmail(email).stream(),
- customerBananaRepository.findAllByEmail(email).stream())
- .collect(Collectors.toList());
- }
- }
- ```
- Notice these things:
- - I've renamed all references to my company and project name in compliance to all these sweet NDA's that i've signed up. Sorry for any inconsistency
- - My service knows both BananaRepository and OrangeRepository and call them both to collect customers from both repos
- - There are two identical types extending from customer. I need this to make them available to both mongo repositories.
- - My service returns a List of ? extends Customers just because of that. Remember that java generics doesn't recognize inheritance when typing <somehing>
- - The mongo **repository interface must live within the model class** (in the very same package). This is mandatory or it won't work.
- - There is some magic going on with these property resolvers. So I have to define the database properties like this:
- ```
- database.mongodb.banana.username=username
- database.mongodb.orange.username=username
- database.mongodb.peach.username=username
- ```
- - The "peach" mongodb has nothing to do with my problem. It's just another mongodb config for a third mongo instance, that I used for a completely different purpose (Storing events, indeed)
Add Comment
Please, Sign In to add comment