Getting Started with CRUD Operations in Spring Boot and DynamoDB: A Beginner’s Guide

Matheshyogeswaran
LinkIT
Published in
6 min readSep 8, 2023

An In-Depth Introduction to Creating, Reading, Updating, and Deleting Data in Spring Boot and DynamoDB for Beginners

Artwork by Author

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.

Creating Spring Boot Project in Spring Initializr

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”

Search IAM

2. Click on IAM

Click on IAM

3. Click on Users

Click on Users

4. Click on mathesh

Click on mathesh

5. Click on Security Credentials

Click on Security Credentials

6. Click on Create access key

Click on Create access key

7. Select Local code

Select Local code

8. Check I understand the above recommendation and want to proceed to create an access key.

Check the box

9. Click on Next

Click on Next

10. Type the description

Type the description

11. Click on Create access key

Click on Create access key

12. Click on Download .csv file

Click on Download .csv file

13. Click on Done

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

Search DynamoDB

2. Click on DynamoDB

Click on DynamoDB

3. Click on Create Table

Click on Create Table

4. Type “Product”

Type “Product”

5. Type “id” as the partition key

Type “id” as the partition key

6. Click on Create Table

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.

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!💻

--

--

Matheshyogeswaran
LinkIT
Writer for

Undergraduate at the University of Moratuwa, Trainee Software Engineer, and tech enthusiast exploring cloud computing and software development.