Guest User

Untitled

a guest
Feb 11th, 2019
149
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.71 KB | None | 0 0
  1. As per my current knowledge of Spring, Spring-data and Spring-data-mongodb I've ended up whith this solution:
  2.  
  3. ----------
  4. **config/MultipleMongoProperties.java**
  5. ```
  6. package com.mycompany.myapp.config;
  7.  
  8.  
  9. import lombok.Data;
  10. import org.springframework.boot.autoconfigure.mongo.MongoProperties;
  11. import org.springframework.boot.context.properties.ConfigurationProperties;
  12.  
  13. @Data
  14. @ConfigurationProperties(prefix = "database.mongodb")
  15. public class MultipleMongoProperties {
  16. private MongoProperties orange = new MongoProperties();
  17. private MongoProperties banana = new MongoProperties();
  18. private MongoProperties peach = new MongoProperties();
  19. }
  20. ```
  21.  
  22. **config/MultipleMongoConfig.java**
  23.  
  24. ```
  25. package com.mycompany.myapp.config;
  26.  
  27. import com.mongodb.*;
  28. import lombok.RequiredArgsConstructor;
  29. import org.apache.catalina.Server;
  30. import org.slf4j.Logger;
  31. import org.slf4j.LoggerFactory;
  32. import org.springframework.boot.autoconfigure.mongo.MongoProperties;
  33. import org.springframework.boot.context.properties.EnableConfigurationProperties;
  34. import org.springframework.context.annotation.Bean;
  35. import org.springframework.context.annotation.Configuration;
  36. import org.springframework.context.annotation.Primary;
  37. import org.springframework.data.mongodb.MongoDbFactory;
  38. import org.springframework.data.mongodb.core.MongoTemplate;
  39. import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
  40.  
  41. import static com.mongodb.WriteConcern.ACKNOWLEDGED;
  42. import static java.lang.String.format;
  43. import static java.util.Collections.singletonList;
  44.  
  45.  
  46. import java.util.Arrays;
  47. import java.util.Collections;
  48. import java.util.Optional;
  49.  
  50.  
  51. @Configuration
  52. @RequiredArgsConstructor
  53. @EnableConfigurationProperties(MultipleMongoProperties.class)
  54. public class MultipleMongoConfig {
  55.  
  56. private final MultipleMongoProperties mongoProperties;
  57.  
  58. private static final Logger LOGGER = LoggerFactory.getLogger(MultipleMongoConfig.class);
  59.  
  60. @Primary
  61. @Bean(name = "orangeMongoTemplate")
  62. public MongoTemplate orangeMongoTemplate() {
  63. return new MongoTemplate(orangeFactory(this.mongoProperties.getOrange()));
  64. }
  65.  
  66. @Bean(name = "bananaMongoTemplate")
  67. public MongoTemplate bananaMongoTemplate() {
  68. return new MongoTemplate(bananaFactory(this.mongoProperties.getBanana()));
  69. }
  70.  
  71. @Bean(name = "peachMongoTemplate")
  72. public MongoTemplate peachMongoTemplate() {
  73. return new MongoTemplate(peachFactory(this.mongoProperties.getPeach()));
  74. }
  75.  
  76. @Bean
  77. @Primary
  78. public MongoDbFactory orangeFactory(final MongoProperties mongo) {
  79.  
  80. return getFactory(mongo);
  81. }
  82.  
  83. @Bean
  84. public MongoDbFactory bananaFactory(final MongoProperties mongo) {
  85.  
  86. return getFactory(mongo);
  87. }
  88.  
  89. @Bean
  90. public MongoDbFactory peachFactory(final MongoProperties mongo) {
  91.  
  92. return getFactory(mongo);
  93. }
  94.  
  95. public SimpleMongoDbFactory getFactory(MongoProperties mongo){
  96.  
  97. MongoClientOptions options = MongoClientOptions.builder()
  98. .connectTimeout(5000)
  99. .socketTimeout(8000)
  100. .readPreference(ReadPreference.secondaryPreferred())
  101. .writeConcern(ACKNOWLEDGED)
  102. .build();
  103.  
  104. MongoCredential credential;
  105. MongoClient client;
  106.  
  107. Optional<String> username= Optional.ofNullable(mongo.getUsername());
  108. Optional<char[]> password = Optional.ofNullable(mongo.getPassword());
  109. Optional<String> authDbName = Optional.ofNullable(mongo.getAuthenticationDatabase());
  110. Optional<String> database = Optional.ofNullable(mongo.getDatabase());
  111. Optional<String> uri = Optional.ofNullable(mongo.getUri());
  112. Optional<String> host = Optional.ofNullable(mongo.getHost());
  113. Optional<Integer> port = Optional.ofNullable(mongo.getPort());
  114.  
  115. if (! database.isPresent()) {
  116. String msg = format("database parameter is required and was not specified. {%s}", mongo);
  117. LOGGER.error(msg);
  118. throw new RuntimeException(msg);
  119. }
  120.  
  121. if (uri.isPresent()) {
  122. String url = uri.get();
  123. LOGGER.info("URI IS PRESENT. " + url);
  124. LOGGER.info(format("URI specified [%s]. This will take precedence over host and port settings.", url));
  125. Optional<String> authString=Optional.empty();
  126. if (username.isPresent() && password.isPresent()) {
  127. authString = Optional.of(format("%s:%s", username.get(), new String(password.get())));
  128. }
  129. StringBuilder sb = new StringBuilder();
  130. if ( ! url.matches("^mongodb://")) sb.append("mongodb://");
  131. if ( ! url.contains("@") && authString.isPresent()){
  132. sb.append(authString.get()).append("@");
  133. }
  134. sb.append(url);
  135. if ( ! url.contains("/") && authDbName.isPresent()){
  136. sb.append("/").append(authDbName.get());
  137. }
  138.  
  139. LOGGER.info(format("URI resolved to: %s",sb.toString()));
  140. client = new MongoClient(new MongoClientURI(sb.toString()));
  141.  
  142. return new SimpleMongoDbFactory(client, database.get());
  143. }
  144.  
  145.  
  146. ServerAddress a = new ServerAddress(host.orElse("localhost"), port.orElse(27017));
  147. LOGGER.debug(format("Address resolved to %s",a));
  148.  
  149. if ( ! username.isPresent() || ! password.isPresent()) {
  150. String msg = format("Some of the auth parameters were not specified: {%s} will try connection without authentication", mongo);
  151. LOGGER.info(msg);
  152. client = new MongoClient(singletonList(a),options);
  153. return new SimpleMongoDbFactory(client,database.get());
  154. }
  155.  
  156. MongoCredential cred = MongoCredential.createCredential(username.get(), authDbName.get(),password.get());
  157.  
  158. client = new MongoClient(singletonList(a),cred,options);
  159. return new SimpleMongoDbFactory(client, database.get());
  160. }
  161.  
  162.  
  163. private static int sizeOfValue(String value){
  164. if (value == null) return 0;
  165. return value.length();
  166. }
  167. private static boolean valueIsMissing(String value){
  168. return sizeOfValue(value) == 0;
  169. }
  170. private static boolean valueIsPresent(String value){
  171. return ! valueIsMissing(value);
  172. }
  173.  
  174. private static boolean valueIsPresent(char[] charSequence){
  175. return valueIsPresent(new String(charSequence));
  176. }
  177. }
  178.  
  179. ```
  180.  
  181. **config/CustomerOrangeMongoConfig.java**
  182. ```
  183. package com.mycompany.myapp.config;
  184.  
  185. import org.springframework.context.annotation.Configuration;
  186. import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
  187. @Configuration
  188. @EnableMongoRepositories(basePackages = "com.mycompany.myapp.model.orange",
  189. mongoTemplateRef = "orangeMongoTemplate")
  190. public class CustomerOrangeMongoConfig {
  191.  
  192. }
  193.  
  194. ```
  195.  
  196. **config/CustomerBananaMongoConfig**
  197. ```
  198. package com.mycompany.myapp.config;
  199.  
  200.  
  201. import org.springframework.context.annotation.Configuration;
  202. import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
  203.  
  204. @Configuration
  205. @EnableMongoRepositories(basePackages = "com.mycompany.myapp.model.banana",
  206. mongoTemplateRef = "bananaMongoTemplate")
  207. public class CustomerBananaMongoConfig {
  208.  
  209. }
  210. ```
  211.  
  212. **config/PeachMongoConfig**
  213. ```
  214. package com.mycompany.myapp.config;
  215.  
  216. import org.springframework.context.annotation.Configuration;
  217. import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
  218.  
  219. @Configuration
  220. @EnableMongoRepositories(basePackages = "com.mycompany.myapp.model.peach",
  221. mongoTemplateRef = "peachMongoTemplate")
  222. public class AlerterMongoConfig {
  223.  
  224. }
  225.  
  226. ```
  227. **model/Customer.java**
  228. ```
  229. package com.mycompany.myapp.model;
  230.  
  231. import com.fasterxml.jackson.annotation.JsonInclude;
  232. import lombok.Data;
  233. import org.springframework.data.annotation.Id;
  234.  
  235. import java.util.List;
  236.  
  237. @Data
  238. @JsonInclude(JsonInclude.Include.NON_NULL)
  239. public class Customer {
  240. @Id
  241. String id;
  242. String fiscalId;
  243. String email;
  244. String gender;
  245. String birthdate;
  246. String lastName;
  247. String firstName;
  248. //and so on...
  249.  
  250. }
  251.  
  252. ```
  253.  
  254. **model/banana/BananaCustomer.java**
  255. ```
  256. package com.mycompany.myapp.model.banana;
  257.  
  258. import com.mycompany.myapp.model.Customer;
  259. import org.springframework.data.mongodb.core.mapping.Document;
  260.  
  261. @Document(collection = "customers")
  262. public class BananaCustomer extends Customer {
  263.  
  264. }
  265.  
  266. ```
  267. **model/banana/CustomerBananaRepository.java**
  268. ```
  269. package com.mycompany.myapp.model.banana;
  270.  
  271. import org.springframework.data.mongodb.repository.MongoRepository;
  272. import org.springframework.data.mongodb.repository.Query;
  273.  
  274. import java.util.List;
  275.  
  276. public interface CustomerBananaRepository extends MongoRepository<BananaCustomer, String> {
  277. List<BananaCustomer> findAllByFiscalId(String fiscalId);
  278.  
  279. List<BananaCustomer> findAllByEmail(String email);
  280. }
  281.  
  282. ```
  283.  
  284. **model/orange/OrangeCustomer.java**
  285. ```
  286. package com.mycompany.myapp.model.orange;
  287.  
  288. import com.mycompany.myapp.model.Customer;
  289. import org.springframework.data.mongodb.core.mapping.Document;
  290.  
  291. @Document(collection = "customers")
  292. public class OrangeCustomer extends Customer {
  293.  
  294. }
  295.  
  296. ```
  297. **model/orange/CustomerOrangeRepo.java**
  298. ```
  299. package com.mycompany.myapp.model.orange;
  300.  
  301. import org.springframework.data.mongodb.repository.MongoRepository;
  302. import org.springframework.data.mongodb.repository.Query;
  303.  
  304. import java.util.List;
  305.  
  306.  
  307. public interface CustomerOrangeRepo extends MongoRepository<OrangeCustomer, String> {
  308.  
  309. List<OrangeCustomer> findAllByFiscalId(String fiscalId);
  310.  
  311. List<OrangeCustomer> findAllByEmail(String email);
  312. }
  313.  
  314. ```
  315. And last, but not least
  316.  
  317. **service/CustomerService.java**
  318. ```
  319. package com.mycompany.myapp.service;
  320.  
  321. import com.mycompany.myapp.model.Customer;
  322. import com.mycompany.myapp.model.banana.CustomerBananaRepository;
  323. import com.mycompany.myapp.model.orange.CustomerOrangeRepo;
  324. import org.springframework.beans.factory.annotation.Autowired;
  325. import org.springframework.stereotype.Service;
  326.  
  327. import java.time.LocalDateTime;
  328. import java.util.Collection;
  329. import java.util.List;
  330. import java.util.Optional;
  331. import java.util.stream.Collectors;
  332. import java.util.stream.Stream;
  333.  
  334. @Service
  335. public class CustomerService {
  336.  
  337. private final CustomerOrangeRepo customerOrangeRepo;
  338.  
  339. private final CustomerBananaRepository customerBananaRepository;
  340.  
  341. @Autowired
  342. public CustomerService(CustomerOrangeRepo customerOrangeRepo, CustomerBananaRepository customerBananaRepository) {
  343.  
  344. this.customerOrangeRepo = customerOrangeRepo;
  345. this.customerBananaRepository = customerBananaRepository;
  346.  
  347. }
  348.  
  349.  
  350.  
  351. public List<? extends Customer> findAllByEmail(String email) {
  352. return Stream.concat(
  353. customerOrangeRepo.findAllByEmail(email).stream(),
  354. customerBananaRepository.findAllByEmail(email).stream())
  355. .collect(Collectors.toList());
  356. }
  357. }
  358.  
  359. ```
  360.  
  361. Notice these things:
  362.  
  363. - 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
  364. - My service knows both BananaRepository and OrangeRepository and call them both to collect customers from both repos
  365. - There are two identical types extending from customer. I need this to make them available to both mongo repositories.
  366. - My service returns a List of ? extends Customers just because of that. Remember that java generics doesn't recognize inheritance when typing <somehing>
  367. - The mongo **repository interface must live within the model class** (in the very same package). This is mandatory or it won't work.
  368. - There is some magic going on with these property resolvers. So I have to define the database properties like this:
  369. ```
  370. database.mongodb.banana.username=username
  371. database.mongodb.orange.username=username
  372. database.mongodb.peach.username=username
  373. ```
  374. - 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