Simple Java Spring Boot Application with DynamoDB

Today we’ll build a simple Spring Boot Application and integrate it with DynamoDB.

We’ll configure our Spring Boot application to use a local DynamoDB instance using Spring Data. We’ll create an example data model and repository class as well as perform actual database operations using an integration test. Notice that in similar way you can work with Amazon DynamoDB.

What is DynamoDB

Amazon DynamoDB is a fast and flexible NoSQL database service for all applications that need consistent, single-digit millisecond latency at any scale. It is a fully managed cloud database and supports both document and key-value store models. Its flexible data model, reliable performance, and automatic scaling of throughput capacity make it a great fit for mobile, web, gaming, ad tech, IoT, and many other applications. DynamoDB is very similar to such NoSQL databases as Cassandra or MongoDB. DynamoDB offers fast, consistent and predictable performance and is massively scalable.

Let’s now install a local instance of DynamoDB for learning purposes and to avoid incurring the cost of running a live instance on Amazon.

Running DynamoDB locally makes more sense than running on AWS in development mode, because the local instance will be running as an executable JAR file.

You can find instructions on how to run DynamoDB locally here.

 

Maven Dependencies

<dependencyManagement>
    <dependencies>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-releasetrain</artifactId>
        <version>Hopper-SR10</version>
        <type>pom</type>
        <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk-dynamodb</artifactId>
        <version>1.11.34</version>
    </dependency>
    <dependency>
        <groupId>com.github.derjust</groupId>
        <artifactId>spring-data-dynamodb</artifactId>
        <version>4.3.1</version>
    </dependency>
</dependencies>

 

Application Configuration

Put the following configurations in the application.properties file:

amazon.dynamodb.endpoint=http://localhost:8000/
amazon.aws.accesskey=key
amazon.aws.secretkey=key2

The secret keys listed above are just arbitrary values for your local config. When accessing a local instance of DynamoDB these fields need to be populated by some values but are not needed to actually authenticate.

Spring will automatically load the properties from application.properties file:

@Configuration
@EnableDynamoDBRepositories(basePackages = "com.codeflex.spring.dynamodb.example")
public class DynamoDBConfig {
 
    @Value("${amazon.dynamodb.endpoint}")
    private String amazonDynamoDBEndpoint;
 
    @Value("${amazon.aws.accesskey}")
    private String amazonAWSAccessKey;
 
    @Value("${amazon.aws.secretkey}")
    private String amazonAWSSecretKey;
 
    @Bean
    public AmazonDynamoDB amazonDynamoDB() {
        AmazonDynamoDB dynamoDB = new AmazonDynamoDBClient(amazonAWSCredentials());
         
        if (!StringUtils.isEmpty(amazonDynamoDBEndpoint)) {
            dynamoDB.setEndpoint(amazonDynamoDBEndpoint);
        }
         
        return dynamoDB;
    }
 
    @Bean
    public AWSCredentials amazonAWSCredentials() {
        return new BasicAWSCredentials(amazonAWSAccessKey, amazonAWSSecretKey);
    }
}

 

Data Model

Let’s create a simple Book class that will be stored in our DynamoDB. We’ll use annotations in a similar way just like you probably already used once for Hibernate projects.

@DynamoDBTable(tableName = "Book")
public class Book {
    private String id;
    private String name;
    private String price;
 
    @DynamoDBHashKey
    @DynamoDBAutoGeneratedKey
    public String getId() {
        return id;
    }
 
    @DynamoDBAttribute
    public String getName() {
        return name;
    }
 
    @DynamoDBAttribute
    public String getPrice() {
        return price;
    } 
}

 

Book Repository Class

Now, let’s create BookRepository interface to define the CRUD functionality. All repositories used to read and persist data from DynamoDB will implement this interface:

@EnableScan
public interface BookRepository extends CrudRepository<Book, String> {
     
    List<Book> findById(String id);
}

 

Testing our Spring Boot Application with DynamoDB

Now, we want to test our application to ensure that we can connect and perform operations on our local DynamoDB:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
@WebAppConfiguration
@ActiveProfiles("local")
@TestPropertySource(properties = { 
  "amazon.dynamodb.endpoint=http://localhost:8000/", 
  "amazon.aws.accesskey=yourAccessKey", 
  "amazon.aws.secretkey=yourSecretKey" })
public class BookRepositoryIntegrationTest {
 
    private DynamoDBMapper dynamoDBMapper;
 
    @Autowired
    private AmazonDynamoDB amazonDynamoDB;
 
    @Autowired
    BookRepository repository;
 
    private static final String ID = "1";
    private static final String NAME = "Learn Java & DevOps on Codeflex.co";
    private static final String PRICE = "100";
 
    @Before
    public void setup() throws Exception {
        dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB);
         
        CreateTableRequest tableRequest = dynamoDBMapper.generateCreateTableRequest(Book.class);
        tableRequest.setProvisionedThroughput(new ProvisionedThroughput(1L, 1L));
        amazonDynamoDB.createTable(tableRequest);
         
        // your code here...
 
        dynamoDBMapper.batchDelete((List<Book>)repository.findAll());
    }
 
    @Test
    public void dynamoDBTestCase() {
        Book codeflex = new Book(ID, NAME, PRICE);
        BookRepository.save(codeflex);
 
        List<Book> theBook = (List<Book>) repository.findAll();
         
        assertTrue("Book found.", theBook.size() > 0);
        assertTrue("The book name is correct.", theBook.get(0).getName().equals(NAME));
    }
}

This is it! You have now your Spring Boot Application communicating with DynamoDB.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.