Build Rest CRUD API with Micronaut and MongoDB
Hello everyone. Today we will learn how to develop REST-style CRUD APIs with MongoDB and Micronaut. You can download the source code from our Github repository.
After completing this tutorial what we will build?
We will build REST API CRUD features:
- GET - Fetch all User : /api/v1/users
- GET - Get User by ID : /api/v1/users/{id}
- POST - Create User : /api/v1/users
- PUT - Edit User Details : /api/v1/users/
- DELETE - Delete User : /api/v1/users/{id}
Technologies used:
- Micronaut 3.1.1
- MongoDB
- Mongo Synch 3.1.1
- Maven
- Java 11
Project Directory:
Maven[pom.xml]
A Project Object Model or POM is the fundamental unit of work in Maven. It is an XML file that contains information about the project and configuration details utilized by Maven to build the project. It contains default values for most projects. Some of the configurations that can be designated in the POM is the project dependencies, the plugins or goals that can be executed, the build profiles, and so on. Other information such as the project version, description, developers, mailing lists and such can withal be designated.
<?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.knf.dev.demo</groupId>
<artifactId>micronaut-mongodb-crud</artifactId>
<version>0.1</version>
<packaging>${packaging}</packaging>
<parent>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-parent</artifactId>
<version>3.1.1</version>
</parent>
<properties>
<packaging>jar</packaging>
<jdk.version>11</jdk.version>
<release.version>11</release.version>
<micronaut.version>3.1.1</micronaut.version>
<exec.mainClass>com.knf.dev.demo.Application</exec.mainClass>
<micronaut.runtime>netty</micronaut.runtime>
</properties>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-validation</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-server-netty</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-client</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-runtime</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut.mongodb</groupId>
<artifactId>micronaut-mongo-sync</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut.test</groupId>
<artifactId>micronaut-test-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>2.0.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.micronaut.build</groupId>
<artifactId>micronaut-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- Uncomment to enable incremental compilation -->
<!-- <useIncrementalCompilation>false</useIncrementalCompilation> -->
<annotationProcessorPaths>
<path>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject-java</artifactId>
<version>${micronaut.version}</version>
</path>
<path>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-validation</artifactId>
<version>${micronaut.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<arg>-Amicronaut.processing.group=com.knf.dev.demo</arg>
<arg>-Amicronaut.processing.module=micronaut-mongodb-crud</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.yaml
micronaut:
application:
name: micronautMongodbCrud
mongodb.uri: mongodb://localhost:27017
Create Document - User.java
package com.knf.dev.demo.entity;
import io.micronaut.core.annotation.Introspected;
@Introspected
public class User {
private String id;
private String firstName;
private String lastName;
private String emailId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
public User(String id, String firstName, String lastName, String emailId) {
super();
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.emailId = emailId;
}
public User() {
super();
}
}
Create UserRepository.java
package com.knf.dev.demo.repository.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
import com.knf.dev.demo.entity.User;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.model.Filters;
import jakarta.inject.Singleton;
@Singleton
public class UserRepository {
private final MongoClient mongoClient;
public UserRepository(MongoClient mongoClient) {
this.mongoClient = mongoClient;
}
private MongoCollection<Document> getCollection() {
return mongoClient.getDatabase("user-test").
getCollection("user-test");
}
public User saveUser(User user) {
Document document = new Document().append("firstName",
user.getFirstName())
.append("lastName", user.getLastName()).
append("emailId", user.getEmailId());
getCollection().insertOne(document);
user.setId(document.getObjectId("_id").toString());
return user;
}
public User updateUser(String id, User user) {
Optional<Document> optionalDocument = findDocumentById(id);
if (optionalDocument.isPresent()) {
Document document = optionalDocument.get();
document.put("firstName", user.getFirstName());
document.put("lastName", user.getLastName());
document.put("emailId", user.getEmailId());
Bson bsonFilter = Filters.eq("_id", new ObjectId(id));
getCollection().replaceOne(bsonFilter, document);
}
return user;
}
public List<User> findAll() {
List<User> users = new ArrayList<>();
MongoCursor<Document> cursor = getCollection().find().
iterator();
try {
while (cursor.hasNext()) {
Document document = cursor.next();
User user = new User();
user.setLastName(document.getString("lastName"));
user.setFirstName(document.getString("firstName"));
user.setEmailId(document.getString("emailId"));
user.setId(String.valueOf(document.getObjectId("_id")));
users.add(user);
}
} finally {
cursor.close();
}
return users;
}
public Optional<User> findUserById(String id) {
return findDocumentById(id).map(this::mapUser);
}
public void deleteUserById(String id) {
Bson bsonFilter = Filters.eq("_id", new ObjectId(id));
getCollection().deleteOne(bsonFilter);
}
private Optional<Document> findDocumentById(String id) {
Bson bsonFilter = Filters.eq("_id", new ObjectId(id));
try (MongoCursor<Document> iterator = getCollection().
find(bsonFilter).iterator()) {
return iterator.hasNext() ? Optional.
of(iterator.next()) : Optional.empty();
}
}
private User mapUser(Document document) {
User user = new User();
user.setId(document.getObjectId("_id").toString());
user.setEmailId(document.getString("emailId"));
user.setLastName(document.getString("lastName"));
user.setFirstName(document.getString("firstName"));
return user;
}
}
Create UserController.java
package com.knf.dev.demo.contoller;
import java.util.List;
import java.util.Optional;
import com.knf.dev.demo.entity.User;
import com.knf.dev.demo.repository.impl.UserRepository;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Delete;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Post;
import io.micronaut.http.annotation.Put;
import jakarta.inject.Inject;
@Controller("/api/users")
public class UserController {
@Inject
UserRepository userRepository;
@Get
public List<User> getUsers() {
return userRepository.findAll();
}
@Get("/{id}")
public Optional<User> getUser(String id) {
return userRepository.findUserById(id);
}
@Post
public HttpResponse<User> addUser(@Body User user) {
userRepository.saveUser(user);
return HttpResponse.created(user);
}
@Put("/{id}")
public HttpResponse<User> updateUser(String id, @Body User user) {
userRepository.updateUser(id, user);
return HttpResponse.created(user);
}
@Delete("/{id}")
public HttpResponse<Void> delete(String id) {
userRepository.deleteUserById(id);
return HttpResponse.noContent();
}
}
Create Main Class
package com.knf.dev.demo;
import io.micronaut.runtime.Micronaut;
public class Application {
public static void main(String[] args) {
Micronaut.run(Application.class, args);
}
}
Verify REST APIs
Run as Java Application
or
mvn mn:run