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.
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);
}
}
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.
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.