See for yourself, here is a simple example demonstrating how easy it is to get started:
package domainModel {
import longevity.model.annotations._
// first, define our domain classes:
// the @persistent is the thing we want to persist in its own table.
// the primaryKey describes how we want to retrieve the objects.
@persistent(keySet = Set(primaryKey(User.props.username)))
case class User(
username: Username,
email: Email,
fullName: FullName)
// @keyVal means we can retrieve users by username:
@keyVal[User]
case class Username(username: String)
// a @component is a part of the object we want to persist:
@component
case class Email(email: String)
@component
case class FullName(
last: String,
first: String,
title: Option[String])
// gather all the domain classes into a domain model:
@domainModel
object DomainModel
}
object applicationServices extends App {
import domainModel._
import longevity.context.LongevityContext
import scala.concurrent.ExecutionContext.Implicits.global
// build the context for our domain model
val context = LongevityContext(DomainModel)
// get the user repository
val userRepo = context.repoPool[User]
// we are now ready to start persisting users
val username = Username("sméagol")
val oldEmail = Email("gollum@gmail.example.com")
val newEmail = Email("sméagol@gmail.example.com")
val fullName = context.testDataGenerator.generate[FullName]
val user = User(username, oldEmail, fullName)
// create, retrieve, update, delete
val f = for {
created <- userRepo.create(user)
retrieved <- userRepo.retrieveOne(username)
modified = retrieved.map(_.copy(email = newEmail))
updated <- userRepo.update(modified)
deleted <- userRepo.delete(updated)
} yield {
println(s"created ${created.get}")
println(s"retrieved ${retrieved.get}")
println(s"updated ${updated.get}")
println(s"deleted ${deleted.get}")
}
// wait for the CRUD ops to complete
import scala.concurrent.Await
import scala.concurrent.duration.Duration
Await.result(f, Duration.Inf)
// close db connection after CRUD ops complete
context.repoPool.closeSession()
}
You can find this example on GitHub. It should pretty much run for you right out of the box. Try setting longevity.backEnd to Mongo or Cassandra in application.conf if you have one of them installed locally.
Writing macro annotations is so much fun! I started out writing a single macro, and ended up writing nine. My initial goal was removing the boilerplate in describing the properties of a persistent class, i.e., the ability to talk meta about members of classes like the User.username field above. With the @persistent annotation, this property is simply User.props.username. But it occurred to me that I could write a small handful of annotations that would allow for describing a domain model using nothing but the annotations.
Of course, all longevity functionality is available without using the macro annotations! But I don't see any advantage in doing so, aside from not having to enable macro paradise in your build.
Well, what a relief to get this out! I feel like a true 1.0 feature set is now in place. But because the last few releases have brought some major API changes, I plan on holding off on committing to a 1.0 release for a while, to give the changes some time to settle.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.