Action(parser.json) vs Action.async Error и использование concurrent.Execution.Implicits не может инициализировать контроллеры классов в Play Scala
Я пытаюсь создать почтовый запрос на вставку данных в mongoddb, используя: 1. sbt 0.13.6 2. play 2.10 3. scala 2.11.2 4. play2-реактивамонго 0.10.2 5. mongodb 2.6.4
отправка данных с помощью json, создание класса наблюдений для модели и использование JSPath для преобразования json в класс сущностей.
это мой пример кода:
def inserTransaction = Action(parser.json) { implicit request =>
val json = request.body
val data = json.as[Transaction]
Logger.info(data.toString)
val future = collection.insert(data.copy(id = Option[BSONObjectID](BSONObjectID.generate)))
var result = ""
future.onComplete {
case Failure(t) => result = "An error has occured: " + t.getMessage
case Success(post) => result = "success"
}
Ok(result)
}
Я видел некоторый пример кода, который использовал Action.sync для обработки асинхронных в контроллерах, но когда я пытаюсь использовать Action.sync, моя Intellij IDE обнаруживает ошибку "не удается разрешить Action.sync как подпись", я пытался изменить результат такой функции
future.onComplete {
case Failure(t) => Ok("An error has occured: " + t.getMessage)
case Success(post) => Ok("success")
}
Поэтому я решил использовать Action(parser.json), но проблема, возникшая в результате активации активатора, заключается в том, что я должен использовать "import play.api.libs.concurrent.Execution.Implicits._" в моем коде. Но когда я импортировал библиотеки, пришла новая ошибка:
! Internal server error, for (POST) [/insertdata] ->
java.lang.ExceptionInInitializerError: null ....
Caused by: play.api.PlayException: ReactiveMongoPlugin Error[The ReactiveMongoPlugin has not been
initialized! Please edit your conf/play.plugins file and add the following line....
когда я попытался перезагрузить запрос, он показал другую ошибку:
! Internal server error, for (POST) [/api/insertdata] ->
java.lang.NoClassDefFoundError: Could not initialize class controllers.TransactionController$
[error] application - Error while rendering default error page
scala.MatchError: java.lang.NoClassDefFoundError: Could not initialize class
controllers.TransactionController$ (of class java.lang.NoClassDefFoundError)
У кого-нибудь есть решение моей проблемы?
2 ответа
Этот вопрос может помочь: есть ли преимущества в использовании не асинхронных действий в Play Framework 2.2?
Действие против Действие.async
Если вы думаете о действиях на высоком уровне, которые берут и вводят, и производят выход, то эти два делают то же самое, но немного отличаются. Оба из них принимают в запросе и выводят результаты. Action.async позволяет коду действий правильно обращаться с фьючерсами. Я пропускаю некоторые детали, но надеюсь, что это поможет.
Можете ли вы вставить свой файл плагинов?
Проблема с вашим кодом в том, что вы используете Future
обратный вызов для управления изменяемой переменной. Функция вернется задолго до Future
завершен, поэтому обратный вызов по существу ничего не делает. Вместо этого вы должны использовать Action.async
а также map
Future
по вашему желанию Result
, Вы также можете использовать recover
справиться с любыми сбоями.
Ваш код должен выглядеть примерно так:
def inserTransaction = Action(parser.json).async { implicit request =>
val json = request.body
val data = json.as[Transaction]
Logger.info(data.toString)
val future = collection.insert(data.copy(id = Option[BSONObjectID](BSONObjectID.generate)))
future.map(result => Ok(result))
.recover { t: Throwable => Ok("An error has occured: " + t.getMessage) }
}
Или даже лучше:
def inserTransaction = Action(parser.json).async { implicit request =>
request.body.validate[Transaction].fold(
error => Future.successful(Ok("json errors...")),
data => {
collection.insert(data.copy(id = Option[BSONObjectID](BSONObjectID.generate)))
.map(result => Ok(result))
.recover { t: Throwable => Ok("An error has occured: " + t.getMessage) }
}
)
}
(Может не скомпилировать сразу, так как я не знаю что collection.insert
делает)