I'm new to Scala and I'm trying to do my first Play 2.0 application. I'm using:
I have this in my conf/routes
file:
PUT /newVenue controllers.Application.createNewVenue
I have this in my Application.scala
file:
def createNewVenue = Action(parse.json) { request =>
val newVenue = Venue.fromJSON(request.body.toString)
Venue.insert(newVenue)
Ok("New Venue Created")
}
And this is the code for Venue.scala
:
import play.api.Play.current
import com.novus.salat._
import com.novus.salat.global._
import com.novus.salat.annotations._
import com.novus.salat.dao._
import com.mongodb.casbah.Imports._
import se.radley.plugin.salat._
object Venue extends ModelCompanion[Venue, ObjectId] {
val collection = mongoCollection("venues")
val dao = new SalatDAO[Venue, ObjectId](collection = collection) {}
}
case class Venue(
@Key("_id") val venueId:ObjectId,
var playlist:Playlist,
var isPlaying:Boolean = false)
To test if this is working I send a PUT request to localhost:9000/newVenue
with this JSON as a body:
{"venueId": 3,"playlist":{"playlistId":2,"currentSongPosition":5},"isPlaying":false}
And then I get this error:
[error] application -
! @6d7oco1hf - Internal server error, for request [PUT /newVenue] ->
play.core.ActionInvoker$$anonfun$receive$1$$anon$1: Execution exception [[NoSuchMethodException: model.Venue$.apply$default$1()]]
at play.core.ActionInvoker$$anonfun$receive$1.apply(Invoker.scala:134) [play_2.9.1.jar:2.0.4]
at play.core.ActionInvoker$$anonfun$receive$1.apply(Invoker.scala:115) [play_2.9.1.jar:2.0.4]
at akka.actor.Actor$class.apply(Actor.scala:318) [akka-actor.jar:2.0.2]
at play.core.ActionInvoker.apply(Invoker.scala:113) [play_2.9.1.jar:2.0.4]
at akka.actor.ActorCell.invoke(ActorCell.scala:626) [akka-actor.jar:2.0.2]
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:197) [akka-actor.jar:2.0.2]
Caused by: java.lang.NoSuchMethodException: model.Venue$.apply$default$1()
at java.lang.Class.getMethod(Class.java:1605) ~[na:1.6.0_37]
at com.novus.salat.ConcreteGrater.defaultArg(Grater.scala:350) ~[salat-core_2.9.1-1.9.1.jar:1.9.1]
at com.novus.salat.ConcreteGrater.safeDefault(Grater.scala:360) ~[salat-core_2.9.1-1.9.1.jar:1.9.1]
at com.novus.salat.ConcreteGrater$$anonfun$6$$anonfun$apply$7.apply(Grater.scala:319) ~[salat-core_2.9.1-1.9.1.jar:1.9.1]
at com.novus.salat.ConcreteGrater$$anonfun$6$$anonfun$apply$7.apply(Grater.scala:319) ~[salat-core_2.9.1-1.9.1.jar:1.9.1]
at scala.Option.orElse(Option.scala:218) ~[scala-library.jar:0.11.3]
I think the line triggering the error is val newVenue = Venue.fromJSON(request.body.toString).
Does anyone have a clue of what's wrong?
I followed the tutorial in SalatWithPlay2 page and also followed some advices in similar problems), but I had no luck so far.
UPDATE:
I found a workaround, although it's not exactly a solution, but maybe it's helpful for somebody else and for understanding what is the actual solution.
If I remove the annotation @Key, the code of the case class Venue looks like this:
case class Venue(
val venueId:ObjectId,
var playlist:Playlist,
var isPlaying:Boolean = false)
And then I get this other error:
[RuntimeException: in: unexpected OID input class='net.liftweb.json.JsonAST$JInt', value='3']
And if instead of using ObjectId I use Long for example, the code looks like this:
case class Venue(
val venueId:Long,
var playlist:Playlist,
var isPlaying:Boolean = false)
And I get no error!
So the NoSuchMethodException apparently is related to the @Key annotation related to the _id. I also tried to rename venueId to _id and the same NoSuchMethodException error appeared. So the question is: why can't I use the @Key annotation to say which of my attributes maps to the object id of the document in the mongo database?
Besides that, regular Integers cannot be automatically converted to ObjectId instances for some other reason.
Thanks!