I'm having trouble to retrieve a document in mongoDB using the new scala driver.
Here my code :
def retrieveDocument(id: Int,
collectionName: String,
databaseName: String,
url: String): Option[Document] = {
var res: Option[Document] = None
getMongoCollectionImmutable(collectionName, databaseName, url)
.find(Filters.equal("_id", id))
.first().subscribe(
(doc: Document) => res = Some(doc),
(e: Throwable) => throw e,
() => ())
res
}
def getMongoCollectionImmutable(collectionName: String,databaseName: String, url: String = DEFAULT_URL): MongoCollection[ImmuDoc] = {
db match {
case None =>
getMongoDatabase(databaseName, url).getCollection(collectionName)
case Some(db) =>
db.client.getDatabase(databaseName).getCollection(collectionName)
}
def getMongoDatabase(name: String, url: String = DEFAULT_URL): MongoDatabase = {
db match {
case None =>
db = Some(new _Database(url))
getMongoDatabase(name)
case Some(db) =>
db.client.getDatabase(name)
}
def retrieve(id: Int): Try[User] = {
try {
val docOption = Database.retrieveDocument(id, USER_COLLECTION, DATABASE_NAME, DEFAULT_URL)
docOption match {
case None => Failure(new Exception(s"Unable to retrieve a user with id ${id}"))
case Some(doc) => Try(User(doc))
}
} catch {
case e: Throwable => Failure(e)
}
}
Here are the (significant) logs of the driver:
19:16:24.334 DEBUG cluster - Updating cluster description to {type=STANDALONE, servers=[{address=localhost:27017, type=STANDALONE, roundTripTime=0.7 ms, state=CONNECTED}]
19:16:24.366 INFO connection - Opened connection [connectionId{localValue:2, serverValue:90}] to localhost:27017
19:16:24.377 DEBUG query - Asynchronously sending query of namespace jobless.user on connection [connectionId{localValue:2, serverValue:90}] to server localhost:27017
19:16:24.381 DEBUG query - Query results received 1 documents with cursor null
Here my test output
Run starting. Expected test count is: 1
UserTest:
User Document((_id,BsonInt32{value=1}), (firstname,BsonString{value='user1'}), (lastname,BsonString{value='last1'}), (encryptedPass,BsonString{value='pass'}), (cvListPath,BsonArray{values=[{ "name" : "path1", "path" : "name1" }, { "name" : "path2", "path" : "name2" }]}), (motivationLettersPath,BsonArray{values=[{ "name" : "path1", "path" : "name1" }, { "name" : "path2", "path" : "name2" }]}))
- retrieve from DB Failure(java.lang.Exception: Unable to retrieve a user with id 1) *** FAILED ***
java.lang.Exception: Unable to retrieve a user with id 1 (UserTest.scala:31)
But ! By using wireshark I can see the database query the right way and returning the document ! (I checked by doing a query using the mongo linux command and it's the very same)
Frame 1262: 123 bytes on wire (984 bits), 123 bytes captured (984 bits) on interface 0
Linux cooked capture
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 42714, Dst Port: 27017, Seq: 438, Ack: 1272, Len: 55
Mongo Wire Protocol
Message Length: 55
Request ID: 0x00000008 (8)
Response To: 0x00000000 (0)
OpCode: Query (2004)
Query Flags
fullCollectionName: xxx.user
Number To Skip: 0
Number to Return: -1
Query
Document length: 14
Elements
Element: _id
Type: Int32 (0x10)
Value: 1
And the database response is also correct.
What am I doing wrong ?
Ok so, I blame myself (and the mystic documentation of the driver)
This driver is asynchronous, so we just have to wait for it to complete... So to sum up using that (found here) which is genuinely used in the documentation without being in the driver itself
implicit class DocumentObservable[C](val observable: Observable[Document]) extends ImplicitObservable[Document] {
override val converter: (Document) => String = (doc) => doc.toJson
}
implicit class GenericObservable[C](val observable: Observable[C]) extends ImplicitObservable[C] {
override val converter: (C) => String = (doc) => doc.toString
}
trait ImplicitObservable[C] {
val observable: Observable[C]
val converter: (C) => String
def results(): Seq[C] = Await.result(observable.toFuture(), Duration(10, TimeUnit.SECONDS))
def headResult() = Await.result(observable.head(), Duration(10, TimeUnit.SECONDS))
def printResults(initial: String = ""): Unit = {
if (initial.length > 0) print(initial)
results().foreach(res => println(converter(res)))
}
def printHeadResult(initial: String = ""): Unit = println(s"${initial}${converter(headResult())}")
}
And changing retrieve that way :
def retrieveDocument(id: Int, collectionName: String, databaseName: String, url: String): Option[Document] = {
var res: Option[Document] = None
getMongoCollectionImmutable(collectionName, databaseName, url)
.find(Filters.equal("_id", id))
.limit(1).results().foreach({ x => res = Some(x) })
res
}
It fixes my problem.
User contributions licensed under CC BY-SA 3.0