This guide shows how to integrate AWS DynamoDB with Spring Boot using Spring Cloud AWS starter and implement CRUD operations.
Setup
1. Add Dependencies
<dependency>
<groupId>io.awspring.cloud</groupId>
<artifactId>spring-cloud-aws-starter-dynamodb</artifactId>
<version>3.3.0</version>
</dependency>
<!-- Also include Spring Boot Starter Web if building a web app -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2. Configure AWS Credentials
Add to application.properties
or application.yml
:
# AWS configuration
spring.cloud.aws.credentials.access-key=YOUR_ACCESS_KEY
spring.cloud.aws.credentials.secret-key=YOUR_SECRET_KEY
spring.cloud.aws.region.static=us-east-1
# Optional - if you want to use local DynamoDB for testing
spring.cloud.aws.dynamodb.endpoint=http://localhost:8000
Entity Class
Create a model class with DynamoDB annotations:
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
@DynamoDbBean
public class Product {
private String id;
private String name;
private Double price;
private Integer stock;
@DynamoDbPartitionKey
public String getId() {
return id;
}
// Standard getters and setters
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public Integer getStock() {
return stock;
}
public void setStock(Integer stock) {
this.stock = stock;
}
}
Repository Layer
Create a repository class to handle DynamoDB operations:
import org.springframework.stereotype.Repository;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.Key;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import java.util.List;
import java.util.stream.Collectors;
@Repository
public class ProductRepository {
private final DynamoDbEnhancedClient enhancedClient;
private final DynamoDbTable<Product> productTable;
public ProductRepository(DynamoDbEnhancedClient enhancedClient) {
this.enhancedClient = enhancedClient;
this.productTable = enhancedClient.table("Product", TableSchema.fromBean(Product.class));
}
public Product save(Product product) {
productTable.putItem(product);
return product;
}
public Product findById(String id) {
Key key = Key.builder().partitionValue(id).build();
return productTable.getItem(key);
}
public List<Product> findAll() {
return productTable.scan().items().stream().collect(Collectors.toList());
}
public Product update(Product product) {
return productTable.updateItem(product);
}
public void deleteById(String id) {
Key key = Key.builder().partitionValue(id).build();
productTable.deleteItem(key);
}
}
Service Layer
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ProductService {
private final ProductRepository productRepository;
public ProductService(ProductRepository productRepository) {
this.productRepository = productRepository;
}
public Product createProduct(Product product) {
return productRepository.save(product);
}
public Product getProduct(String id) {
return productRepository.findById(id);
}
public List<Product> getAllProducts() {
return productRepository.findAll();
}
public Product updateProduct(Product product) {
return productRepository.update(product);
}
public void deleteProduct(String id) {
productRepository.deleteById(id);
}
}
Controller Layer
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/products")
public class ProductController {
private final ProductService productService;
public ProductController(ProductService productService) {
this.productService = productService;
}
@PostMapping
public Product createProduct(@RequestBody Product product) {
return productService.createProduct(product);
}
@GetMapping("/{id}")
public Product getProduct(@PathVariable String id) {
return productService.getProduct(id);
}
@GetMapping
public List<Product> getAllProducts() {
return productService.getAllProducts();
}
@PutMapping("/{id}")
public Product updateProduct(@PathVariable String id, @RequestBody Product product) {
product.setId(id);
return productService.updateProduct(product);
}
@DeleteMapping("/{id}")
public void deleteProduct(@PathVariable String id) {
productService.deleteProduct(id);
}
}
Main Application Class
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DynamoDbApplication {
public static void main(String[] args) {
SpringApplication.run(DynamoDbApplication.class, args);
}
}
Additional Configuration (Optional)
If you need to customize the DynamoDB client:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
@Configuration
public class DynamoDbConfig {
@Bean
public DynamoDbClient dynamoDbClient() {
return DynamoDbClient.builder()
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create("accessKey", "secretKey")))
.region(Region.US_EAST_1)
.build();
}
@Bean
public DynamoDbEnhancedClient dynamoDbEnhancedClient(DynamoDbClient dynamoDbClient) {
return DynamoDbEnhancedClient.builder()
.dynamoDbClient(dynamoDbClient)
.build();
}
}
Testing with Local DynamoDB
For local development, you can use DynamoDB Local:
- Download DynamoDB Local from AWS
- Run it:
java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb
- Configure your application to use the local endpoint:
spring.cloud.aws.dynamodb.endpoint=http://localhost:8000
Creating Tables Programmatically
You can create tables at startup:
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput;
@Component
public class DynamoDbInitializer implements CommandLineRunner {
private final DynamoDbEnhancedClient enhancedClient;
public DynamoDbInitializer(DynamoDbEnhancedClient enhancedClient) {
this.enhancedClient = enhancedClient;
}
@Override
public void run(String... args) throws Exception {
DynamoDbTable<Product> productTable = enhancedClient.table("Product",
TableSchema.fromBean(Product.class));
try {
productTable.createTable(builder -> builder
.provisionedThroughput(ProvisionedThroughput.builder()
.readCapacityUnits(10L)
.writeCapacityUnits(10L)
.build()));
} catch (Exception e) {
System.out.println("Table already exists");
}
}
}
This setup provides a complete Spring Boot application with CRUD operations for DynamoDB using Spring Cloud AWS.