Expand my Community achievements bar.

SOLVED

AdapterFactory, SlingAdaptable and caching

Avatar

Level 1

I struggle to understand how the built-in caching mechanism of Sling works when using AdapterFactory.

 

Here is my first AdapterFactory:

 

@component(
        property = {
                AdapterFactory.ADAPTABLE_CLASSES + "=org.apache.sling.api.SlingHttpServletRequest",
                AdapterFactory.ADAPTER_CLASSES + "=com.example.Foo"
        }
)
public final class FooAdapterFactory implements AdapterFactory {
    @Override
    public <AdapterType> AdapterType getAdapter(Object adaptable, Class<AdapterType> adapterTypeClass) {
        SlingHttpServletRequest request = (SlingHttpServletRequest) adaptable;
        return Optional.ofNullable(request.getResourceResolver().adaptTo(PageManager.class))
                .map(pageManager -> pageManager.getContainingPage(request.getResource()))
                .map(page -> page.getContentResource())
                // the following line is not cached:
                .map(contentResource -> contentResource.adaptTo(Bar.class))
                // continue the chain with the Bar instance
                .map(...)
                .orElse(null);
    }
}

 

 

And the my second AdapterFactory:

 

@component(service = AdapterFactory.class,
        property = {
                AdapterFactory.ADAPTABLE_CLASSES + "=org.apache.sling.api.resource.Resource",
                AdapterFactory.ADAPTER_CLASSES + "=com.example.Bar"
        }
)
public final class BarAdapterFactory implements AdapterFactory {
    @Override
    public <AdapterType> AdapterType getAdapter(Object adaptable, Class<AdapterType> adapterTypeClass) {
        Resource resource = (Resource) adaptable;
        // perform costly operation using the resource
        // ...
    }
}

 

 

From the sightly template, I call the FooAdapterFactory from various locations (multiple components on the same page use Foo) with:

 

<sly data-sly-use.foo="com.example.Foo" />

 

 

For a single HTTP request to /content/example/mypage.html, I would expect the second call (and the following ones) to contentResource.adaptTo(Bar.class) to be cached as contentResource is a JcrNodeResource, which extends SlingAdaptable. and therefore should be cached by Sling from what I understand.
However, this is not the case and my costly operation done in BarAdapterFactory.getAdapter() is called for each call to <sly data-sly-use.foo="com.example.Foo" />.

Can someone point out what I am missing here please? Or is there a better to achieve what I am trying to do? 
Thanks in advance

1 Accepted Solution

Avatar

Correct answer by
Community Advisor
1 Reply

Avatar

Correct answer by
Community Advisor