akkaでアプリケーションを作るときに設定値の読み込みをどうするか、という話。
- akka.actor.Extension
=======================
akka.actor.Extension
を使って各アクターで共通化させることができる。
import akka.actor.{ExtendedActorSystem, Extension, ExtensionId}
class SampleExtentionImpl(system: ExtendedActorSystem) extends Extension {
val hoge = "HOGE"
}
object SampleExtension extends ExtensionId[SampleExtensionImpl] {
def createExtension(system: ExtendedActorSystem) = new SampleExtensionImpl(system)
}
Extensionを定義しておくことで、アクターから呼び出すことができる。
import akka.actor.Actor
class SampleActor extends Actor {
val ext = SampleExtension(system)
def hoge = ext.hoge //=> "HOGE"
}
手っ取り早い方法ではあるが、ExtensionIdのオブジェクトを直接呼ぶ必要があり、実行時切り替えなどには向かない。
また、Actorクラス以外ではsystem: ActorSystem
がないと利用できない。
主にActorSystemにおける共通処理の集約やシングルトンな処理に向いている気がする。
- TypesafeConfig
=================
akkaはデフォルトでreference.conf
とapplication.conf
をクラスパスから読み込み、system.settings.config
から利用可能にしている。
cf. http://doc.akka.io/docs/akka/2.3.4/general/configuration.html
書式はTypesafeがライブラリとして提供するHOCON(Human-Optimized Config Object Notation)というものになる。
Actorクラスであれば先述したようにsystem.settings.config
から取得できるが、他クラスではsystemが無いため利用できない。
直接初期化時の引数に渡すこともできるが、configに依存したクラスであることを明示するため、DIを試みる。
import com.typesafe.config.Config
import akka.actor.ActorSystem
// configを定義するtrait
trait ConfigSupplier {
val config: Config
}
// configから読み込む設定情報の実装
trait DatabaseSetting { this: ConfigSupplier =>
import scala.util.Try
val dbHost = Try(config.getString("sample.db.host")).getOrElse("localhost")
val dbPort = Try(config.getInt("sample.db.port")).getOrElse(5432)
}
// 設定情報を利用するクラス
class SampleApplication { this: DatabaseSetting =>
val connection = getConnection(dbHost, dbPort)
}
object Main extends App {
val system = ActorSystem()
// インスタンス化のときに配線と注入
val app = new SampleApplication with DatabaseSetting with ConfigSupplier {
val config = system.settings.config
}
//...
}