0

I have a function saveToDB() that calls another function db.writeDocument() in another class called DB.scala. The saveToDB() function receives a JSON message and sends it to the writeDocument() and expects a future to be returned.

So, in the code below, you can see that db.writeDocument(message) returns a function which is being .map'ed to see either a success result or a failure.

Everything works great on the success side of things, but when I kill the MongoDB server, reactivemongo.core.actors.Exceptions$PrimaryUnavailableException$: MongoError['No primary node is available!'] is never caught and all I get is the 500 Internal Server Error with response body containing Execution exception

def saveToDB(message: JsValue): Future[JsValue] = {

    db.writeDocument(message).map { result =>
      val resultJson = Json.obj("transactionID" -> (message \ "transactionID").get, "campaignID" -> (message \ "campaignID").get,
        "status" -> "OK", "message" -> ("Valid Request Received"))
      resultJson
    }.recover { case e: Exception => {
      BadRequest("Please check your MongoDB server" + e.toString)
      Json.toJson("status -> error")

    }
    }


def writeDocument(json: JsValue): Future[WriteResult] = {
    val db = getDBConnection
    val collection = db.collection[JSONCollection]("Messages")

    val document = json.as[JsObject]
    val future = collection.insert(document)
    future.onComplete {
      case Failure(e) => {
        throw e
      }
      case Success(result) =>
    }
    future
  }
  }

To be completely fair about my question, I am trying to use the saveToDB() in the following way: (I have tried my best to explain this and please let me know if you need more explanation.)

val saveResponseFromDB = saveToDB(message)
Future.firstCompletedOf(Seq(saveResponseFromDB, timeoutFuture)).map {
              case resultJson: JsObject => {
                val status = ((resultJson \ "status").get)
                Ok(resultJson)

              } case _ => BadRequest(Json.obj("campaignID" -> campaignID,
                "status" -> "error", "message" -> "Error reading from the Database. Is it Down?") )
        }

EDIT 1:

def getDBConnection: DefaultDB = {
    val driver = new MongoDriver
    val connection = driver.connection(List(hostName))
    val db = connection(dbName)
    db
  }
summerNight
  • 1,446
  • 3
  • 25
  • 52
  • What's `getDBConnection`? What are the versions? – cchantep Feb 09 '16 at 08:08
  • Please see my EDIT 1 for getDBConnection. From my build.sbt I have `"org.reactivemongo" %% "reactivemongo" % "0.12.0-SNAPSHOT", "org.reactivemongo" %% "play2-reactivemongo" % "0.11.9"` and I have a MongoDB version `3.0.6` – summerNight Feb 09 '16 at 15:33
  • Using both `"reactivemongo" % "0.12.0-SNAPSHOT"` & `"play2-reactivemongo" % "0.11.9"` is just incompatible. Define only the Play dependency, so the driver is transitive. – cchantep Feb 09 '16 at 21:23
  • As indicated in the doc, `MongoConnection` is a pool of connection. Creating a driver instance and pool of connection for each call is wasting many resources. – cchantep Feb 09 '16 at 21:27
  • @cchantep: Thanks. I removed `reactivemongo" % "0.12.0-SNAPSHOT` and also moved the mongo driver instance from inside a function up to the class variable definition. However, I haven't still been able to figure out why I can't catch a DB exception. – summerNight Feb 10 '16 at 03:03
  • It's not only the driver instance, but also the connection `MongoConnection` instancz that must be managed, in order not to be created for each, otherwise it will each time take time to prepare the pool and its underlying actor system. – cchantep Feb 10 '16 at 08:26

0 Answers0