简体   繁体   中英

Work with akka-http and mongo-scala-driver

I want to use akka-http and new mongo-scala-driver for my rest service.

This code is working

val routes = {
  pathPrefix("info") {
    pathEndOrSingleSlash {
      get {
        val mongoClient: MongoClient = MongoClient("mongodb://localhost:27017,localhost:27018,localhost:27019/?replicaSet=rs0")
        val database: MongoDatabase = mongoClient.getDatabase("test")
        val collection: MongoCollection[Document] = database.getCollection("test")
        val future  = collection.find().limit(10).toFuture()
        val list = Await.result(future, Duration(10, TimeUnit.SECONDS))
        complete(list.map(_.toJson()))
      }
    }
  }
}

But I want to remove the blocking code Await.result and write asynchronous.

How can I do it? Thanks

build.sbt:

scalaVersion := "2.12.1"

"org.mongodb.scala" %% "mongo-scala-driver" % "1.2.1"
"com.typesafe.akka" %% "akka-http-core" % "10.0.4"
"com.typesafe.akka" %% "akka-http" % "10.0.4"

UPDATE

If I change my code:

complete(future.map(_.toJson()))

I get an error:

Error:(160, 36) value toJson is not a member of Seq[org.mongodb.scala.Document]
        complete(future.map(_.toJson()))

UPDATE

If I change my code:

        onComplete(future) {
          case Success(value) => complete(value)
          case Failure(ex)    => complete((InternalServerError, s"An error occurred: ${ex.getMessage}"))
        }

I get en error:

Error:(166, 47) type mismatch;
found   : Seq[org.mongodb.scala.bson.collection.immutable.Document]
required: akka.http.scaladsl.marshalling.ToResponseMarshallable
          case Success(value) => complete(value)

假设功能是未来,只需删除await并执行以下操作:

complete(feature.map(_.toJson))

First of all, you should not create a MongoClient instance in every request you receive. Also, you should not block your request to get the response. The Await.result(f, duration) will block the default dispatcher and probably decrease the performance of your application drastically.

//other imports
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.model.StatusCodes._

object Endpoint {
  val mongoClient: MongoClient = MongoClient("mongodb://localhost:27017,localhost:27018,localhost:27019/?replicaSet=rs0")
  val database: MongoDatabase = mongoClient.getDatabase("test")
  val collection: MongoCollection[Document] = database.getCollection("test")

  val routes = {
    pathPrefix("info") {
      pathEndOrSingleSlash {
        get {
          val future  = collection.find().limit(10).toFuture()
          onComplete(future) {
            case Success(list) =>
              complete(OK -> list.map(_.asJson()))
            case Failure(e) =>
              log.error(e)
              complete(InternalServerError -> "an error occurred while performing the request")
          }
        }
      }
    }
  }
}

That's more likely what you're looking for. Akka HTTP works very well with Futures and this is way to go without blocking your app.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM