简体   繁体   English

如何使用Casbah从actor插入MongoDB?

[英]How to insert into MongoDB from actor using Casbah?

Assumptions: 假设:

  • MongoDB is running at localhost:27017 MongoDB在本地主机上运行:27017

  • This project is modeled after https://github.com/sap1ens/akka-microservice . 该项目以https://github.com/sap1ens/akka-microservice建模。 Please refer to it if there is not enough information below to help. 如果下面没有足够的信息来帮助您,请参考它。 If it gets too confusing, I can add code from other files if necessary. 如果太混乱了,我可以根据需要添加其他文件中的代码。

Questions based on RegistrationsService.scala 基于RegistrationsService.scala的问题

  • Why is it trying to connect to MongoDB and insert the document on startup before any PostRegistrationMessage is sent to RegistrationsService actor? 为什么在将任何PostRegistrationMessage发送到RegistrationsService actor之前尝试连接到MongoDB并在启动时插入文档?

  • Why is it failing? 为什么会失败?

  • How can I convert registrationJsValue into MongoDBObject and insert it into collection? 如何将registrationJsValue转换为MongoDBObject并将其插入集合中?

Relevant info in build.sbt build.sbt中的相关信息

scalaVersion := "2.10.4"

val akkaVersion = "2.3.8"

val sprayVersion = "1.3.1"

// Main dependencies
libraryDependencies ++= Seq(
    "com.typesafe.akka" %% "akka-actor" % akkaVersion,
    "com.typesafe.akka" %% "akka-slf4j" % akkaVersion,
    "io.spray" % "spray-can" % sprayVersion,
    "io.spray" % "spray-routing" % sprayVersion,
    "io.spray" % "spray-client" % sprayVersion,
    "io.spray" %% "spray-json" % sprayVersion,
    "com.typesafe" % "config" % "1.2.1",
    "ch.qos.logback" % "logback-classic" % "1.1.2",
    "org.mongodb" %% "casbah" % "2.7.4"
)

RegistrationService.scala (like ExampleService.scala in git repo) RegistrationService.scala (例如git repo中的ExampleService.scala)

package service

import akka.actor.{Props, ActorLogging, Actor}
import spray.json._
import com.mongodb.util.JSON
import com.mongodb.casbah.Imports._
import model.Registration
import model.RegistrationProtocol._

object RegistrationsService {
  case class PostRegistrationMessage(registration: Registration)

  def props(property: String) = Props(classOf[RegistrationsService], property)
}

class RegistrationsService(property: String) extends Actor with ActorLogging {
  import RegistrationsService._

  def receive = {
    case PostRegistrationMessage(registration) => {

      val registrationJsValue = registration.toJson
      val dbObject = JSON.parse(registrationJsValue.toString()).asInstanceOf[DBObject]

      val mongoClientURI = MongoClientURI("mongodb://localhost:27017/")
      val mongoClient = MongoClient(mongoClientURI)
      val someDB = mongoClient("somedb")
      val registrationsColl = someDB("registratoins")
      log.info(s"Got access to registratoins collection")

      registrationsColl.insert(MongoDBObject("hello" -> "world"))
      log.info(s"Inserted a doc to registratoins collection")

      mongoClient.close()
      log.info(s"Closed client connection to mongo")

      sender() ! registrationJsValue
    }
  }
}

sbt run sbt运行

