我正试图创建一个向mongodb插入数据的post请求,使用:1.sbt 0.13.62.播放2.103.标量2.11.24.播放2 reactivamongo 0.10.25.mongodb 2.6.4
通过json发布数据,并为模型创建一个case类,并使用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.ssync时,我的Intellij IDE检测到一个错误"无法将Action.sync解析为签名",我尝试更改类似的函数的结果
future.onComplete {
case Failure(t) => Ok("An error has occured: " + t.getMessage)
case Success(post) => Ok("success")
}
所以我决定使用Action(parser.json),但activator play的问题是告诉我应该在代码中使用"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)
有人能解决我的问题吗?
代码的问题是使用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
做什么)
这个问题可能会有所帮助:在Play Framework 2.2中使用非异步操作有什么好处吗?
Action vs Action.async
如果你想到的是高级别的动作,它们接受、输入并产生输出,那么这两个动作做的是相同的,但略有不同。这两者都接收请求和输出结果。Action.async允许操作代码正确处理Futures。我跳过了一些细节,但我希望这能有所帮助。
你能粘贴你的插件文件吗?