Resource Streams in Apache Sling | Perficient Digital

Resource Streams in Apache Sling


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:


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());
  }); 


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!

Leave a Reply