Spring boot application with DynamoDB. Lets Explore.

Hemant
4 min readAug 4, 2024

--

In this article, I will walk you through the process of creating a DynamoDB table and connecting it to your Spring Boot application(No JPA). Let’s start.

What is DynamoDB?

Amazon DynamoDB as per DynamoDB site — Serverless, NoSQL, fully managed database with single-digit millisecond performance at any scale.

In this article we will create a DynamoDB table which we will use to store number of visitor to our website. We will provide an endpoint /counter using spring boot. Once user will call to this endpoint then counter value from DynamoDB will be incremented using spring boot service and returned as a response to user.

Step 1: Set Up Your DynamoDB Table

First things first, let’s create a DynamoDB table. Follow these steps:

  1. Log in to the AWS Management Console: Navigate to the DynamoDB service.

2. Create a new table: Click on “Create table” and provide a name for your table, here I am using visitor_counter. Set the primary/partition key, here I am using counter_id with data type String.

3. Configure settings: You can leave the default settings for read/write capacity or customize them based on your application’s needs.

4. Create the table: Click on “Create” to finalize the table creation.

First it will show table with status Creating, wait for some time.

After some time table Status will be changed to Active. Now table is ready to use.

Step 2: Set Up Your Spring Boot Application

Now that we have our DynamoDB table, let’s set up our Spring Boot application to connect to it.

  1. Create an application:

Follow https://start.spring.io/ for custom application or use this link to download template with spring boot web dependency.

  • You can use application which I created to perform these steps from github

2. Add dependencies: Add the following dependencies to your pom.xml file:

        <dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>dynamodb</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>dynamodb-enhanced</artifactId>
</dependency>

3. Add Model Class: create a model class with annotation @DynamoDbBeanannotation. Also, add @DynamoDbPartitionKey to field which was used a partition key while creating DynamoDB table


import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;

@DynamoDbBean
public class Counter {
private String counter_id;
private Integer counter;

@DynamoDbPartitionKey
public String getCounter_id() {
return counter_id;
}
public void setCounter_id(String counter_id) {
this.counter_id = counter_id;
}
public Integer getCounter() {
return counter;
}
public void setCounter(Integer counter) {
this.counter = counter;
}

public void incrementCounter(){
this.counter++;
}
public Counter(String counter_id, Integer counter) {
this.counter_id = counter_id;
this.counter = counter;
}

public Counter() {
}
}

4. Add Service class : This class will perform DB operations.

package com.lab01.spring.backend;

import org.springframework.stereotype.Component;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;

import java.util.Optional;

@Component
public class DynamoDBService {
public final String tableName = "visitor_counter";
public final String recordId = "1001";

private DynamoDbClient getClient() {
Region region = Region.US_EAST_1;
return DynamoDbClient.builder()
.region(region)
.build();
}

private DynamoDbEnhancedClient enhancedClient() {
return DynamoDbEnhancedClient.builder()
.dynamoDbClient(getClient())
.build();
}

// Get counter value from database , save incremented and return incremented.
public Integer incrementAndReturnCounter() {
Counter counter = getCounterFromDynamoDB();
if (counter == null) {
throw new RuntimeException("Counter not available");
}
counter.incrementCounter();
saveCounter(counter);
return counter.getCounter();
}

private Counter getCounterFromDynamoDB() {
try {
DynamoDbTable<Counter> table = enhancedClient().table(tableName, TableSchema.fromBean(Counter.class));
Optional<Counter> counterOptional = table.scan().items().stream().filter(c -> c.getCounter_id().equals(recordId)).findFirst();
Counter counter;
if (counterOptional.isEmpty()) {
counter = new Counter(recordId, 0);
} else {
counter = counterOptional.get();
}
return counter;
} catch (DynamoDbException e) {
System.err.println(e.getMessage());
}
return null;
}

private void saveCounter(Counter counter) {
try {
DynamoDbTable<Counter> table = enhancedClient().table(tableName, TableSchema.fromBean(Counter.class));
table.putItem(counter);
} catch (DynamoDbException e) {
System.err.println(e.getMessage());
}
}
}

5. Add GET endpoint /counter

Add a Controller class with GET api /counter — which will increment this value in DynamoDB and return that value as API response.

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/counter")
public class CounterController {
private final DynamoDBService dynamoDBService;
public CounterController(DynamoDBService counterService) {
this.dynamoDBService = counterService;
}
@GetMapping
public int increment() {
return dynamoDBService.incrementAndReturnCounter();
}
}

Step 3: Test

With everything set up, now lets connect.

Start spring boot application either of these methods

  • From IDE
  • From Terminal using command
mvn spring-boot:run

Open Browser and hit http://localhost:8080/counter

You can verify these values inside DynamoDB console

Hit API again to see increment working.

Conclusion:

Congratulations! You’ve successfully created a DynamoDB table and connected it to your Spring Boot application. With DynamoDB’s scalability and Spring Boot’s ease of use, an application can handle any amount of data with lightning-fast performance.

Happy coding!

--

--

Hemant

Lead Software Engineer @JPMorgan & Chase. Writes about Java, AWS and System Design