Play2.4のプラグインシステムにある欠陥について

私の理解が正しければ、Play2.4のプラグインシステムにはプラグインの起動順が制御できないという大きな欠陥があります。Play2.3以前はplay.pluginsファイルに優先度を記述するというイケてない感が漂うやり方ではありましたが、問題なく制御することができていました。

Play2.4からはプラグインをDIコンポーネントとして記述するようになりました。play.pluginsファイルはなくなり、優先度ではなくコード中に記述してあるコンポーネント間の依存関係を利用して起動順が結果的にうまくいくようになっています。

ただし全てのプラグインがコードを介して依存しているわけではありません。例えばflyway-playのようなデータベースマイグレーションを行うライブラリはscalikejdbc-fixtureのようにデータベースフィクスチャプラグインよりも先に起動する必要がありますが、コード上で依存させるわけにはいきません。flyway-playではなくplay-evolutionsを使うときや、マイグレーションツールを全く使わないという選択ができなくなるためです。

Playの開発チームとしてはプラグイン間にコードにはない単純な起動順という関係があるのは間違いであるという態度を取っています。 つまりflyway-playとscalikejdbc-fixtureの実装に責任があるとの指摘を受けました。 ちょっと何を言ってるのかわかりませんが、少なくとも2.3のプラグインからの移行先としてはこのようなケースは当然考慮されるべきです。そもそも移行期間すら設けられずに行われた変更なのです。

まとめるとPlay2.4のプラグインシステムではPlay2.3で行っていたプラグインの起動順制御ができないため、プラグインの組み合わせによってはPlay2.3から2.4への移行はできません。Play2.4の重大な欠陥と言えますが、1日やりとりしてもPlay開発チームと話がかみ合っていないので、修正される見込みはないかと思います。

https://github.com/playframework/playframework/pull/4960

追記

そのあと、一応の対処法は教えてもらいましたので書いておきます。 教わった例はFixtureコンポーネントのラッパーを書いて、それをMigrationsComponentに依存させろ、というもの。

class DBFixturesComponentWrapper @Inject() (migrations: MigrationsComponent) {
  val dbFixturesComponent = ???
}

これはMigrationsComponentをコンストラクタで受け取ってるのでMigrationが先に起動するわけですが、FixturesComponentはDIではなく手動でインスタンス化しています。 次のようなコードにするほうが自然に見えるかもしれません。DIで起動順を制御しようとするのは結局失敗だったということです。

class DBFixturesComponentWrapper @Inject() {
  val migrationsComponent = ???
  val dbFixturesComponent = ???
}