読者です 読者をやめる 読者になる 読者になる

MANA-DOT

PIXEL ART, PROGRAMING, ETC.

Play2でデータベースを標準の.conf以外から設定する

状況

Play2を利用して既存サービスの管理ツールを作っていて、DB接続関係の設定ファイルを既存のサービスと同じもの(Yamlファイル)を利用したい。

独自設定用のYamlファイルはだいたいこんな感じになっています。

# db.yml
hoge_db:
    user: hoge_user
    password: hogepassword
    database: hoge
    host: localhost
fuga_db:
    user: fuga_user
    password: fugapassword
    database: fuga
    host: localhost
...

最初はGlobalSettingsのbeforeStart中でYamlファイルをパースしconfigurationに追記してあげれば、その後Playが追記されたDB設定を読んでくれると思っていたのですが、このconfigurationの追記の方法が調べても調べても見つかりませんでした。

そこで、configurationを追記することは一旦諦め、Play標準のDBPlugin(Playが自動で読み込む)を使わずに、自分で自分の設定ファイルを読み込むDBPluginを作ることにしたので、そのためのメモ。

やったこと

DB用のプラグインですが、標準利用されているのがplay.api.db.BoneCPPluginというもののようです。こいつのソースを読んだところ、db設定はdbConfigというフィールドに保持しているので、こいつを継承してdbConfigをオーバーライドし、独自の設定を返すようにしてやればよさそうです。

以下のようになりました。

package hogeapp.plugins

import collection.JavaConversions._
import Java.util.{Map => JMap}

class MyDBPlugin(app: Application) extends BoneCPPlugin(app) {
  override lazy val dbConfig = {
    // Yaml の DB設定を読み込む
    val dbSetting = Yaml.load("db.yml").asInstanceOf[JMap[String, JMap[String, String]]]

    // dbSettingをplayのconf形式にしてapp.configurationに追加したものを返す
    (app.configuration /: dbSetting) { case (conf, (k, v)) =>
      conf ++ Configuration(
        ConfigFactory.parseString("""
          db.%s = {
            "user"     : "%s",
            "password" : "%s",
            "driver"   : "com.mysql.jdbc.Driver",
            "url"      : "jdbc:mysql://%s/%s?characterEncoding=UTF8"
          }""".format(k, v("user"), v("password"), v("host"), v("database"))))
    }.getConfig("db").getOrElse(Configuration.empty)
  }
}

あとは、こいつを起動時に読み込むようにconf/play.pluginsに追加してあげれば良いです。 標準のDBPluginが優先度200らしかったので、199で動かすことにしました。

199:hogeapp.plugins.MyDBPlugin

これでdb.ymlの設定値でDBにつないでくれるようになりました。 ただ、少々ゴリ押し感のある方法なので、(出来ればapp.configurationの値に追加してあげたい)よりエレガントな方法をご存知な方がいたら是非ご教示願いたいです。