AEMContext not able to adapt to correct implementation class based on the models annotation resourceType property

Description

We implemented an interface with multiple implementations. To determine the "closest" implementation to use when adapting to the interface we configured the resourceType properties on the implementation classes as described here.

https://sling.apache.org/documentation/bundles/models.html#associating-a-model-class-with-a-resource-type-since-1-3-0-

This works on a AEM instance, but when we wrote a test to validate that the correct implementation is used with certain resourceTypes we noticed that the AEMContext is not behaving as we expected.
It seems it doens't take the resourceType property into account when deciding.
Right now when multiple implementations are found, it seems it just takes the first implementation that matches based on the alphabetical order of the class names.

Code example

public interface FooterComponent { ... } @Model(adaptables = SlingHttpServletRequest.class, adapters = {FooterComponent.class}, resourceType = "base/components/navigation/footer-component") public class BaseFooterComponentImpl implements FooterComponent { ... } @Model(adaptables = SlingHttpServletRequest.class, adapters = {FooterComponent.class}, resourceType = "custom/components/navigation/footer-component") public class CustomFooterComponentImpl implements FooterComponent { ... }

Test Example

@RunWith(MockitoJUnitRunner.class) public class CustomFooterComponentImplTest { @Rule public final AemContext context = new AemContext(); @Before public void setUp() throws Exception { context.load().json("myFooter.json", "/content"); } @Test public void validFooter_validateCorrectImplementationClass() { context.currentPage(); Resource resource = context.resourceResolver().getResource("/content/jcr:content/valid"); context.request().setResource(resource); FooterComponent component = context.request().adaptTo(FooterComponent.class); //expected value based on json assertTrue(component instanceof CustomFooterComponentImpl); } }

Test JSON

{ "jcr:primaryType": "cq:Page", "jcr:content": { "jcr:primaryType": "cq:PageContent", "valid": { "sling:resourceType": "custom/components/navigation/footer-component" } } }

We assume that the reason for this behaviour is because the aem-mock still uses an old sling.api version 2.11.0 whereas AEM already uses the newer 2.18.4 version that includes this functionality.
Functionality is available version 2.13+

WCM.io mvn dependency:tree

[INFO] +- io.wcm:io.wcm.testing.aem-mock.junit4:jar:2.6.0:test [INFO] | +- io.wcm:io.wcm.testing.aem-mock.core:jar:2.6.0:test [INFO] | | +- org.apache.sling:org.apache.sling.api:jar:2.11.0:test

AEM 6.4 Sling Api bundle

<dependency> <artifactId>org.apache.sling.api</artifactId> <version>2.18.4</version> <groupId>org.apache.sling</groupId> <scope>provided</scope> </dependency>

Activity

Show:

Ben Oeyen July 29, 2019 at 1:54 PM

Thx Stefan for the blazing fast reply!

We managed to get our tests working now, thanks for explaining.

 

Stefan Seifert July 29, 2019 at 1:44 PM

Stefan Seifert July 29, 2019 at 1:43 PM

this should work OOTB - but: you have to make sure to reference a version of the sling models implementation JAR matching those of your AEM version. Sling Mocks (and AEM Mocks) is designed to work with multiple AEM versions, thus it references an older set of implementation JARs roughly from AEM 6.2. but it works if you reference newer set of the implementation JARs.

to make this easier you can the AEM dependencies for the AEM version you are using from these helper POMs:
https://wcm.io/tooling/maven/aem-dependencies.html

this not only defines the version of the uber-jar, but also the fitting versions of the implementation JARs required by Sling/AEM Mocks.

Done

Details

Assignee

Reporter

Labels

Components

Priority

Created July 29, 2019 at 1:31 PM
Updated July 29, 2019 at 2:05 PM
Resolved July 29, 2019 at 2:05 PM