Actionクラスの中からバックグラウンドタスクを起動する
ActionクラスであるMainActionBeanクラスから、BackgroundTaskBean.execute()をバックグラウンドで実行したい場合。最初は普通に子スレッドを生成してやろうとしてたのですが、何やらEJBの中ではスレッド生成しちゃダメだとかなんとか。EJB3もそうなんでしょうか?
さておき、安全のため代替として下記の方法をとりました。ヒントはSeamリファレンスマニュアルのChapter17、Asynchronicity and messaging。バックグラウンドタスクを外部システム上で実行するなら、JMS使えばいいんでしょうけど、ローカルだけだとさすがに大げさですし。
MainActionインターフェースは省略するとして、MainActionBean.java
@Stateless @Name("mainAction") public class MainActionBean implements MainAction { @In(create=true) private BackgroundTask backgroundTask; public void execute() { ... // 即座にreturnし、中身の処理はバックグランドで実行される backgroundTask.execute(); } }
BackgroundTask.java
@Local public interface BackgroundTask { @Asynchronous public void execute(); }
BackgroundTaskBean.java
@Stateless @Name("backgroundTask") public class BackgroundTaskBean implements BackgroundTask { public void execute() { ... Process someProcess = Runtime.getRuntime().exec(someCmd); ... } }
BackgroundTaskBeanのsetterでインスタンスフィールドを設定しても、その後execute()で実行するときには、フィールドはnullになってました。仕方ないので、execute()の引数で全て渡すようにしてます。まだ仕組みは追えてないのですが、タイマーで実行される前に、一度インスタンスプールに戻されて初期化される、ということなのでしょうか?
とりあえず、手元ではそんな感じで最低限の用は足せてます。もしもっとエレガントな解法をご存知の方いらっしゃいましたら、是非教えてくださいまし。