Spring Boot with Spring Data makes it easy to access a database through so called Repositories. But what if you want to access multiple databases maybe even with different Database Management Systems?
In this post, we will show you how to configure multi data source with the mongoDB using spring boot and spring data.
Project structure
This is a directory structure of the standard gradle project.
Project dependencies
task wrapper(type: Wrapper) { gradleVersion = '3.4.1' } apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'org.springframework.boot' tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } buildscript { ext { springBootVersion = '1.5.4.RELEASE' } repositories { mavenLocal() mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } repositories { mavenLocal() mavenCentral() } dependencies { compile('org.springframework.boot:spring-boot-starter-web:1.4.3.RELEASE') { exclude module: "spring-boot-starter-tomcat" } compile 'org.springframework.boot:spring-boot-starter-jetty:1.4.3.RELEASE' compile 'org.springframework.boot:spring-boot-starter-data-mongodb:1.5.2.RELEASE' compileOnly 'org.projectlombok:lombok:1.16.12' testCompile('org.springframework.boot:spring-boot-starter-test') { exclude(module: 'commons-logging') } }
application.properties file
#mongo db configuration details primary.mongodb.host=127.0.0.1 primary.mongodb.port=27017 primary.mongodb.database=test secondary.mongodb.host=127.0.0.1 secondary.mongodb.port=27017 secondary.mongodb.database=springbatch
Create AbstractMongoConfig class for MongoDB
This class will have the details of database/datasource like hostname, port, and database.
package com.walking.techie.mongo.config; import com.mongodb.MongoClient; import lombok.Data; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.SimpleMongoDbFactory; @Data public abstract class AbstractMongoConfig { //Mongo DB Properties private String host, database; private int port; /* * Method that creates MongoDbFactory * Common to both of the MongoDb connections */ public MongoDbFactory mongoDbFactory() { return new SimpleMongoDbFactory(getMongoClient(), database); } /* * Method that creates MongoClient */ private MongoClient getMongoClient() { return new MongoClient(host, port); } /* * Factory method to create the MongoTemplate */ abstract public MongoTemplate getMongoTemplate(); }
Create configurable connection class for MongoDB
Here we will create two mongo configuration class, one configuration class will act as the primary data source and other will act as the secondary data source. Both classes will extends AbstractMongoConfig class.
package com.walking.techie.mongo.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; @Configuration @EnableMongoRepositories(basePackages = {"com.walking.techie.common.repository", "com.walking.techie.primary.repository"}, mongoTemplateRef = "primaryMongoTemplate") @ConfigurationProperties(prefix = "primary.mongodb") public class PrimaryMongoConnection extends AbstractMongoConfig { /** * Implementation of the MongoTemplate factory method * * @Bean gives a name (primaryMongoTemplate) to the created MongoTemplate instance * @Primary declares that if MongoTemplate is autowired without providing a specific name, this is * the instance which will be mapped by default */ @Primary @Override @Bean(name = "primaryMongoTemplate") public MongoTemplate getMongoTemplate() { return new MongoTemplate(mongoDbFactory()); } }
package com.walking.techie.mongo.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; @Configuration @EnableMongoRepositories( basePackages = {"com.walking.techie.secondary.repository"}, mongoTemplateRef = "secondaryMongoTemplate" ) @ConfigurationProperties(prefix = "secondary.mongodb") public class SecondaryMongoConnection extends AbstractMongoConfig { /** * Implementation of the MongoTemplate factory method * * @Bean gives a name (secondaryMongoTemplate) to the created MongoTemplate instance Note that * this method doesn't have @Primary */ @Override public @Bean(name = "secondaryMongoTemplate") MongoTemplate getMongoTemplate() { return new MongoTemplate(mongoDbFactory()); } }
Create repository
Here creating three repository, in that two repository will use the primary mongo connection, and other will use secondary mongo connection. I have created three packages to have all the repository in separate package to show the flexibility of the configurable connection.
package com.walking.techie.common.repository; import com.walking.techie.model.User; import org.springframework.data.mongodb.repository.MongoRepository; public interface UserRepository extends MongoRepository<User, String> { }
package com.walking.techie.primary.repository; import com.walking.techie.model.Employee; import org.springframework.data.mongodb.repository.MongoRepository; public interface EmployeeRepository extends MongoRepository<Employee, String> { }
package com.walking.techie.secondary.repository; import com.walking.techie.model.Product; import org.springframework.data.mongodb.repository.MongoRepository; public interface ProductRepository extends MongoRepository<Product, String> { }
Java model class
package com.walking.techie.model; import lombok.Data; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.index.Indexed; import org.springframework.data.mongodb.core.mapping.Document; @Document(collection = "user") @Data public class User { @Id private String id; private String name; private String email; @Indexed private int age; }
package com.walking.techie.model; import lombok.Data; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.index.Indexed; import org.springframework.data.mongodb.core.mapping.Document; @Document(collection = "employee") @Data public class Employee { @Id private String id; private String name; private String email; @Indexed private int age; }
package com.walking.techie.model; import lombok.Data; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.index.Indexed; import org.springframework.data.mongodb.core.mapping.Document; @Document(collection = "product") @Data public class Product { @Id private String id; private String name; @Indexed private int price; }
Controller
Here, create a rest controller.
package com.walking.techie.controller; import com.walking.techie.handler.SaveTransaction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("save") public class Transaction { @Autowired private SaveTransaction saveTransaction; @PostMapping public String save() { saveTransaction.save(); return "success"; } }
Handler
Handler will have the logic to store the data into the mongoDB.
package com.walking.techie.handler; public interface SaveTransaction { public void save(); }
package com.walking.techie.handler; import com.walking.techie.common.repository.UserRepository; import com.walking.techie.model.Employee; import com.walking.techie.model.Product; import com.walking.techie.model.User; import com.walking.techie.primary.repository.EmployeeRepository; import com.walking.techie.secondary.repository.ProductRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class SaveTransactionHandler implements SaveTransaction { @Autowired private UserRepository userRepository; @Autowired private ProductRepository productRepository; @Autowired private EmployeeRepository employeeRepository; @Override public void save() { //user details User user = new User(); user.setName("John"); user.setAge(28); user.setEmail("john@gmail.com"); // product details Product product = new Product(); product.setName("Insurance"); product.setPrice(10000); //Employee details Employee employee = new Employee(); employee.setName("Walking Techie"); employee.setAge(26); employee.setEmail("walkingtechie@gmail.com"); //save in DB userRepository.save(user); productRepository.save(product); employeeRepository.save(employee); } }
Run Application
package com.walking.techie; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
Output
Run the web application it will deploy on the embedded jetty server on port 8080. When you call the following url with post method you will get the success as response, after that you can verify in the mongoDB.
localhost:8080/save
Note : This code has been compiled and run on mac notebook and intellij IDEA.
ReplyDeleteThanks for sharing sir,the useful information which is very informative and good points were stated in this article.for more information please visit our website.
MongoDB Training in Hyderabad
how do i use @CreatedDate with this example ... we need @EnableMongoAuditing ?
ReplyDeleteif i use this @EnableMongoAuditing annotation then i found an error
Parameter 0 of constructor in org.springframework.data.mongodb.config.MongoAuditingRegistrar$MongoMappingContextLookup required a bean of type 'org.springframework.data.mongodb.core.convert.MappingMongoConverter' that could not be found.
The following candidates were found but could not be injected:
- Bean method 'mappingMongoConverter' in 'MongoDataAutoConfiguration' not loaded because AnyNestedCondition 0 matched 2 did not; NestedCondition on MongoDataAutoConfiguration.AnyMongoClientAvailable.FallbackClientAvailable @ConditionalOnBean (types: com.mongodb.client.MongoClient; SearchStrategy: all) did not find any beans of type com.mongodb.client.MongoClient; NestedCondition on MongoDataAutoConfiguration.AnyMongoClientAvailable.PreferredClientAvailable @ConditionalOnBean (types: com.mongodb.MongoClient; SearchStrategy: all) did not find any beans of type com.mongodb.MongoClient
- Bean method 'mappingMongoConverter' in 'MongoReactiveDataAutoConfiguration' not loaded because @ConditionalOnClass did not find required class 'com.mongodb.reactivestreams.client.MongoClient'
How to work on this if my mongo db is LDAP authenticated
ReplyDeleteIt's very useful blog post with inforamtive and insightful content and i had good experience with this information.
ReplyDeleteoracle training in chennai
oracle training institute in chennai
oracle training in bangalore
oracle training in hyderabad
oracle training
hadoop training in chennai
hadoop training in bangalore
Thanks for sharing.Keep post.
ReplyDeleteMachine Learning training in Pallikranai Chennai
Data science training in Pallikaranai
Python Training in Pallikaranai chennai
Bigdata training in Pallikaranai chennai
Spark with ML training in Pallikaranai chennai
nice information ..........!
ReplyDeletespring boot certification course training
nice.............!
ReplyDeletespring boot certification course training
It's very useful blog post with inforamtive and insightful content and i had good experience with this information.
ReplyDeletehttps://onlineitguru.com/uipath-online-training