/ / Чому я отримую цей виняток IllegalArgumentException під час спроби ввести послуги в актора? - скала, ігрові рамки, акка, гіс

Чому я отримую цей виняток IllegalArgumentException, коли намагаюся ввести послуги актору? - scala, playframework, akka, guice

Мій код:

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 для завантаження в сервісах, які потрібні акторові, я обов’язково ввімкнув модуль у застосунку .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"
}

Моє завдання - мати ігровий додаток з бекендом, який обробляється акторами. Кожен актор буде мати певні залежності від різних служб, я намагався вводити ці служби за допомогою Google Guice.

Все, що я отримую під час запуску програми, це трасування винятків:

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

Я не знаю, як саме це виправити ...

Я використовую Play 2.4.

Відповіді:

5 за відповідь № 1

Лінія override def props: Props = Props[TempActor] намагається викликати конструктор нульових аргументівверсія TempActor, де жодна не існує. У коді Akka за Props немає нічого, що б дозволило йому зрозуміти, що ви використовуєте Google Guice, і відповідно створити TempActor.

Ви можете зробити це, наприклад:

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

2 для відповіді № 2

Врешті-решт, я пішов із тим, що, на мою думку, працювало.

Я використовував код пластини котла в https://github.com/rocketraman/activator-akka-scala-guice генерувати акторів, які мали залежності.

У самому додатку Play я "не використовую систему акторів / уявлення, яку вбудував Play, я створюю власну систему інжекторів та акторів у глобальних налаштуваннях.

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 (..., name)". Мій керівник не має ніяких залежностей, оскільки його робота полягає в тому, щоб приймати запити та передавати їх відповідному дочірньому актору (які створюються за допомогою коду rocketraman).