In tradition approach, implementing Data Access Layer makes lots of boilerplate code. Spring Data helps us improve our codes and reduce efforts for development and maintenance. It supports us the ways to write interface for repositories and custom finder methods, the implementation will be done automatically by Spring Framework. In this tutorial, we’re gonna look at how to use Spring Data DynamoDB with Spring Boot.
Related Posts:
– Spring MongoOperations to access MongoDB
– How to build SpringBoot MongoDb RestfulApi
– How to use SpringData MongoRepository to interact with MongoDB
I. Technology
– Java 1.8
– Maven 3.3.9
– Spring Tool Suite – Version 3.9.0.RELEASE
– Spring Boot: 1.5.9.RELEASE
II. Overview
1. Goal
2. Project Structure
– Class Customer corresponds to entity and table Customer.
– CustomerRepository is an interface extends CrudRepository, will be autowired in WebController for implementing repository methods and custom finder methods.
– WebController is a REST Controller which has request mapping methods for RESTful requests such as: save, delete, findall, findbyid, findbylastname.
– Configuration for DynamoDB properties in application.properties. The accesskey
and secretkey
are just arbitrary values and are not needed to actually authenticate when accessing local instance of DynamoDB. The properties will be dynamically pulled out in the DynamoDBConfig.
– Dependencies for Spring Boot and DynamoDB in pom.xml
III. Practice
1. Create Spring Boot project & add Dependencies
org.springframework.boot spring-boot-starter-web com.amazonaws aws-java-sdk-dynamodb 1.11.34 com.github.derjust spring-data-dynamodb 4.5.0
2. Configure Spring Data DynamoDB
Open application.properties:
amazon.dynamodb.endpoint=http://localhost:8000/ amazon.aws.accesskey=jsa amazon.aws.secretkey=javasampleapproach
Under package config, create DynamoDBConfig class:
package com.javasampleapproach.dynamodb.config; import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; import com.amazonaws.util.StringUtils; @Configuration @EnableDynamoDBRepositories(basePackages = "com.javasampleapproach.dynamodb.repo") public class DynamoDBConfig { @Value("${amazon.dynamodb.endpoint}") private String dBEndpoint; @Value("${amazon.aws.accesskey}") private String accessKey; @Value("${amazon.aws.secretkey}") private String secretKey; @Bean public AmazonDynamoDB amazonDynamoDB() { AmazonDynamoDB dynamoDB = new AmazonDynamoDBClient(amazonAWSCredentials()); if (!StringUtils.isNullOrEmpty(dBEndpoint)) { dynamoDB.setEndpoint(dBEndpoint); } return dynamoDB; } @Bean public AWSCredentials amazonAWSCredentials() { return new BasicAWSCredentials(accessKey, secretKey); } }
3. Create DataModel Class
Under package model, create Customer class:
package com.javasampleapproach.dynamodb.model; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; @DynamoDBTable(tableName = "Customer") public class Customer { private String id; private String firstName; private String lastName; public Customer() { } public Customer(String id, String firstName, String lastName) { this.id = id; this.firstName = firstName; this.lastName = lastName; } @DynamoDBHashKey(attributeName = "Id") public String getId() { return id; } public void setId(String id) { this.id = id; } @DynamoDBAttribute(attributeName = "FirstName") public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @DynamoDBAttribute(attributeName = "LastName") public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @Override public String toString() { return String.format("Customer[id=%s, firstName='%s', lastName='%s']", id, firstName, lastName); } }
4. Create Repository Interface
This interface helps us do all CRUD functions:
package com.javasampleapproach.dynamodb.repo; import java.util.List; import org.socialsignin.spring.data.dynamodb.repository.EnableScan; import org.springframework.data.repository.CrudRepository; import com.javasampleapproach.dynamodb.model.Customer; @EnableScan public interface CustomerRepository extends CrudRepository{ List findByLastName(String lastName); }
5. Create Web Controller
The controller receives requests from client, using repository to add/get data and return results:
package com.javasampleapproach.dynamodb.controller; import java.util.Arrays; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.javasampleapproach.dynamodb.model.Customer; import com.javasampleapproach.dynamodb.repo.CustomerRepository; @RestController public class WebController { @Autowired CustomerRepository repository; @RequestMapping("/delete") public String delete() { repository.deleteAll(); return "Done"; } @RequestMapping("/save") public String save() { // save a single Customer repository.save(new Customer("JSA-1", "Jack", "Smith")); // save a list of Customers repository.save(Arrays.asList(new Customer("JSA-2", "Adam", "Johnson"), new Customer("JSA-3", "Kim", "Smith"), new Customer("JSA-4", "David", "Williams"), new Customer("JSA-5", "Peter", "Davis"))); return "Done"; } @RequestMapping("/findall") public String findAll() { String result = ""; Iterablecustomers = repository.findAll(); for (Customer cust : customers) { result += cust.toString() + "
"; } return result; } @RequestMapping("/findbyid") public String findById(@RequestParam("id") String id) { String result = ""; result = repository.findOne(id).toString(); return result; } @RequestMapping("/findbylastname") public String fetchDataByLastName(@RequestParam("lastname") String lastName) { String result = ""; for (Customer cust : repository.findByLastName(lastName)) { result += cust.toString() + "
"; } return result; } }
6. Create DynamoDB table
– Run DynamoDB:
java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb
– Create Customer Table:
aws dynamodb create-table --table-name Customer --attribute-definitions AttributeName=Id,AttributeType=S --key-schema AttributeName=Id,KeyType=HASH --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1 --endpoint-url http://localhost:8000
Response is like:
{ "TableDescription": { "TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/Customer", "AttributeDefinitions": [ { "AttributeName": "Id", "AttributeType": "S" } ], "ProvisionedThroughput": { "NumberOfDecreasesToday": 0, "WriteCapacityUnits": 1, "LastIncreaseDateTime": 0.0, "ReadCapacityUnits": 1, "LastDecreaseDateTime": 0.0 }, "TableSizeBytes": 0, "TableName": "Customer", "TableStatus": "ACTIVE", "KeySchema": [ { "KeyType": "HASH", "AttributeName": "Id" } ], "ItemCount": 0, "CreationDateTime": 1514538274.168 } }
7. Run Spring Boot Application & Check Result
– Config maven build:
clean install
– Run project with mode Spring Boot App
– Check results:
Request 1
http://localhost:8080/save
The browser returns Done
and if checking database with Customer table, we can see some data rows has been added:
Request 2
http://localhost:8080/findall
Request 3
http://localhost:8080/findbyid?id=JSA-3
Request 4
http://localhost:8080/findbylastname?lastname=Smith
Request 5
http://localhost:8080/delete
The browser returns Done
and if checking database with Customer table, we can see:
8. Way to check DynamoDB Table
Go to http://localhost:8000/shell
, then run the code below:
var dynamodb = new AWS.DynamoDB({ region: 'us-east-1', endpoint: "http://localhost:8000" }); var tableName = "Customer"; var params = { TableName: tableName, Select: "ALL_ATTRIBUTES" }; function doScan(response) { if (response.error) ppJson(response.error); // an error occurred else { ppJson(response.data); // successful response // More data. Keep calling scan. if ('LastEvaluatedKey' in response.data) { response.request.params.ExclusiveStartKey = response.data.LastEvaluatedKey; dynamodb.scan(response.request.params) .on('complete', doScan) .send(); } } } console.log("Starting a Scan of the table"); dynamodb.scan(params) .on('complete', doScan) .send();
IV. Source Code
Last updated on September 4, 2018.
I’m trying to setup a class that has both the @DynamoDBHashKey and a @DynamoDBRangeKey, but I get a spring error when I define @DynamoDBRangeKey. If I remove the @DynamoDBRangeKey annotation from the field then Spring doesn’t complain, but I need both types of keys.
This is the error I get with both key annotations defined:
Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Couldn’t find field with annotation interface org.springframework.data.annotation.Id!
Any ideas what would be causing this?
Hi Al
Take a look at this wiki post on the spring-data-dynamodb project – https://github.com/derjust/spring-data-dynamodb/wiki/Use-Hash-Range-keys
It explains how to setup this scenario
How could you test the Post methods?
Postman…use body in json format
Thanks..nice tutorial.. Can you please tell me if there is way that dynamoDB table is automatically created on application startup if it doesn’t already exists similar to what hibernate offers through “hibernate.hbm2ddl.auto” property. Thanks
how can we connect to dynamodb in aws from local??
Using access key and secret access key
Awesome, this tutorial helped me a lot, I connected aws dynamodb by referring this tutorial. It worked like a charm !!
Hi,
I am following your tutorial and tried to connect to AWS Dynamodb. Spring boot application is started and no errors, but no data is getting inserted into the tables..Can you please help?
Thanks in advance
There might be an issue with your table, make sure that you run the command which is provided above to create the ddb table. I also face the same issue, then I created table using command line. Which works for me.
Nice tutorial. Best on the web I can find till date for fresher!
Muchas gracias. ?Como puedo iniciar sesion?