14:01:10.655 [microservice-system-akka.actor.default-dispatcher-3] INFO  c.e.a.s.RegistrationsService - Got access to registratoins collection
14:01:11.383 [microservice-system-akka.actor.default-dispatcher-3] DEBUG spray.can.server.HttpListener - Binding to localhost/127.0.0.1:8878
14:01:11.475 [microservice-system-akka.actor.default-dispatcher-3] DEBUG akka.io.TcpListener - Successfully bound to /127.0.0.1:8878
14:01:11.480 [microservice-system-akka.actor.default-dispatcher-6] INFO  spray.can.server.HttpListener - Bound to localhost/127.0.0.1:8878
14:01:20.704 [microservice-system-akka.actor.default-dispatcher-5] ERROR akka.actor.OneForOneStrategy - Timed out after 10000 ms while waiting for a server that matches AnyServerSelector{}. Client view of cluster state is {type=Unknown, servers=[{address=localhost:27017, type=Unknown, state=Connecting, exception={java.lang.NullPointerException}}]
com.mongodb.MongoTimeoutException: Timed out after 10000 ms while waiting for a server that matches AnyServerSelector{}. Client view of cluster state is {type=Unknown, servers=[{address=localhost:27017, type=Unknown, state=Connecting, exception={java.lang.NullPointerException}}]
    at com.mongodb.BaseCluster.getServer(BaseCluster.java:82) ~[mongo-java-driver-2.12.4.jar:na]
    at com.mongodb.DBTCPConnector.getServer(DBTCPConnector.java:654) ~[mongo-java-driver-2.12.4.jar:na]
    at com.mongodb.DBTCPConnector.access$300(DBTCPConnector.java:39) ~[mongo-java-driver-2.12.4.jar:na]
    at com.mongodb.DBTCPConnector$MyPort.getConnection(DBTCPConnector.java:503) ~[mongo-java-driver-2.12.4.jar:na]
    at com.mongodb.DBTCPConnector$MyPort.get(DBTCPConnector.java:451) ~[mongo-java-driver-2.12.4.jar:na]
    at com.mongodb.DBTCPConnector.getPrimaryPort(DBTCPConnector.java:409) ~[mongo-java-driver-2.12.4.jar:na]
    at com.mongodb.DBCollectionImpl.insert(DBCollectionImpl.java:182) ~[mongo-java-driver-2.12.4.jar:na]
    at com.mongodb.DBCollectionImpl.insert(DBCollectionImpl.java:165) ~[mongo-java-driver-2.12.4.jar:na]
    at com.mongodb.DBCollection.insert(DBCollection.java:93) ~[mongo-java-driver-2.12.4.jar:na]
    at com.mongodb.casbah.MongoCollectionBase$class.insert(MongoCollection.scala:621) ~[casbah-core_2.10-2.7.4.jar:2.7.4]
    at com.mongodb.casbah.MongoCollection.insert(MongoCollection.scala:1109) ~[casbah-core_2.10-2.7.4.jar:2.7.4]
    at service.RegistrationsService$$anonfun$receive$1.applyOrElse(RegistrationsService.scala:47) ~[classes/:na]
    at akka.actor.Actor$class.aroundReceive(Actor.scala:465) ~[akka-actor_2.10-2.3.8.jar:na]
    at service.RegistrationsService.aroundReceive(RegistrationsService.scala:20) ~[classes/:na]
    at akka.actor.ActorCell.receiveMessage(ActorCell.scala:516) [akka-actor_2.10-2.3.8.jar:na]
    at akka.actor.ActorCell.invoke(ActorCell.scala:487) [akka-actor_2.10-2.3.8.jar:na]
    at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:254) [akka-actor_2.10-2.3.8.jar:na]
    at akka.dispatch.Mailbox.run(Mailbox.scala:221) [akka-actor_2.10-2.3.8.jar:na]
    at akka.dispatch.Mailbox.exec(Mailbox.scala:231) [akka-actor_2.10-2.3.8.jar:na]
    at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) [scala-library.jar:na]
    at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) [scala-library.jar:na]
    at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) [scala-library.jar:na]
    at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) [scala-library.jar:na]
^C14:01:42.231 [microservice-system-akka.actor.default-dispatcher-11] INFO  akka.actor.LocalActorRef - Message [akka.actor.Terminated] from Actor[akka://microservice-system/user/$a#1754981697] to Actor[akka://microservice-system/user/IO-HTTP/listener-0#-602059531] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
14:01:42.236 [microservice-system-akka.actor.default-dispatcher-11] DEBUG akka.event.EventStream - shutting down: StandardOutLogger started

Not sure what you mean by the following. 不确定以下内容是什么意思。

Why is it trying to connect to MongoDB and insert the document on startup before any PostRegistrationMessage is sent to RegistrationsService actor? 为什么在将任何PostRegistrationMessage发送到RegistrationsService actor之前尝试连接到MongoDB并在启动时插入文档?

In the example code (for RegistrationsService ) you have shown the only connection that is made is inside the Actor's receive method. 在示例代码(用于RegistrationsService )中,您显示了仅在Actor的receive方法内部建立的连接。 Unless you (or some other piece of code is sending this message, the actor will not try to connect to Mongo. 除非您(或其他代码段正在发送此消息),否则演员将不会尝试连接到Mongo。

On a side note, what are you creating a Mongo connection inside the Actor's receive method ? 附带说明一下,您要在Actor的receive方法中创建Mongo连接吗? You should avoid any heavy weight operation inside the receive method. 您应该避免在receive方法内部进行任何繁重的操作。 You can create a Mongo connection outside the Actor and then inject it in the Actor's constructor to be used in the Receive method. 您可以在Actor外部创建Mongo连接,然后将其注入Actor的构造函数中以在Receive方法中使用。

Have you written a standalone program/test that connects to your MongoDB using the casbah driver? 您是否编写了使用casbah驱动程序连接到MongoDB的独立程序/测试? It should work independently of your actor code and will help your isolate any issues (if there is one) with the driver and connection code. 它应该独立于您的参与者代码而工作,并且将帮助您隔离驱动程序和连接代码的所有问题(如果有)。

PS: This may not the be the answer to your question but I didn't want to write it in the comments part because of space and formatting limitations. PS:这可能不是您问题的答案,但由于篇幅和格式限制,我不想在评论部分中写下它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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