
Scanamo
Scanamo is a library to make use of DynamoDB with Scala.
In this blog, we are going to work on latest version 1.0.0-M11
So, let’s get it started-
1. Add Library Dependencies: –
Setup sbt
project and add these library dependencies
libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.5.25"
libraryDependencies += "org.scanamo" %% "scanamo-alpakka" % "1.0.0-M11"
libraryDependencies += "com.typesafe.akka" %% "akka-stream" % "2.5.25"
2. Setup application.conf
: –
Create application.conf
file and place it inside the src\main\resources\
akka.stream.alpakka.dynamodb {
region = "eu-west-1"
host = "localhost"
port = 8000
tls = false
parallelism = 32
credentials {
access-key-id = "dummy-access-key"
secret-key-id = "dummy-secret-key"
}
}
3. Create Case Class And DAO: –
Create case class as it is required to map it with DynamoDB table.
case class User(id: Long, name: String, email: String)
Below is a trait which represent DAO, DAO is DATA ACCESS OBJECT
trait UserDAO {
def addUser(user: User): Future[Option[Either[DynamoReadError, User]]]
def getUser(email: String): Future[Option[Either[DynamoReadError, User]]]
def updateUserName(email: String, updatedName:String): Future[Either[DynamoReadError, User]]
def deleteUser(email: String): Future[String]
}
4. Implement UserDAO: –
Now, implement DAO and provide body to the abstract method as shown, Here we are using scanamo library to perform curd operation with DynamoDB
.
class DynamoDBImplementation(tableName: String)(
implicit val actorMaterializer: ActorMaterializer,
val dynamoClient: DynamoClient,
val executionContext: ExecutionContext
) extends UserDAO {
private lazy val scanamoAlpakka: ScanamoAlpakka = ScanamoAlpakka(dynamoClient)
private val table: Table[User] = Table[User](tableName)
override def addUser(user: User): Future[Option[Either[DynamoReadError, User]]] =
scanamoAlpakka.execFuture(table.put(user))
override def getUser(email: String): Future[Option[Either[DynamoReadError, User]]] =
scanamoAlpakka.execFuture(table.get("email" -> email))
override def updateUserName(email: String, updatedName:String): Future[Either[DynamoReadError, User]] =
scanamoAlpakka.execFuture(table.update("email" -> email, set("name" -> updatedName)))
override def deleteUser(email: String): Future[String] =
scanamoAlpakka.execFuture(table.delete("email" -> email)).map(_.toString)
}
5. Initialise ActorSystem
and DynamoClient
: –
Initialize ActorSystem
, ActorMaterializer
, ExecutionContext
and DynamoClient
implicit val system: ActorSystem = ActorSystem("Scanamo-tutorial")
implicit val materializer: ActorMaterializer = ActorMaterializer()
implicit val executionContext: ExecutionContext = system.dispatcher
val dynamoSettings: DynamoSettings = DynamoSettings(system)
implicit val dynamoClient: DynamoClient = DynamoClient(dynamoSettings)
6. Insert some data: –
Its time to run our code by populating it with some data.
val tableName = "TestTable"
val userDAO: UserDAO = new DynamoDBImplementation(tableName)
val sampleUser = User(100L, "Test", "test@test@test")
userDAO.addUser(sampleUser).onComplete {
case Success(Some(Right(user))) => println(s"$user ----- updated")
case Success(Some(Left(dynamoReadError))) => println(dynamoReadError)
case Success(None) => println("User inserted")
case Failure(exception) => exception.printStackTrace()
}
7. Query inserted data: –
If data is inserted successfully, then we are going to get User
using email from DynamoDB
userDAO.getUser(sampleUser.email).onComplete {
case Success(Some(Right(user))) => println(s"$user")
case Success(Some(Left(dynamoReadError))) => println(dynamoReadError)
case Success(None) => println("User not found")
case Failure(exception) => exception.printStackTrace()
}
So, from above we can execute async database operations on DynamoDB using scanamo library.
To setup local DynamoDB, Click Here
.