Asakusa FrameworkのOperator DSLで使えるSharedのメモ。
|
Sharedクラスは、AsakusaFW(0.7.3以降)が提供しているユーティリティAPIのひとつ。
オブジェクトの共有に使用する。
「Operatorで使う為に、一度だけ加工(初期化)してstaticフィールドに保持しておき、何度も使用する」という場合にSharedが利用できる。
import com.asakusafw.runtime.core.BatchContext; import com.asakusafw.runtime.core.util.Shared; import com.asakusafw.runtime.value.Date;
public abstract class ExampleOperator {
private static final Shared<Date> MY_DATE = new Shared<Date>() { @Override protected Date initialValue() { String s = BatchContext.get("my_date"); if (s == null) { throw new IllegalArgumentException("'my_date' not defined"); } return Date.valueOf(s, Date.Format.SIMPLE); // YYYYMMDD } };
@Update public void updateDate(Hoge in) { in.setHogeDate(MY_DATE.get()); } }
Sharedは(ThreadLocalクラスと似た形式で
)initialValueメソッドで値の初期化処理を記述し、getメソッドで値を取得することが出来る。
このinitialValueメソッドの中で、アプリケーションで使用したい形式に変換(加工・初期化)する。
上記の例ではOperatorクラス内でSharedのstaticフィールドを用意したが、複数のOperatorクラスから呼びたい場合は、Utilクラス等の他のクラスに書いてもよい。
Sharedはstaticフィールドに保持する(一度だけ初期化する)為、Sharedを呼び出すOperatorやフロー(JobFlow,
FlowPart)のテストを複数まとめて実行すると、異なる値が保持できずにテストが失敗する可能性がある。
(例えばtestAではSharedを20170604で初期化しているがtestBでは20170101を指定している場合など)
個々のテストを実行する度にSharedを初期化すれば、この問題は解消する。
Sharedの初期化の為にSharedObjectCleanerというクラスが提供されている。
@Ruleアノテーションを付けてテストクラスのフィールドに保持しておくだけで、テスト実行毎にSharedを初期化してくれる。
import org.junit.Rule; import org.junit.Test; import com.asakusafw.testdriver.SharedObjectCleaner;
public class ExampleOperatorTest { @Rule public final SharedObjectCleaner cleaner = new SharedObjectCleaner().add(ExampleOperator.class); 〜 }
SharedObjectCleanerにはSharedを保持しているクラスを指定しなければならない。
複数のクラスを指定する場合は「new SharedObjectCleaner().add(ExampleOperator.class).add(ExampleUtil.class)
」の様にして指定することが出来る。
なので、Sharedを使うクラスが多いとどれを初期化する必要があるか把握するのが大変になるので(特にフローのテストでは)、Sharedを使うクラスはなるべく減らす(Utilクラス等に集める)方が良さそう。