Getting Started with CRUD Operations in Spring Boot and DynamoDB: A Beginner’s Guide
An In-Depth Introduction to Creating, Reading, Updating, and Deleting Data in Spring Boot and DynamoDB for Beginners
Welcome to this beginner-friendly tutorial, where we’ll explore the world of creating, reading, updating, and deleting data (CRUD) in Spring Boot applications. We’ll focus on using DynamoDB, a powerful and scalable database service from Amazon Web Services (AWS). Our goal is to help you understand how to build CRUD operations while organizing your project effectively.
Getting Started with Spring Boot
Let’s jump right in by creating a basic Spring Boot application. Follow these steps:
Go to Spring Initializr.
Choose the Maven project option.
Select the ‘Spring Web’ and ‘lombok’ dependencies.
Click the ‘Generate’ button to initiate project generation.
Organizing Your Project
Once the project is generated, open it in IntelliJ IDEA. Our first task is to establish a well-structured file hierarchy. Your project structure should look like this:
my-spring-boot-dynamodb-app/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ ├── com/
│ │ │ │ ├── myapp/
│ │ │ │ │ ├── config/
│ │ │ │ │ │ ├── DynamoDBConfig.java # DynamoDB configuration
│ │ │ │ │ ├── controller/
│ │ │ │ │ │ ├── ProductController.java # REST API controllers
│ │ │ │ │ ├── model/
│ │ │ │ │ │ ├── Product.java # Product entity class
│ │ │ │ │ │ ├── ProductDTO.java # Product Data Transfer Object
│ │ │ │ │ ├── service/
│ │ │ │ │ │ ├── ProductService.java # Service layer interfaces
│ │ │ │ │ │ ├── ProductServiceImpl.java # Service layer implementation
│ │ │ │ │ ├── Application.java # Spring Boot main application class
│ │ ├── resources/
│ │ │ ├── application.properties # Application-specific properties
├── test/
- Controller: Contains the REST API controllers for handling HTTP requests and responses.
- Model: Defines the data models or entities of your application.
- Service: Implements business logic and acts as an intermediary between controllers and repositories.
- Impl: Contains the actual implementations of service interfaces.
- Resources: Contains application configuration files and static resources.
- Application.properties: Configuration file for Spring Boot application properties like database configuration.
- DynamoDBConfig.java: This Java class is responsible for configuring the connection to DynamoDB. It’s where you’d set AWS credentials and DynamoDB endpoint details.
Include AWS dependency
Ensure that you include the required AWS dependencies in your project’s pom.xml. To do so, add the following dependency snippet to your pom.xml file:
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-dynamodb</artifactId>
<version>1.12.272</version>
</dependency>
Database Configuration: application.properties
The main focus here is connecting to DynamoDB, and the steps for obtaining the AWS access key and secret key are crucial:
1. Go to the AWS console and Type “iam”
2. Click on IAM
3. Click on Users
4. Click on mathesh
5. Click on Security Credentials
6. Click on Create access key
7. Select Local code
8. Check I understand the above recommendation and want to proceed to create an access key.
9. Click on Next
10. Type the description
11. Click on Create access key
12. Click on Download .csv file
13. Click on Done
From this, you can get the aws.access.key and aws.access.secret-key. Then, you need to create the DynamoDB instance, and you can get the aws.dynamodb.endpoint as shown below:
server:
#Spring Boot Applicaiton Port
port: 8080
#Endpoint that application might connect to
aws.dynamodb.endpoint: https://dynamodb.<Your dynamoDB instance located>.amazonaws.com
# Access credentials for the aws programmatic access. Please make sure that you donot share this information with others or commit
# it to public.
aws.access.key: <Your access key>
aws.access.secret-key: <Your secret key>
# your AWS region where dynamo db instance is located.
aws.region: <Your dynamoDB instance located>
The Entity: Product.java
Before this, you need to create the DynamoDB in AWS. Follow these steps:
1. Search DynamoDB
2. Click on DynamoDB
3. Click on Create Table
4. Type “Product”
5. Type “id” as the partition key
6. Click on Create Table
Let’s create the entity class that represents our product:
package com.crudDynamo.CrudDynamo.model;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAutoGeneratedKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
import lombok.Data;
@DynamoDBTable(tableName = "Product") // This must be the same as in DynamoDB
@Data
public class Product {
@DynamoDBHashKey(attributeName = "id")
@DynamoDBAutoGeneratedKey
private String id;
@DynamoDBAttribute
private String name;
@DynamoDBAttribute
private double price;
@DynamoDBAttribute
private Long stockCount;
}
ProductDTO.java
package com.crudDynamo.CrudDynamo.model;
import lombok.Data;
@Data
public class ProductDTO {
private String id;
private String name;
private double price;
private Long stockCount;
}
Implementing Business Logic: ProductServiceBL.java
package com.crudDynamo.CrudDynamo.service.BL;
import com.crudDynamo.CrudDynamo.model.ProductDTO;
import java.util.List;
public interface ProductServiceBL {
List<ProductDTO> getAllProducts();
ProductDTO getProductById(String id);
ProductDTO createNewProduct(ProductDTO dto);
ProductDTO updateProduct(String id, ProductDTO dto);
void deleteProduct(String id);
}
ProductServiceImpl.java
package com.crudDynamo.CrudDynamo.service.Impl;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBScanExpression;
import com.crudDynamo.CrudDynamo.model.Product;
import com.crudDynamo.CrudDynamo.model.ProductDTO;
import com.crudDynamo.CrudDynamo.service.BL.ProductServiceBL;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class ProductServiceImpl implements ProductServiceBL {
private final DynamoDBMapper dynamoDBMapper;
public ProductServiceImpl(DynamoDBMapper dynamoDBMapper) {
this.dynamoDBMapper = dynamoDBMapper;
}
@Override
public List<ProductDTO> getAllProducts() {
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression();
List<Product> products = dynamoDBMapper.scan(Product.class, scanExpression);
return products.stream().map(this::convertToDTO).collect(Collectors.toList());
}
@Override
public ProductDTO getProductById(String id) {
Product product = dynamoDBMapper.load(Product.class, id);
return convertToDTO(product);
}
@Override
public ProductDTO createNewProduct(ProductDTO dto) {
Product product = new Product();
BeanUtils.copyProperties(dto, product);
dynamoDBMapper.save(product);
return convertToDTO(product);
}
@Override
public ProductDTO updateProduct(String id, ProductDTO dto) {
Product product = dynamoDBMapper.load(Product.class, id);
BeanUtils.copyProperties(dto, product);
dynamoDBMapper.save(product);
return convertToDTO(product);
}
@Override
public void deleteProduct(String id) {
Product product = dynamoDBMapper.load(Product.class, id);
if (product != null) {
dynamoDBMapper.delete(product);
}
}
private ProductDTO convertToDTO(Product product) {
ProductDTO dto = new ProductDTO();
BeanUtils.copyProperties(product, dto);
return dto;
}
}
ProductController.java
package com.crudDynamo.CrudDynamo.controller;
import com.crudDynamo.CrudDynamo.model.ProductDTO;
import com.crudDynamo.CrudDynamo.service.BL.ProductServiceBL;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/products")
public class ProductController {
private final ProductServiceBL productServiceBL;
public ProductController(ProductServiceBL productServiceBL) {
this.productServiceBL = productServiceBL;
}
@GetMapping
public List<ProductDTO> getAllProducts() {
return productServiceBL.getAllProducts();
}
@GetMapping("/{id}")
public ProductDTO getProductById(@PathVariable String id) {
return productServiceBL.getProductById(id);
}
@PostMapping
public ProductDTO createProduct(@RequestBody ProductDTO productDTO) {
return productServiceBL.createNewProduct(productDTO);
}
@PutMapping("/{id}")
public ProductDTO updateProduct(@PathVariable String id, @RequestBody ProductDTO productDTO) {
return productServiceBL.updateProduct(id, productDTO);
}
@DeleteMapping("/{id}")
public void deleteProduct(@PathVariable String id) {
productServiceBL.deleteProduct(id);
}
}
Here, we’ll provide a visual illustration of how our CRUD application operates using Postman.
Conclusion
In conclusion, we delved into building CRUD applications with Spring Boot and DynamoDB. You’ve learned essential concepts such as project setup, code organization, database configuration, entity class creation, business logic implementation, and REST API endpoints. To access the full source code with detailed examples, visit our GitHub repository. Feel free to connect with me on LinkedIn. Happy coding!💻