Я новичок в Scala и пытаюсь сделать свое первое приложение Play 2.0. Я использую:
- Скала 2.9.3
- Играть 2.0.4
- SalatWithPlay2 1.1
У меня есть это в моем файле conf/routes
:
PUT /newVenue controllers.Application.createNewVenue
У меня есть это в моем файле Application.scala
:
def createNewVenue = Action(parse.json) { request =>
val newVenue = Venue.fromJSON(request.body.toString)
Venue.insert(newVenue)
Ok("New Venue Created")
}
А это код для 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)
Чтобы проверить, работает ли это, я отправляю запрос PUT на localhost:9000/newVenue
с этим JSON в качестве тела:
{"venueId": 3,"playlist":{"playlistId":2,"currentSongPosition":5},"isPlaying":false}
И затем я получаю эту ошибку:
[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]
Я думаю, что ошибка вызывается строкой val newVenue = Venue.fromJSON(request.body.toString).
Кто-нибудь знает, что не так? Я следовал руководству на странице SalatWithPlay2, а также следовал некоторым советам в подобных проблемах), но пока мне не везло.
ОБНОВЛЕНИЕ:
Я нашел обходной путь, хотя это не совсем решение, но, возможно, это полезно для кого-то еще и для понимания того, что является фактическим решением.
Если я уберу аннотацию @Key, код кейса класса Venue будет выглядеть так:
case class Venue(
val venueId:ObjectId,
var playlist:Playlist,
var isPlaying:Boolean = false)
И тогда я получаю эту другую ошибку:
[RuntimeException: in: unexpected OID input class='net.liftweb.json.JsonAST$JInt', value='3']
А если вместо ObjectId я использую, например, Long, то код выглядит так:
case class Venue(
val venueId:Long,
var playlist:Playlist,
var isPlaying:Boolean = false)
И у меня нет ошибки!
Таким образом, NoSuchMethodException, по-видимому, связано с аннотацией @Key, относящейся к _id. Я также попытался переименовать место проведения Id в _id, и появилась та же ошибка NoSuchMethodException. Итак, возникает вопрос: почему я не могу использовать аннотацию @Key, чтобы сказать, какой из моих атрибутов соответствует идентификатору объекта документа в базе данных mongo? Кроме того, обычные целые числа не могут быть преобразованы автоматически. к экземплярам ObjectId по какой-либо другой причине.
Спасибо!