かとじゅんの技術日誌

技術の話をするところ

タスクとタスクグループの関係

詳しくは知りませんが,JP1にはジョブとジョブグループが存在します.
ジョブ,つまりバッチ処理の最小単位ですが,ジョブグループはジョブを複数内包することができます.これをそのままクラス表現にすると,コンポジットパターンでJobGroupはJobを複数保持できるクラスということになるかと思います.
このモデルは意図的にS2Chronosでは採用していません.非常に見通しが悪くなるためです.デザイン的には優れていてもソースコードの見通しが悪くなるものはなるべく採用しないというスタンスです.
では,S2Chronosではジョブグループに相当するタスクグループはどう表現するかってことですが,,,

まず,タスククラスでは,複数のタスクメソッドを管理できます.doExecute以外のdoから始まるメソッドを複数定義できます.以下を参照してください.

@Task
@NonDelayTrigger
public class SampleTask {

	private static Logger log = Logger.getLogger(SampleTask .class);

	public void initialize(){
		log.info(this.getClass().getSimpleName() + ":initialize");
	}

	@NextTask("taskA")
	public void start(){
		log.info(this.getClass().getSimpleName() + ":start");
	}

	@NextTask("taskB")
	public void doTaskA(){
		log.info(this.getClass().getSimpleName() + ":doTaskA");
	}

	public void doTaskB(){
		log.info(this.getClass().getSimpleName() + ":doTaskB");
	}

	public void end(){
		log.info(this.getClass().getSimpleName() + ":end");
	}

	public void destroy(){
		log.info(this.getClass().getSimpleName() + ":destroy");
	}
}

この場合,doから始まるタスクメソッドが複数あるのでどこから始めればよいかわかりません.なので,startメソッドにNextTaskアノテーションを使って指定する必要があります.doを省いたメソッド名をキャメル形式で指定してください.また,doTaskAの後に実行するタスクメソッドもdoTaskA自体にNextTaskアノテーションで定義してください.
この方法では,コンパイル時に遷移先のタスクを決定しますが,以下のようにすれば実行時にも指定できます.

@Task
@NonDelayTrigger
public class SampleTask {

	private static Logger log = Logger.getLogger(SampleTask .class);

	public void initialize(){
		log.info(this.getClass().getSimpleName() + ":initialize");
	}

	@NextTask("taskA")
	public void start(){
		log.info(this.getClass().getSimpleName() + ":start");
	}


	public String doTaskA(){
		log.info(this.getClass().getSimpleName() + ":doTaskA");
		return "taskB";
	}

	public void doTaskB(){
		log.info(this.getClass().getSimpleName() + ":doTaskB");
	}

	public void end(){
		log.info(this.getClass().getSimpleName() + ":end");
	}

	public void destroy(){
		log.info(this.getClass().getSimpleName() + ":destroy");
	}
}

戻り値で次に遷移するタスクメソッドを指定すれば実行に遷移先を決定できます.
各タスクメソッドはdoTaskAが完了すれば,doTaskBへと同期的に呼び出されて実行されます.通常の関数呼び出しと変わりません.このタスクメソッドを非同期に呼び出したい場合は以下のようにします.

@Task
@NonDelayTrigger
public class SampleTask {

	private static Logger log = Logger.getLogger(SampleTask .class);

	public void initialize(){
		log.info(this.getClass().getSimpleName() + ":initialize");
	}

	@NextTask("taskA")
	public void start(){
		log.info(this.getClass().getSimpleName() + ":start");
	}

	@NextTask("taskA")
	@JoinTask(JoinType.NoWait)
	public void doTaskA(){
		log.info(this.getClass().getSimpleName() + ":doTaskA");
	}

	public void doTaskB(){
		log.info(this.getClass().getSimpleName() + ":doTaskB");
	}

	public void end(){
		log.info(this.getClass().getSimpleName() + ":end");
	}

	public void destroy(){
		log.info(this.getClass().getSimpleName() + ":destroy");
	}
}

このようにJoinTaskアノテーションでNoWaitを指定するとdoTaskAの終了を待たずに次のdoTaskBに遷移します.ちなみに,先ほどの戻り値にStringを使って次のタスクメソッドに遷移する場合は同期呼び出し,つまりJoinTaskアノテーションでWaitが指定されたのと同じ扱いになります.
同期でも非同期でもすべてのタスクメソッドが終了するとendメソッドが呼ばれます.

このように,ひとつのタスククラスで複数のバッチ処理をメソッド単位で定義できます.1つのバッチ処理でも,複数のバッチ処理でもタスククラスで柔軟に定義できるようにしています.S2Chronosではこれをタスクグループと定義しています.また,タスククラスには複数のタスクグループを定義できます.これは別の機会に紹介します.
同期呼び出しについては通常の関数呼び出しと変わらないわけなので,NextTaskアノテーションを使わずとも記述できますが,タスクメソッドの遷移はコードを書かないというポリシーで設計されています.