/user/create - insert record in MongoDB database.
/user/ - fetch all the records from MongoDb database.
/user/{userId} - select a particular record from MongoDB database.
/user/settings/{userId} - retrieve records from MongoDB database for specific {userId}.
/user/settings/{userId}/{key} - retrieve records from MongoDB database for specific {userId} and {key}.
/user/settings/{userId}/{key}/{value} - update {value} for sepecific {userId} and {key}.
Here is the high level application’s architecture with MongoDB integration.
Note: It depends on requirement, suppose user wants to retrieve data in real-time, we should opt for a nonrelational database. If, on the other hand, your biggest concern is having information you can trust no matter what, a relational database is your best option. Also, there’s a third choice that might not be obvious: you can use both in your application.
We can download MongoDB .msi from MongoDB official site or https://www.filehorse.com/download-mongodb/42707/download/
Once downloading completed, you may install .msi file by clicking on next -> next button.
Now, you can download and install GUI for MongoDB as below.
Download URL: https://www.mongodb.com/try/download/compass
You may download .msi or .zip file from website and install in your local machine.
First of all we need to Create Database. E.g. bootdb
MongoDB backend is ready for storing Collection and Documents. Now we will create a Spring Boot Rest Application for create, fetch and update operations.
Java 8
Maven 3.5.0
Spring Boot
Eclipse
Spring Boot Starter Data MongoDB
Spring Boot Rest API
MongoDB 4.2.0
MongoDB Compass 1.27.1
Application maven file (pom.xml) would be looked like as below.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>spring-boot-data-mongodb</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-boot-data-mongodb</name>
<description>Demo project for Spring Boot Data - Mongo DB</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
#Local MongoDB config
spring.data.mongodb.database=bootdb
#spring.data.mongodb.username=root
#spring.data.mongodb.password=root
spring.data.mongodb.port=27017
spring.data.mongodb.host=localhost
#app config
server.port=8102
spring.application.name=SpringBootMongo
server.context-path=/user
package com.the.basic.tech.info.mongodb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootMongoDBApp {
public static void main(String[] args) {
SpringApplication.run(SpringBootMongoDBApp.class, args);
}
}
In this class Rest APIs exposed for the enduser.
package com.the.basic.tech.info.mongodb.controller;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.the.basic.tech.info.mongodb.dal.UserInterface;
import com.the.basic.tech.info.mongodb.dal.UserRepository;
import com.the.basic.tech.info.mongodb.model.User;
@RestController
@RequestMapping(value = "/")
public class UserController {
private final Logger LOG = LoggerFactory.getLogger(getClass());
private final UserRepository userRepository; //MongoRepository
private final UserInterface userInferface; //MongoTemplate
public UserController(UserRepository userRepository, UserInterface userInferface) {
this.userRepository = userRepository;
this.userInferface = userInferface;
}
/*
* In Postman select post method, Body -> raw -> JSON(application/json)
*/
@RequestMapping(value = "/create", method = RequestMethod.POST)
public User addNewUsers(@RequestBody User user) {
LOG.info("Saving user.");
return userRepository.save(user);
}
@RequestMapping(value = "", method = RequestMethod.GET)
public List<User> getAllUsers() {
LOG.info("Getting all users.");
return userRepository.findAll();
}
@RequestMapping(value = "/{userId}", method = RequestMethod.GET)
public User getUser(@PathVariable String userId) {
LOG.info("Getting user with ID: {}.", userId);
return userRepository.findOne(userId);
}
@RequestMapping(value = "/settings/{userId}", method = RequestMethod.GET)
public Object getAllUserSettings(@PathVariable String userId) {
User user = userRepository.findOne(userId);
if (user != null) {
return userInferface.getAllUserSettings(userId);
} else {
return "User not found.";
}
}
@RequestMapping(value = "/settings/{userId}/{key}", method = RequestMethod.GET)
public String getUserSetting(@PathVariable String userId, @PathVariable String key) {
return userInferface.getUserSetting(userId, key);
}
@RequestMapping(value = "/settings/{userId}/{key}/{value}", method = RequestMethod.GET)
public String addUserSetting(@PathVariable String userId, @PathVariable String key, @PathVariable String value) {
User user = userRepository.findOne(userId);
if (user != null) {
user.getUserSettings().put(key, value);
userRepository.save(user);
return "Key added";
} else {
return "User not found.";
}
}
}
DAO Layer: UserInterface.java
package com.the.basic.tech.info.mongodb.dao;
import java.util.List;
import com.the.basic.tech.info.mongodb.model.User;
public interface UserInterface {
List<User> getAllUsers();
User getUserById(String userId);
User addNewUser(User user);
Object getAllUserSettings(String userId);
String getUserSetting(String userId, String key);
String addUserSetting(String userId, String key, String value);
}
DAO Layer: UserRepository.java
package com.the.basic.tech.info.mongodb.dao;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import com.the.basic.tech.info.mongodb.model.User;
@Repository
public interface UserRepository extends MongoRepository<User, String> {
}
DAO Layer: UserInterfaceImpl.java
package com.the.basic.tech.info.mongodb.dao;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;
import com.the.basic.tech.info.mongodb.model.User;
@Repository
public class UserInterfaceImpl implements UserInterface {
@Autowired
private MongoTemplate mongoTemplate;
@Override
public List<User> getAllUsers() {
return mongoTemplate.findAll(User.class);
}
@Override
public User getUserById(String userId) {
Query query = new Query();
query.addCriteria(Criteria.where("userId").is(userId));
return mongoTemplate.findOne(query, User.class);
}
@Override
public User addNewUser(User user) {
mongoTemplate.save(user);
// Now, user object will contain the ID as well
return user;
}
@Override
public Object getAllUserSettings(String userId) {
Query query = new Query();
query.addCriteria(Criteria.where("userId").is(userId));
User user = mongoTemplate.findOne(query, User.class);
return user != null ? user.getUserSettings() : "User not found.";
}
@Override
public String getUserSetting(String userId, String key) {
Query query = new Query();
query.fields().include("userSettings");
query.addCriteria(Criteria.where("userId").is(userId).andOperator(Criteria.where("userSettings." + key).exists(true)));
User user = mongoTemplate.findOne(query, User.class);
return user != null ? user.getUserSettings().get(key) : "Not found.";
}
@Override
public String addUserSetting(String userId, String key, String value) {
Query query = new Query();
query.addCriteria(Criteria.where("userId").is(userId));
User user = mongoTemplate.findOne(query, User.class);
if (user != null) {
user.getUserSettings().put(key, value);
mongoTemplate.save(user);
return "Key added.";
} else {
return "User not found.";
}
}
}
Model Layer: User.java
package com.the.basic.tech.info.mongodb.model;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document
public class User {
@Id
private String userId;
private String name;
private Date creationDate = new Date();
private Map<String, String> userSettings = new HashMap<>();
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
public Map<String, String> getUserSettings() {
return userSettings;
}
public void setUserSettings(Map<String, String> userSettings) {
this.userSettings = userSettings;
}
}
We need to add below PostConstruct configuration to remove _class from document, otherwise by default additional attribute will be displayed wih _class name under document record.
package com.the.basic.tech.info.mongodb;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
@Configuration
public class MongoDbConfiguration {
@Autowired
private MappingMongoConverter mappingMongoConverter;
// remove _class
@PostConstruct
public void setUpMongoEscapeCharacterConversion() {
mappingMongoConverter.setTypeMapper(new DefaultMongoTypeMapper(null));
}
}
Run spring-boot-data-mongodb: mvn spring-boot:run
D:developmentspring-boot-data-mongodb>mvn spring-boot:run
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building spring-boot-data-mongodb 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> spring-boot-maven-plugin:1.5.9.RELEASE:run (default-cli) > test-compile @ spring-boot-data-mongodb >>>
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ spring-boot-data-mongodb ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ spring-boot-data-mongodb ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 7 source files to D:developmentspring-boot-data-mongodbtargetclasses
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ spring-boot-data-mongodb ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:developmentspring-boot-data-mongodbsrctestresources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ spring-boot-data-mongodb ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] <<< spring-boot-maven-plugin:1.5.9.RELEASE:run (default-cli) < test-compile @ spring-boot-data-mongodb <<<
[INFO]
[INFO]
[INFO] --- spring-boot-maven-plugin:1.5.9.RELEASE:run (default-cli) @ spring-boot-data-mongodb ---
. ____ _ __ _ _
/\ / ___'_ __ _ _(_)_ __ __ _
( ( )___ | '_ | '_| | '_ / _` |
\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |___, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.9.RELEASE)
2021-07-06 14:35:17.616 INFO 33404 --- [ main] c.t.b.t.i.mongodb.SpringBootMongoDBApp : Starting SpringBootMongoDBApp on LOCALHOST with PID 33404 (D:developmentspring-boot-data-mongodbtargetclasses started by 172025 in D:developmentspring-boot-data-mongodb)
2021-07-06 14:35:17.627 INFO 33404 --- [ main] c.t.b.t.i.mongodb.SpringBootMongoDBApp : No active profile set, falling back to default profiles: default
2021-07-06 14:35:17.731 INFO 33404 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@9ce86e2: startup date [Tue Jul 06 14:35:17 IST 2021]; root of context hierarchy
2021-07-06 14:35:21.456 INFO 33404 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8102 (http)
2021-07-06 14:35:21.475 INFO 33404 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-07-06 14:35:21.477 INFO 33404 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.23
2021-07-06 14:35:21.728 INFO 33404 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/user] : Initializing Spring embedded WebApplicationContext
2021-07-06 14:35:21.736 INFO 33404 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 4014 ms
2021-07-06 14:35:22.043 INFO 33404 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2021-07-06 14:35:22.054 INFO 33404 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]
2021-07-06 14:35:22.057 INFO 33404 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2021-07-06 14:35:22.060 INFO 33404 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2021-07-06 14:35:22.066 INFO 33404 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*]
2021-07-06 14:35:24.470 INFO 33404 --- [ main] org.mongodb.driver.cluster : Cluster created with settings {hosts=[localhost:27017], mode=MULTIPLE, requiredClusterType=UNKNOWN, serverSelectionTimeout='30000 ms', maxWaitQueueSize=500}
2021-07-06 14:35:24.472 INFO 33404 --- [ main] org.mongodb.driver.cluster : Adding discovered server localhost:27017 to client view of cluster
2021-07-06 14:35:24.602 INFO 33404 --- [localhost:27017] org.mongodb.driver.connection : Opened connection [connectionId{localValue:1, serverValue:44}] to localhost:27017
2021-07-06 14:35:24.606 INFO 33404 --- [localhost:27017] org.mongodb.driver.cluster : Monitor thread successfully connected to server with description ServerDescription{address=localhost:27017, type=STANDALONE, state=CONNECTED, ok=true, version=ServerVersion{versionList=[4, 2, 0]}, minWireVersion=0, maxWireVersion=8, maxDocumentSize=16777216, roundTripTimeNanos=1007800}
2021-07-06 14:35:24.611 INFO 33404 --- [localhost:27017] org.mongodb.driver.cluster : Discovered cluster type of STANDALONE
2021-07-06 14:35:25.448 INFO 33404 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@9ce86e2: startup date [Tue Jul 06 14:35:17 IST 2021]; root of context hierarchy
2021-07-06 14:35:25.602 INFO 33404 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/settings/{userId}],methods=[GET]}" onto public java.lang.Object com.the.basic.tech.info.mongodb.controller.UserController.getAllUserSettings(java.lang.String)
2021-07-06 14:35:25.610 INFO 33404 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/settings/{userId}/{key}/{value}],methods=[GET]}" onto public java.lang.String com.the.basic.tech.info.mongodb.controller.UserController.addUserSetting(java.lang.String,java.lang.String,java.lang.String)
2021-07-06 14:35:25.617 INFO 33404 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/create],methods=[POST]}" onto public com.the.basic.tech.info.mongodb.model.User com.the.basic.tech.info.mongodb.controller.UserController.addNewUsers(com.the.basic.tech.info.mongodb.model.User)
2021-07-06 14:35:25.622 INFO 33404 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/{userId}],methods=[GET]}" onto public com.the.basic.tech.info.mongodb.model.User com.the.basic.tech.info.mongodb.controller.UserController.getUser(java.lang.String)
2021-07-06 14:35:25.644 INFO 33404 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/],methods=[GET]}" onto public java.util.List<com.the.basic.tech.info.mongodb.model.User> com.the.basic.tech.info.mongodb.controller.UserController.getAllUsers()
2021-07-06 14:35:25.655 INFO 33404 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/settings/{userId}/{key}],methods=[GET]}" onto public java.lang.String com.the.basic.tech.info.mongodb.controller.UserController.getUserSetting(java.lang.String,java.lang.String)
2021-07-06 14:35:25.678 INFO 33404 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2021-07-06 14:35:25.705 INFO 33404 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2021-07-06 14:35:25.809 INFO 33404 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2021-07-06 14:35:25.819 INFO 33404 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2021-07-06 14:35:26.020 INFO 33404 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2021-07-06 14:35:26.418 INFO 33404 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2021-07-06 14:35:26.604 INFO 33404 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8102 (http)
2021-07-06 14:35:26.619 INFO 33404 --- [ main] c.t.b.t.i.mongodb.SpringBootMongoDBApp : Started SpringBootMongoDBApp in 9.672 seconds (JVM running for 21.001)
Post following data to the end point /user/create/ from PostMan.
{
"name" : "the basic tech info",
"userSettings" : {
"domain" : "java, J2EE",
"framework" : "Spring, Spring Boot, Hibernate",
"microservice patterns" : "zuul, ribbon, hystrix, eureka"
}
}
2021-07-06 14:47:13.578 INFO 33404 --- [nio-8102-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/user] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2021-07-06 14:47:13.581 INFO 33404 --- [nio-8102-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2021-07-06 14:47:13.628 INFO 33404 --- [nio-8102-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 46 ms
2021-07-06 14:47:13.947 INFO 33404 --- [nio-8102-exec-1] c.t.b.t.i.m.controller.UserController : Saving user.
2021-07-06 14:47:14.057 INFO 33404 --- [nio-8102-exec-1] org.mongodb.driver.connection : Opened connection [connectionId{localValue:2, serverValue:45}] to localhost:27017
URL: http://localhost:8102/user/settings/60e4230d1584a3827cf3f037/framework
URL: http://localhost:8102/user/settings/60e4230d1584a3827cf3f037/framework/Java8
Now, we can see updated document/record as below. Here, key {framework} has been updated with Java8 value in second record as displayed in below snapshot.
Happy learning. Drop me your questions in comments section if any 🙂