@singleton
class Hoge @Inject() (implicit system: ActorSystem, materializer: ActorMaterializer) {
def fuga = Try {
Http().singleRequest(
HttpRequest(method = HttpMethods.GET, uri = "https://mikeneko.tk"
)
}
}
で実行すると以下のエラー
ProvisionException: Unable to provision, see the following errors:
No implementation for akka.stream.ActorMaterializer was bound.
ActorMaterializer のimplicitがないってエラーになります。
IntelliJでもちゃんとあるって判定はされているのですが・・・
調べてみても同じ記述方法でやってる人はいますね。
* https://blog.colinbreck.com/integrating-akka-streams-and-akka-actors-part-ii/
* https://www.programcreek.com/scala/akka.stream.ActorMaterializer
ハマる(1回目)
色々試してみてわかったのですが、ActorMaterialは ()
の宣言で挙動が変わってきそうです。
一回外に出して確認してみます。
// これは通る
@singleton
class Hoge @Inject() (implicit system: ActorSystem) {
implicit val materializer = ActorMaterializer()
def fuga = Try {
Http().singleRequest(
HttpRequest(method = HttpMethods.GET, uri = "https://mikeneko.tk"
)
}
}
// これは通らない(ActorMaterializerにかっこがないだけ)
@Singleton
class Hoge @Inject() (implicit system: ActorSystem) {
implicit val materializer = ActorMaterializer
def fuga = Try {
Http().singleRequest(
HttpRequest(method = HttpMethods.GET, uri = "https://mikeneko.tk"
)
}
}
// 結果
could not find implicit value for parameter materializer:
akka.stream.ActorMaterializer
つまり ActorMaterializer
はActorMaterializerとして判断されておらず、 ActorMaterializer()
で判断されるようになるみたいです。
理由として、 ActorMaterializer()
は applyが呼ばれるのですが、 ActorMaterializer
だとただオブジェクトを呼んでいるだけっぽいです。
applyできずに、エラーになっているっぽいですね。ただのオブジェクトをimplicitとして渡されても困るって感じでしょうか。
object ActorMaterializer {
def apply(materializerSettings: Option[ActorMaterializerSettings] = None, namePrefix: Option[String] = None)(implicit context: ActorRefFactory): ActorMaterializer = {
val system = actorSystemOf(context)
val settings = materializerSettings getOrElse ActorMaterializerSettings(system)
apply(settings, namePrefix.getOrElse("flow"))(context)
}
...
}
ActorSystemがカッコ無しで通るのは、抽象クラスになっていてそもそもの作りが全然違うからでした。
abstract class ActorSystem extends ActorRefFactory {
...
}
更にハマる(2回目)
ならカッコ付きで宣言したらOK って思ったのですがここで新たな問題として @Inject()
の後ろでimplicitとして定義したいのですがこの中で ActorMaterializer()
という記述は使えません。カッコが使えないのです。(何故?)
ActorSystemはかっこなしとありで挙動が変わらなかったのでここに書いていますが、ActorMaterializerに関しては変わるので外に出すことにしました。やってることは同じなはず・・・
@singleton
class Hoge @Inject() (implicit system: ActorSystem) {
implicit val materializer = ActorMaterializer()
def fuga = Try {
Http().singleRequest(
HttpRequest(method = HttpMethods.GET, uri = "https://mikeneko.tk"
)
}
}
一旦これで。
毎回 ActorMaterializerを生成するのを防ぎたいという目標自体はクリアでき他のでこれでOKとします。