Spring Boot 3 Astra DB CRUD Example

In this section, we will learn how to build REST CRUD APIs with Spring Boot, and Astra DB.

Astra DB

DataStax Astra DB is a cloud-native, scalable Database-as-a-Service built on Apache Cassandra.


Create a Database

First, Sign into the datastax at https://astra.datastax.com.

Then click on the "Databases" button.


You will be taken to a page like the below image, then click on the "Create Database" button.


Then enter Database name, Provider, and, Region
, then click on the "Create Database" button.


Now, You can see "Your database is initializing..." like the below image.

You will be taken to a page like the below image.

Copy "Database ID" and "region name" and keep them for future purposes.


Generate Application Token

Mocking

Then click on "Tokens" button.


You will be taken to a page like the below image,


Then select role, for demo purpose here we selected role "Administrator User".


Then click on "Generate Token" button.


Copy the application "token" and keep it for future purposes.


Creating a spring boot 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-astra-db-crud. Here I selected the Maven project - language Java 17 - Spring Boot 3.3.0, and Spring Data for Apache Cassandra.


Then, click on the Generate button. When we click on the Generate button, it starts packing the project in a .zip(spring-boot-astra-db-crud) file and downloads the project. Then, Extract the Zip file. 
Then, import the project on your favourite IDE.
 


Final Project Directory


In the pom.xml, add the Astra Spring Boot starter dependency:

<dependency>
<groupId>com.datastax.astra</groupId>
<artifactId>astra-spring-boot-3x-starter</artifactId>
<version>1.2.7</version>
</dependency>


Complete 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>3.3.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.knf.dev.demo</groupId>
<artifactId>spring-boot-astra-db-crud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-astra-db-crud</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-cassandra</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.datastax.astra</groupId>
<artifactId>astra-spring-boot-3x-starter</artifactId>
<version>1.2.7</version>
</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>


application.yaml

spring:
cassandra:
schema-action: CREATE_IF_NOT_EXISTS
astra:
api:
application-token: <APPLICATION-TOKEN>
database-id: <DATABASE-ID>
database-region: <REGION>
cross-region-failback: false
grpc:
enabled: true
cql:
enabled: true
download-scb:
# if disabled zip files must be in folder (path)
enabled: true
# Looking for files scb_dbid-dbregion.zip in folder (default is ~/.astra/scb)
# path: /tmp
driver-config:
basic:
session-keyspace: default_keyspace

  • The spring.data.cassandra.schema-action property defines the schema action to take at startup and can be none, create, create-if-not-exists, recreate or recreate-drop-unused. We use create-if-not-exists to create the required schema. 
  • The starter introduce a set of keys prefixed with astra.*. Replace the values with expected values . 
  • **Important note** Do not publish the values directly for security.
  • For demo purpose we are using the default keyspace, that is default_keyspace.


Create Student Entity

package com.knf.dev.demo.entity;

import org.springframework.data.cassandra.core.mapping.PrimaryKey;
import org.springframework.data.cassandra.core.mapping.Table;

import java.util.Set;
import java.util.UUID;

