Unit Testing JCR Resource Resolver Mappings

Website Design. Developing Programming And Coding Technologies.

Recently, I had a task to shorten URLs and remove the HTML extension in AEM. On top of that, I had to add a context root to the URLs so that these mappings would happen.

  • /content/myapp/en_US.html -> /mycontext/
  • /content/myapp/en_US/homepage.html -> /mycontext/homepage/
  • /content/myapp/es_ES.html -> /mycontext/es_ES/
  • /content/myapp/es_ES/homepage.html -> /mycontext/es_ES/homepage/

Shorting URLs in AEM consists of two things:

  • The dispatcher will receive requests for short extension-less URLs and must rewrite them before passing them through to the publishers.
  • The links within the HTML markup rendered by AEM must be rewritten to their short extension-less versions.

Setting up Apache is straight forward. You need to inspect the incoming request and translate it to its long version before sending it on to AEM. What I had trouble with was configuring the Sling mappings to rewrite URLs. There are 2 ways to achieve this:

  • Update the content under /etc/map
  • Add the mapping to the resource.resolver.mapping property of the OSGi configuration

What I Do

In general, I have always opted for the second. I find it is simpler to manage than managing content under /etc/map. The only annoying thing is that if you make a change it causes every OSGi component that depends on it to restart. Having to wait a long time between changes is frustrating. This is especially true if I am trying to work out new mapping rules.

Nowadays, I find myself doing more and more TDD. In particular, I’ve been leveraging Sling Mocks. With JUnit 5 and AssertJ, I can develop Sling Models and OSGi components without ever having to load a page.

And this is it! I wrote the unit test and then I focused on creating a set of outgoing mappings. Once satisfied, I popped them into the OSGi configuration. Then, I sat around for 7 minutes until the system became responsive again, and the job was complete!

import static org.assertj.core.api.Assertions.assertThat;
import org.apache.commons.lang3.ArrayUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import io.wcm.testing.mock.aem.junit5.*;

class UrlMappingTest {

    private static final ImmutableMap<String, Object> PROPERTIES =
        ImmutableMap.of("resource.resolver.mapping", ArrayUtils.toArray(

    private final AemContext context =
            new AemContextBuilder().resourceResolverType(ResourceResolverType.JCR_MOCK)

    public void testShortExtensionlessMappings() {

        final ResourceResolver resourceResolver = this.context.resourceResolver();

        final String defaultLocaleRoot =

        final String defaultLocalePath =

        final String localeRoot =

        final String localePath =

        final String qsParams =

I hope you found this blog post useful. For any additional questions, please comment below and be sure to check out our other Adobe blogs.

About the Author

Juan Ayala is a Lead Developer in the Adobe practice at Perficient, Inc., focused on the Adobe Experience platform and the things revolving around it.

More from this Author

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Subscribe to the Weekly Blog Digest:

Sign Up