I have Play 2.3 appliction with reactive mongo plugin. I have base document:
trait TemporalDocument {
val created: Option[DateTime] = Some(new DateTime())
val updated: Option[DateTime] = Some(new DateTime())
}
and one of the concrete document:
case class User(name: String) extends TemporalDocument
object User{
implicit val userFormat = Json.format[User]
}
So when I persist it to mongo db using reactive mongo plugin only name is persisted, created/updated fields are not.
My repository looks like:
trait MongoDocumentRepository[T <: TemporalDocument] extends ContextHolder {
private val db = ReactiveMongoPlugin.db
def insert(document: T)(implicit writer: Writes[T]): Future[String] = {
collection.insert(document).map {
lastError => lastError.toString
} recover {
case e: Exception => sys.error(e.getMessage)
}
}
private def collection: JSONCollection = db.collection[JSONCollection](collectionName)
implicit object BSONDateTimeHandler extends BSONHandler[BSONDateTime, DateTime] {
def read(time: BSONDateTime) = new DateTime(time.value)
def write(jdtime: DateTime) = BSONDateTime(jdtime.getMillis)
}
}
Problem is that I will have many documents extended from base document and I do not want each time init those dates and probably some other fields. Is it possible to do something like this?
Firstly, we can halve the surface-area of the problem; Reactive Mongo and/or the Play Reactive Mongo Plugin are not relevant here, it's Play's JSON macros that build the appropriate JSON structures (or not, in this case) that are responsible.
If I set up a TemporalDocument
and User
as in your code, and then write it out:
val user = User("timmy")
println(Json.toJson(user))
I get:
{"name":"timmy"}
I haven't looked into it, but I suspect this is because the created
and updated
fields don't appear in the "field list" of the User
case class.
If I rework your code a little bit like this:
trait TemporalDocument {
val created: Option[DateTime]
val updated: Option[DateTime]
}
case class User(
name: String,
val created: Option[DateTime] = Some(new DateTime()),
val updated: Option[DateTime] = Some(new DateTime()))
extends TemporalDocument
Then the same test code gets the desired behaviour from play-json:
{"name":"timmy","created":1410930805042,"updated":1410930805071}