如何从Play Controller实现双异步返回?

时间:2016-01-26 21:02:34

标签: scala playframework-2.0 slick-3.0

我正在尝试编写如下的异步REST方法。

def createUser = Action.async(parse.json) { request =>
    val b = request.body.validate[User]
    b.fold(
      errors => {
        Future {
          BadRequest(Json.obj("status" -> "OK", "message" -> JsError.toJson(errors)))
        }
      },
      user => {
        // I am stuck here! Looking the below you would
        // understand what I need to do
        // How to achieve this?
        Future {
          UserServiceImpl.createUser(user) onComplete  {
            case user => Ok
            case _ => InternalServerError
          }
      }
    )
  }

问题是Slick dbConfig.db.run方法也是异步的。所以UserServiceImpl.createUser必须是异步的。

现在,如果UserServiceImpl.createUser抛出异常,我需要返回InternalServerError。如果成功,我想返回Ok。

我该怎么做?

以下是我的模特:

object User {
  case class User(id: Long,
                  firstName: String,
                  lastName: String,
                  mobile: Long,
                  email: String)

  implicit val userWrites = Json.writes[User]
  implicit val userReads = Json.reads[User]
}

class UserTable(tag: Tag)
  extends Table[User.User](tag, "user") {

  def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
  def firstName = column[String]("first_name")
  def lastName = column[String]("last_name")
  def mobile = column[Long]("mobile")
  def email = column[String]("email")

  override def * =
    (id, firstName, lastName, mobile, email) <> (User.User.tupled, User.User.unapply)
}

以下是我的服务:

trait UserService {

    def createUser(user: User): Future[User]

}

object UserServiceImpl extends UserService {
    val dbConfig = DatabaseConfigProvider.get[JdbcProfile](Play.current)
    val users = TableQuery[UserTable]

    override def createUser(user: User): Future[User] = {
      dbConfig.db.run(users += user).map(res => user)
    }

}

1 个答案:

答案 0 :(得分:2)

自己找到解决方案:

def createUser = Action.async(parse.json) { request =>
    val b = request.body.validate[User]
    b.fold(
      errors => {
        Future {
          BadRequest(Json.obj("status" -> "OK", "message" -> JsError.toJson(errors)))
        }
      },
      user => {
        UserServiceImpl.createUser(user).map(res => Ok) recover {
          case ex: Exception => InternalServerError
        }
      }
    )
  }