AEM Developerの皆様お疲れさまです。大和株式会社の狩野です。
2021年初の更新となる今回はバックエンド側の実装方法であるWCMUsePojoとSling Modelsの2つの比較について行いたいと思います。
バックエンド側の実装方法にWCJUsePojoとSling Modelsの2つが存在することに疑問を持っていた人、そもそもバックエンド側の実装方法について知りたい人にはぜひ読んでほしい記事です。
結論
これから新しく書くコードは可能な限りSling Modelsにするのが望ましいです。
Sling ModelsはHTL以外でも再利用が可能だったり、単体テストが容易だったり、他クラスを継承することが可能だったりと利点が多いからです。
WCMUsePojoはHTL以外で再利用が不可であったり、WCMUsePojoを継承するという形で実装するため、他クラスを継承できない上にWSMUsePojoクラス持つメソッドは全てがfinalで宣言されているため、モック化が難しいという問題があります。
WCMUsePojoとSling Modelsの比較
文法
Sling Models
アノテーションでメソッドやフィールドに意味をもたせます。
@Model( adaptables = { SlingHttpServletRequest.class }, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL ) public class SlingModelTutorial { @ValueMapValue private String dialogValue; private String toHtl; @PostConstruct public void init() { toHtl = dialogValue.toUpperCase(); } public String getToHtl() { return toHtl; } }
WCMUsePojo
クラス名にもある通り、純粋なJavaで書かれたObjectで、WCMUsePojoクラスが持っているメソッドを使って必要なオブジェクトを取得します。
public class PojoTutorial extends WCMUsePojo { private String toHtl; @Override public void activate() { ValueMap properties = getProperties(); toHtl = properties.get("dialogValue", ""); } public String getToHtl() { return toHtl; } }
機能面での比較
- HTL以外での再利用
- 実際これができる利点というのを今のところ私は感じたことがないのですが、多くのサイトで語られていたので利点としてあげておきます
- 単体テストが容易
- Sling Modelsは
AemContext
というクラスを利用して簡単に単体テストが可能 - WCMUsePojoはこのクラスが持っているメソッドが
final
で宣言されているため、モック化することが難しく単体テストが少し難しくなる(できないわけではない)
- Sling Modelsは
- 他クラスの継承
- Sling Modelsはアノテーション駆動なので、これを使うために他クラスを継承する必要が無く、継承が可能
- WCMUsePojoはこのクラスを継承した上で動くため、多重継承が禁止されているJavaにおいて継承ができない
単体テストの比較
Sling Models
@ExtendWith(AemContextExtension.class) class SlingModelTutorialTest { @Rule private final AemContext ctx = new AemContext(); @BeforeEach void setUp() { ctx.addModelsForClasses(SlingModelTutorial.class); ctx.load().json("/path/to/resource/json/path.json", "/content/myapp/"); } @Test void getToHtlTest() { String expected = "dialog_value"; ctx.currentResource("/content/myapp/path/to/node"); SlingModelTutorial slingModelTutorial = ctx.request().adaptTo(SlingModelTutorial.class); String actual = slingModelTutorial.getToHtl(); assertEquals(expected, actual); } }
AemContext
というクラスを利用して、ノード構造を記したJsonをテスト用データに使用可能
WCMUsePojo
public class PojoTutorialTest { private ValueMap properties = new ValueMapDecorator(new HashMap<String, Object>()); private PojoTutorial pojoTutorial = PowerMock.spy(new PojoTutorial()); @BeforeEach public void setUp() { properties.put("dialogValue", "dialog_value"); PowerMockito.when(pojoTutorial, "getProperties").thenReturn(properties); } public void getToHtlTest() { String expected = "dialog_value"; pojoTutorial.activate(); String actual = pojoTutorial.getToHtl(); assertEquals(expected, actual); } }
テストコード上でproperties.put()を実行することによってpropertiesを作成しなければならない上に、 getProperties
等のメソッドがfinalで宣言されているため、PowerMockitoでmock化する必要がある。
最後に
以上となります。
技術の選択で迷ったら新しい技術を使いましょうということですね。