MANA-DOT

PIXEL ART, PROGRAMING, ETC.

Play2で.conf以外のファイルから設定を読む 続き

昨日次のようなエントリを書きましたが、Twitterでよりよさそうな方法を教えてもらいました。

PlayのApplication起動時に読み込まれるGlobalSettingsのconfigurationメソッドが怪しいとのこと。 単に検索で先に引っかかったからという理由だけでJavaAPIリファレンスを見てたんですが、Java版のGlobalSettingsにはそんなの生えてなかったから気づきませんでした・・・

試したところ、GlobalSettings.configurationをオーバーライドすると、返したConfigurationオブジェクトがapplication.confに追加されるようです。 ただし、このコンテキストではApplicationがまだ初期化されていないため、標準confの値や、実行パスなどを取ってくることができず、自力で解決してあげなければいけません。 (今回、環境によってyamlファイルを読み替えるつもりだったので、ここでやや苦労しました。)

GlobalSettings.configurationによって書き換えると以下のようになります。

import play.api._
import com.typesafe.config.ConfigFactory
import org.yaml.snakeyaml.Yaml
import java.io.FileInputStream
import java.util.{Map => JMap }
import scala.collection.JavaConversions._

object Global extends GlobalSettings {
  /**
   * Yaml の 設定値 を読み込む
   */
  def loadParamFromYaml = {
    val path = System.getProperty("user.dir") + "/conf/hoge.yml"
    new Yaml().load(new FileInputStream(path)).asInstanceOf[JMap[String, JMap[String, String]]]
  }

  /**
   * yamlから読んだparamをplayのconf形式にする
   */
  def paramAsConfiguration = (Configuration.empty /: loadParamFromYaml ) { case (conf, (settingName, v)) =>
    conf ++ Configuration(
      ConfigFactory.parseString("""
        db.%s = {
          "user"     : "%s",
          "password" : "%s",
          "driver"   : "com.mysql.jdbc.Driver",
          "url"      : "jdbc:mysql://%s/%s?characterEncoding=UTF8"
        }
      """.format( settingName, v("user"), v("password"), v("host"), v("database") )))
  }
  // configurationに追加
  override def configuration = super.configuration ++ paramAsConfiguration
}

Application初期化前なので、play.libs.Yamlが使えないこと、Play.getFileが使えないので、システムプロパティのuser.dirからconfディレクトリを探すことなどがやや面倒になっています。ですが、configurationに追加しているため、昨日の方法とは違いDBPlugin以外からでも参照でき、DBテストのためにFakeApplicationで設定を上書きすることもできます。

おそらくこっちのほうがPlay的に正攻法なのでしょう。教えてくれた方に感謝。