Build REST CRUD APIs with Spring Boot, Azure Cosmos DB and Azure Cosmos DB SQL API
Hello everyone, Hope you are doing well. In this tutorial, you will learn how to build REST CRUD APIs with Spring Boot, Azure Cosmos DB, and Azure Cosmos DB SQL API.
A little bit of Background
Azure Cosmos DB
Azure Cosmos DB is a fully managed NoSQL database for modern app development. Single-digit millisecond response times, and automatic and instant scalability, guarantee speed at any scale.
Azure Cosmos DB SQL API
Azure Cosmos DB SQL API accounts provide support for querying items using the Structured Query Language (SQL) syntax.
Spring Boot
Spring Boot makes it easy to create stand-alone, production-grade Spring-based Applications that you can "just run".
More Info - https://spring.io/projects/spring-boot
After completing this tutorial what we will build?
We will build REST APIs CRUD features:
Step 1: Sign in to Azure Portal and create a resource group
Sign in to Azure portal https://portal.azure.com/#home and find "Resource groups" like below.
Then, create a resource group like the one below.
Step 2: Create an Azure Cosmos DB
Select "Azure Cosmos DB",
You will be taken to a page like the below image, Then click on the "Create Azure Cosmos DB account" button.
Create Azure Cosmos DB Account - Core (SQL),
You will be taken to a page like the below image,
Then click on the "Create" button.
Now, You can see "Deployment is in progress" like the below image.
Once deployment is completed you can see the "Your deployment is complete" page like the below image.
You will be taken to a page like the below image,
Step 3: Add Container
Next enter "Database id", "Container id" etc...
Step 4: Creating a simple spring boot web application.
First, open the Spring initializr https://start.spring.io/
Then, Provide the Group and Artifact name. We have provided Group name com.knf.dev.demo and Artifact spring-boot-azure-cosmos-db-sql-api-crud. Here I selected the Maven project - language Java - Spring Boot 2.7.1 and add Spring web dependency and Azure Cosmos DB dependency.
Then, click on the Generate button. When we click on the Generate button, it starts packing the project in a .zip(spring-boot-azure-cosmos-db-sql-api-crud.zip) file and downloads the project.
Then, Extract the Zip file.
Step 5: Import the project on your favourite IDE, I am using Eclipse IDE
Import the project File -> Import -> Maven ->Existing Maven Project -> Next -> Browse -> Select the project -> Finish
Final Project Directory:
Pom.xml
<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.knf.dev.demo</groupId>
<artifactId>spring-boot-azure-cosmos-db-sql-api-crud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-azure-cosmos-db-sql-api-crud</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
<spring-cloud-azure.version>4.2.0</spring-cloud-azure.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-data-cosmos</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-dependencies</artifactId>
<version>${spring-cloud-azure.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yaml
Configure your Spring Boot application to use your Azure Cosmos DB
spring:
cloud:
azure:
cosmos:
database: <Database id>
populate-query-metrics: true
endpoint: <URI>
key: <PRIMARY KEY>
Create User Model
package com.knf.dev.demo.entity;
import org.springframework.data.annotation.Id;
import com.azure.spring.data.cosmos.core.mapping.Container;
import com.azure.spring.data.cosmos.core.mapping.GeneratedValue;
@Container(containerName = "User")
public class User {
@Id
@GeneratedValue
private String id;
private String firstName;
private String lastName;
private String email;
public User() {
}
public User(String firstName,
String lastName, String email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
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 getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
- @Id annotation is currently used by Spring to support mapping for other non-relational persistence databases or frameworks that do not have a defined common persistence API like JPA.
- @Container: Annotation for Cosmos Container
- @GeneratedValue: Used to specify that an entities id field should generate a value
Create User Repository
package com.knf.dev.demo.repository;
import com.azure.spring.data.cosmos.repository.CosmosRepository;
import com.knf.dev.demo.entity.User;
public interface UserRepository
extends CosmosRepository<User, String> {
}
Extends CosmosRepository interface, which provides Spring Data repository support.
Create Unknown Exception
package com.knf.dev.demo.exception;
public class UnKnownException extends RuntimeException {
private static final long serialVersionUID = 1L;
public UnKnownException(String msg) {
super(msg);
}
}
Create User Not Found Exception
package com.knf.dev.demo.exception;
public class UserNotFound extends RuntimeException {
private static final long serialVersionUID = 1L;
public UserNotFound(String msg) {
super(msg);
}
}
Create Global Exception Handler
package com.knf.dev.demo.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UnknownError.class)
public ResponseEntity<String> internalServerError
(Exception ex, WebRequest request) {
return new ResponseEntity<>(ex.getMessage(),
HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler(UserNotFound.class)
public ResponseEntity<String> userNotFound
(Exception ex, WebRequest request) {
return new ResponseEntity<>(ex.getMessage(),
HttpStatus.NOT_FOUND);
}
}
Create Rest Controller
package com.knf.dev.demo.controller;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.knf.dev.demo.entity.User;
import com.knf.dev.demo.exception.UnKnownException;
import com.knf.dev.demo.exception.UserNotFound;
import com.knf.dev.demo.repository.UserRepository;
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
@Autowired
UserRepository userRepository;
// Create user
@PostMapping
public ResponseEntity<User> createUser
(@RequestBody User user) {
try {
User newuser = new User(user.getFirstName(),
user.getLastName(), user.getEmail());
userRepository.save(newuser);
return new ResponseEntity<>(newuser,
HttpStatus.CREATED);
} catch (Exception e) {
throw new UnKnownException(e.getMessage());
}
}
// Update user
@PutMapping("/{id}")
public ResponseEntity<User> updateUser
(@PathVariable("id") String id,
@RequestBody User user) {
Optional<User> userdata = userRepository
.findById(id);
if (userdata.isPresent()) {
User _user = userdata.get();
_user.setEmail(user.getEmail());
_user.setFirstName(user.getFirstName());
_user.setLastName(user.getLastName());
return new ResponseEntity<>
(userRepository.save(_user), HttpStatus.OK);
} else {
throw new UserNotFound("Invalid User Id");
}
}
// Get all Users
@GetMapping
public ResponseEntity<List<User>> getAllUsers() {
try {
List<User> users = new ArrayList<User>();
userRepository.findAll().forEach(users::add);
return new ResponseEntity<>
(users, HttpStatus.OK);
} catch (Exception e) {
throw new UnKnownException(e.getMessage());
}
}
// Get user by ID
@GetMapping("/{id}")
public ResponseEntity<User> getUserByID
(@PathVariable("id") String id) {
Optional<User> userdata = userRepository
.findById(id);
if (userdata.isPresent()) {
return new ResponseEntity<>(userdata.get(),
HttpStatus.OK);
} else {
throw new UserNotFound("Invalid User Id");
}
}
// Delete user
@DeleteMapping("/{id}")
public ResponseEntity<User> deleteUser
(@PathVariable("id") String id) {
Optional<User> userdata = userRepository
.findById(id);
if (userdata.isPresent()) {
userRepository.deleteById(id);
return new ResponseEntity<>
(HttpStatus.NO_CONTENT);
} else {
throw new UserNotFound("Invalid User Id");
}
}
}
Spring Boot Main Driver
package com.knf.dev.demo;
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);
}
}
Step 6: Local Setup and Run the application
Step 1: Download or clone the source code from GitHub to a local machine - Click here
Step 2: mvn clean install
Step 3: Run the Spring Boot application -
mvn spring-boot:run