Adobe

Resource Streams in Apache Sling

Resource Stream Hero


Jörg Hoh recently wrote an interesting post on Content Architecture where he discussed how expensive JCR Queries could instead be replaced with targeted content structure traversals to allow finding relevant content without searching the whole AEM repository. Unfortunately, from a developer perspective, this means writing a fair amount of boilerplate code to traverse the AEM repository and then identify the relevant Resources.

Fortunately, a new API was just released by the Apache Sling team. This API was created by Jason Bailey and adds support for  using Lambda expressions to filter a stream of Resources from the Sling repository.

This new Resource Filter API allows AEM / Sling developers to be significantly more succinct and readable and how they perform common repository traversals. It’s not a pure replacement of JCR queries or or the traditional method of traversing the repository, but for simple content structures you can do a lot more with a lot less code.


Resource Filter Example


Here’s an example of how one could extract a stream of resources by a page’s component type under a cq:Page:

Innovation & Product Development -- Accelerate Your Sharepoint Intranet with Rise
Accelerate Your SharePoint Intranet with Rise

Discover how to get more from your investment in Office 365 with Rise, Perficient’s Intranet-as-a-Service offering by reducing your intranet’s project duration with out-of-the-box solutions, decreasing your project’s risk, and increasing your intranet’s value.

Get the Guide


log.info("Filtering by type: {}", type);
ResourceFilterStream resourceStream = resource.adaptTo(ResourceFilterStream.class);
resourceStream.setBranchSelector("[jcr:primaryType] == 'cq:Page'")
  .setChildSelector("[jcr:content/sling:resourceType] == $type")
  .addParam("type", type).stream()
  .forEach(r -> {
    log.info(r.getPath());
  }); 
<br clear="none">

The equivalent pre-Stream code is quite a bit more verbose, even in this simple example:


log.info("Filtering by type: {}", type);
public void traverseChildren(Resource parent){
  for(Resource child : parent.getChildren()){
    if("cq:Page".equals(child.getResourceType())) {
      Resource content = child.getChild("jcr:content");
      if(content != null && type.equals(content.getValueMap("sling:resourceType","")){
        log.info(r.getPath());
      }
      traverseChildren(child);
    }
  }
}
[...]
traverseChildren(resource);


In this example, we are just writing the resource to a JSON Array using the javax.json API, but once you have a stream of Resources, you can use any Lambda function to then process or further filter the stream.


Adding the Resource Filter API in your Project


Adding the Resource Filter API into your project takes two steps. First add the dependency into your project’s POM:


<dependency>
    <groupid>org.apache.sling</groupid>
    <artifactid>org.apache.sling.resource.filter</artifactid>
    <version>1.0.0</version>
    <scope>provided</scope>
</dependency>


Once you have your code developed, you can add the Resource Filter bundle into your package build.

Please leave a comment below if you have any questions about the Apache Sling Resource Stream API!

About the Author

Dan is a certified Adobe Digital Marketing Technologist, Architect, and Advisor, having led multiple successful digital marketing programs on the Adobe Experience Cloud. He's passionate about solving complex problems and building innovative digital marketing solutions. Dan is a PMC Member of the Apache Sling project, frequent Adobe Beta participant and committer to ACS AEM Commons, allowing a unique insight into the cutting edge of the Adobe Experience Cloud platform.

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