きっかけ
バッチなど、バックグラウンドの処理をAkkaでスケジュールに登録した形で実装するのがplayでよくあると思います。そういった処理は、開発中やテスト中は止めておきたく、on/offを簡単にできるようにしたくなります。
そこで、playのplugin機能を使います。2.4からmoduleとなっていますが、pluginの方がわかりやすい面もあるのと、今使っているplayのバージョンが古いので、それで紹介してみます。
play.Pluginの実装
自前のpluginをつくるにはplay.Pluginを実装します。
import play.Application;
import play.Configuration;
import play.Plugin;
public class BatchPlugin extends Plugin {
private Logger logger;
private Configuration conf;
public BatchPlugin (Application app) {
this.logger = LoggerFactory.getLogger(BatchPlugin.class);
this.configuration = app.configuration();
}
/**
* プラグインが有効かの判定.
*/
@Override
public boolean enabled() {
return !"disabled".equals(conf.getString("batchPlugin"));
}
/**
* アプリ起動時の処理.
*/
@Override
public void onStart() {
logger.info("start batch");
ActorRef actorRef = Akka.system().actorOf(Props.create(BatchActor.class));
Akka.system().scheduler().schedule(
FiniteDuration.Zero,
FiniteDuration.create(1, TimeUnit.DAYS),
actorRef,
"batch",
Akka.system().dispatcher(),
ActorRef.noSender());
}
/**
* アプリ停止時の処理
*/
@Override
public void onStop() {
logger.info("stop batch");
}
}
play.Applicationだけを引数とするコンストラクタの定義と、enabled(),onStart(),onStop()を実装すればよいです。
enabled()の実装は、evolutionsと同じです。これでapplication.confにbatchPlugin=disabled
を追記すれば、Akkaでのスケジュール登録を止められます。
ActorRefのインスタンス生成はコンストラクタでやろうと思ったのですが、play.Akka.system()がそのタイミングでは起動していないようです。onStartでやらないと無限ループしました...
まとめ
公式サイトにありますが、plugin機能は、他のアプリでも再利用できるようにするよりも、ひとつのアプリで内部的に使うのにも便利です。本番環境のときで動いて欲しいなど、特定のケースのみの機能はpluginに切り出すと、コード的にも運用的にも管理しやすくなります。
2.4からDIで、moduleを注入するやり方がよいでしょう。play.modules.enabled
とplay.modules.disabled
で、moduleを使うかどうかをコントロールできます。
pluginからmoduleへの移行方法も公式で用意されています。