@Table
public class Student {

@PrimaryKey
private UUID id;
private String name;
private String email;
private Set<String> qualifications;

public Student() {
}

public Student(UUID id, String name,
String email, Set<String> qualifications) {
this.id = id;
this.name = name;
this.email = email;
this.qualifications = qualifications;
}

public UUID getId() {
return id;
}

public void setId(UUID id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public Set<String> getQualifications() {
return qualifications;
}

public void setQualifications(Set<String> qualifications) {
this.qualifications = qualifications;
}
}

The Student class is annotated with @Table, which maps it to a Cassandra Table. Each property is mapped to a column. The class uses a simple @PrimaryKey of type UUID. 


Create Student Repository

package com.knf.dev.demo.repository;

import com.knf.dev.demo.entity.Student;
import org.springframework.data.cassandra.repository.CassandraRepository;

import java.util.List;
import java.util.UUID;

public interface StudentRepository extends CassandraRepository<Student, UUID> {

}

StudentRepository extends the CassandraRepository interface and specifies types for the generic type parameters for both the value and the key that the repository works with — Student and UUID, respectively. This interface comes with many operations, including basic CRUD (Create, Read, Update, Delete) and simple query (such as findById(..)) data access operations.


Create EntityNotFoundException

package com.knf.dev.demo.exception;

public class EntityNotFoundException extends RuntimeException {
private static final long serialVersionUID = 1L;

public EntityNotFoundException(String message) {
super(message);
}

}


Create CustomErrorResponse

package com.knf.dev.demo.exception;

import com.fasterxml.jackson.annotation.JsonFormat;

import java.time.LocalDateTime;

public class CustomErrorResponse {

@JsonFormat(shape = JsonFormat.Shape.STRING,
pattern = "yyyy-MM-dd hh:mm:ss")
private LocalDateTime timestamp;
private int status;
private String error;

public LocalDateTime getTimestamp() {
return timestamp;
}

public void setTimestamp(LocalDateTime timestamp) {
this.timestamp = timestamp;
}

public int getStatus() {
return status;
}

public void setStatus(int status) {
this.status = status;
}

public String getError() {
return error;
}

public void setError(String error) {
this.error = error;
}
}


Create GlobalExceptionHandler

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;

import java.time.LocalDateTime;

@ControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity<CustomErrorResponse>
globalExceptionHandler(Exception ex, WebRequest request) {

CustomErrorResponse errors = new CustomErrorResponse();
errors.setTimestamp(LocalDateTime.now());
errors.setError(ex.getMessage());
errors.setStatus(HttpStatus.NOT_FOUND.value());
return new ResponseEntity<>(errors, HttpStatus.NOT_FOUND);
}
}


Create Student Controller

package com.knf.dev.demo.controller;

import com.knf.dev.demo.entity.Student;
import com.knf.dev.demo.exception.EntityNotFoundException;
import com.knf.dev.demo.repository.StudentRepository;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.UUID;

@RestController
@RequestMapping("/api/v1/student")
public class StudentController {

private final StudentRepository studentRepository;

public StudentController(StudentRepository studentRepository) {
this.studentRepository = studentRepository;
}

@GetMapping
public List<Student> findAllStudent() {
return studentRepository.findAll();
}

@GetMapping("/{id}")
public Student findStudentById(@PathVariable UUID id) {
Student student = studentRepository.findById(id)
.orElseThrow(() -> new EntityNotFoundException("Entity not found"));
return student;
}

@PostMapping
public Student addStudent(@RequestBody Student student) {
student.setId(UUID.randomUUID());
return studentRepository.save(student);
}

@PutMapping("/{id}")
public Student updateStudent(@RequestBody Student s, @PathVariable UUID id) {
Student student = studentRepository.findById(id)
.orElseThrow(() -> new EntityNotFoundException("Entity not found"));
student.setQualifications(s.getQualifications());
student.setEmail(s.getEmail());
student.setName(s.getName());
return studentRepository.save(student);
}

@DeleteMapping("/{id}")
public boolean removeStudent(@PathVariable UUID id) {
Student student = studentRepository.findById(id)
.orElseThrow(() -> new EntityNotFoundException("Entity not found"));
studentRepository.delete(student);
return true;
}
}


Run the application - Application.java

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);
}
}
Application is the entry point that sets up the Spring Boot application. The @SpringBootApplication annotation enables auto-configuration and component scanning. 

Step1: 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


OR 


Run this Spring boot application from 

  • IntelliJ IDEA IDE by right click - Run 'Application.main()' 
  • Eclipse/STS - You can right click the project or the Application.java file and run as java application or Spring boot application.

Add Student


Update Student


Fetch all Student


Student by Id


Delete Student

Source code - click here!

Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete