2015-10-12 12 views
1

我的代碼:爲什麼在嘗試將服務注入到actor中時收到此IllegalArgumentException異常?

Global.scala - 我只是在啓動時設置它,它會向演員發送一條快速消息。這裏拋出異常;我證實注入的服務已被加載。

object Global extends GlobalSettings { 
    override def onStart(app: Application): Unit = { 
    val system = app.actorSystem 
    system.actorOf(TempActor.props, TempActor.name) ! "hi hi" 
    } 
} 

TempActor.scala

package actors 

class TempActor @Inject() (
    @Named(TestServiceModuleNames.RedisService) redisService: StatusService 
    , @Named(TestServiceModuleNames.DynamoDbService) dynamoDbService: StatusService 
) extends Actor with ActorLogging { 

    override def receive: Receive = { 
    case msg: Any => 
     log.info(s"the msg => $msg") 
     context.system.shutdown() 
    } 
} 

object TempActor extends NamedActor { 
    override def name: String = this.getClass.getSimpleName 
    override def props: Props = Props[TempActor] 
} 

TestServiceModule.scala - 一個Guice的模塊中的角色需要,我已經確信,使模塊中的application.conf服務加載

package modules 

class TestServiceModule extends AbstractModule with AkkaGuiceSupport { 

    val configs = ConfigFactory.load() 

    override def configure(): Unit = { 

    bind(classOf[StatusService]).annotatedWith(Names.named(TestServiceModuleNames.RedisService)).toInstance(new RedisStatusServiceImpl(new RedisConfig(configs.getString("redis.host"), configs.getInt("redis.port")))) 
    bind(classOf[StatusService]).annotatedWith(Names.named(TestServiceModuleNames.DynamoDbService)).toInstance(new DynamoDBStatusServiceImpl(Region.US_EAST_1, configs.getString("dynamo.db.endpoint"), configs.getString("dynamo.db.table.name.status"))) 
    } 
} 

object TestServiceModuleNames { 
    final val RedisService = "RedisStatusService" 
    final val DynamoDbService = "DynamoDbStatusService" 
} 

application.conf

redis.host="localhost" 
redis.port=4242 

dynamo.db.endpoint="http://localhost:8000" 
dynamo.db.table.name.status="status" 

play.modules { 
    enabled += "modules.TestServiceModule" 
} 

play.akka.actor-system="warden" 

akka { 
    loggers = ["akka.event.slf4j.Slf4jLogger"] 
    loglevel = "DEBUG" 
} 

我的目標是讓演員處理後端處理的遊戲應用。每個actor都會對不同的服務有一定的依賴關係,我試圖用google guice注入這些服務。

所有當我啓動應用程序,我得到的是異常跟蹤:

java.lang.IllegalArgumentException: no matching constructor found on class actors.TempActor for arguments [] 

我不知道如何準確地解決這個問題...

我使用播放2.4。

+0

請把代碼的相關部分在線(即不是鏈接到github),所以問題是自包含http://meta.stackoverflow.com/questions/253915/what-to-do-with-鏈接到github-gist-in-questions – mattinbits

+0

@mattinbits oops,認爲它會更乾淨。將更新 – iCodeLikeImDrunk

回答

5

override def props: Props = Props[TempActor]正試圖調用TempActor的零參數構造函數版本,其中不存在。在Props後面的Akka代碼中沒有任何東西可以讓它理解你正在使用Google Guice並相應地創建一個TempActor。

你可能喜歡的東西做到這一點:

override def props: Props = Props[TempActor] = { 
    Injector injector = Guice.createInjector(new TestServiceModule()); 
    Props(injector.getInstance(TempActor.class)) 
} 
+0

看起來像這樣會工作!我非常接近於從遊戲中使用我自己定製的遊戲中的內置guice/actor系統。 – iCodeLikeImDrunk

+0

問題:我將如何去測試演員?由於噴油器在道具上「硬編碼」,嘲笑服務將是不可能的,不是嗎?既然它是道具,我會在許多演員身上重複這段代碼? – iCodeLikeImDrunk

+0

我知道更多關於阿卡方面比吉斯方面,但你可以通過注射器進入道具方法,如果在你的情況下更好地工作? – mattinbits

1

最後,我去我的感受的工作。

我使用https://github.com/rocketraman/activator-akka-scala-guice中的鍋爐板代碼來生成具有相關性的參與者。

在Play應用程序本身,我沒有使用Play內置的actorsystem/guice,我在全局設置中生成了我自己的注入器和actor系統。

object Global extends GlobalSettings { 

    final val injector = Guice.createInjector(
    new ServiceModule(), 
    new ConfigModule(), 
    new AkkaModule(), 
    new ActorModule() 
) 

    final val actorSystem = injector.instance[ActorSystem] 
    final val quartzScheduler = QuartzSchedulerExtension.get(actorSystem) 
    final val configs = new ConfigProvider().get() 

    override def onStart(app: Application): Unit = { 
     // onstart logic 
    } 


    override def onStop(app: Application): Unit = { 
    actorSystem.shutdown() 
    } 
} 

設置我的項目的方式是有其產生通過正常的途徑主要演員/主管「actorSystem.actorOf(...,名)」。我的主管沒有任何依賴性,因爲它的工作是接受請求並將它們轉發給適當的兒童演員(使用rocketraman的代碼創建)。

相關問題