2016-11-25 81 views
3

在收到TCP特定消息時,我需要查詢我的數據庫。對於這一點,我創建了被稱爲DBActor的演員和它在Application.scala文件加載來自Akka Actor的Scala + Play Framework + Slick + Akka - DB Access

class Application @Inject() (system: ActorSystem) extends Controller { 

     val tcpServer = system.actorOf(Props[TCPServer], "tcpserver") 
     val dbActor = system.actorOf(Props[DBActor], "dbActor") 
    } 

TCP服務器是收到的消息,並需要與

 val handler = context.actorSelection("/dbActor") 

推動它在DB演員演員DB演員太初始化以這種方式,根據播放框架說明書

object DBActor { 
     def props() = 
     Props(classOf[DBActor]) 
    } 


    class DBActor @Inject() (protected val dbConfigProvider: 
     DatabaseConfigProvider) extends Actor 
     with HasDatabaseConfigProvider[JdbcProfile] 
     with ActorLogging 
     with TableComponent { 

     import akka.io.Tcp._ 
     import driver.api._ 

     val table = TableQuery[Table] 

     def receive: Receive = { 
     case GetConfig(id) => { 
      sender ! Await.result(db.run(table.filter(_.id=== id).result.headOption), 
       Duration.Inf) 
      .map { x => x.config } 
     } 
     } 
    } 

目前,演員是不是構建由於錯誤

Error injecting constructor, java.lang.IllegalArgumentException: 
     no matching constructor found on class tcp.DBActor for arguments [] 
     at controllers.Application.<init>(Application.scala:17) 
     at controllers.Application.class(Application.scala:17) 

所以我需要一種方法來在DBactor中注入db配置來查詢數據庫或替代方法。我之前評估過注入DAO或將我需要的DAO轉換爲演員,都失敗了。

在這一點上的問題是,是否有任何意義讓演員訪問數據庫或至少,控制器?如果不能完成,還有什麼選擇?

回答

6

你需要的是一個注入的actor。完整描述可以在這裏找到播放文件(https://www.playframework.com/documentation/2.5.x/ScalaAkka#Dependency-injecting-actors)的,但這裏是它的要點是:

您定義的演員,像這樣綁定:

bindActor[DBActor]("db-actor") 

而且在像這樣的控制器注入演員:

class Application @Inject() (@Named("db-actor") dbActor: ActorRef) extends Controller { 

在不同的音符,你應該避免Await.result只要有可能。在您的情況,這也許可以很容易地被替換:

val senderRef = sender() 
db.run(table.filter(_.id=== id).result.headOption) 
    .map(res => senderRef ! res.config) 

注意發件人裁判之前存儲,因爲它是map內不再有效(見sender()方法scaladoc)。

+0

好吧,它確實有效,我必須以這種方式註冊所有應用程序的演員。謝謝 – emmea90