AbstractResourceVisitor for traversing resource trees


We often come across features that require traversal of a resource tree (e.g. processing assets in a folder). In such scenarios, recommendation is to use tree traversal than queries. More details of similar scenarios can found on link 

Sling provides AbstractResourceVisitor API, which performs traversal through a resource tree, allowing a developer to focus on processing child resources.

How to use AbstractResourceVisitor?

Step 1: Create class that extends AbstractResourceVisitor

Step 2: Implement visit() to process child resources

class ProcessChildVisitor extends AbstractResourceVisitor {
    @Override
    protected void visit(Resource resource) {
        //Business logic to process the resource
    }
}
  • The visit method will be called for each child resource of ‘parentResource’ mentioned in Step 3

Step 3: Initiate processing of child resources by calling accept() of class created in Step 2

    ProcessChildVisitor processChildVisitor = new ProcessChildVisitor();
    processChildVisitor.accept(parentResource);

Code for AbstractResourceVisitor class can be found on link

Improving traversal for specific node types

There might be instances, where we need to traverse only specific type of child resources (e.g. Assets). To implement such scenarios:

Step 1: Create a class that extends AbstractResourceVisitor

Step 2: Override accept() Or traverseChildren() method.

  • accept() decides if the child resources of current resource should be iterated.
  • traverseChildren() iterates over child resources.

Example: Consider that we need to iterate over all Assets in a folder. As we iterate, we should NOT process:

  • sub-folders, but only the assets that they contain.
  • resources below asset (e.g renditions).

Below is the snippet to implement such a Resource Visitor :

import org.apache.sling.api.resource.AbstractResourceVisitor;
import org.apache.sling.api.resource.Resource;

import com.adobe.granite.asset.api.Asset;

/**
* The <code>AbstractAssetVisitor</code> helps in traversing a
* resource tree by decoupling the actual traversal code
* from application code. Concrete subclasses should implement
* the {@link AbstractAssetVisitor#visit(Resource)} method.
*
*/
public abstract class AbstractAssetVisitor extends AbstractResourceVisitor {

    /**
    * Visit the given resource and all its descendants.
    * @param res The resource
    */
    @Override
    public void accept(final Resource res) {
        if (res != null) {
            visit(res);

            if(res.adaptTo(Asset.class)==null){
                traverseChildren(res.listChildren());
            }
        }
    }
}

4 thoughts on “AbstractResourceVisitor for traversing resource trees

  1. Interesting article Aanchal. I am trying to understand how this can elevate the use of queries. Using queries we specify dynamic conditions and return the required resource and read / update -> can the similar behavior be achieved with this?

    Can you please give additional use cases where this can be leveraged?

    Like

    1. Thanks Chetanya for the query. The choice between Traversal & Query depends on the use-case.
      Example:

      Traversals are faster and should be used when:
      1. We have to take some actions against child resources below a folder. The target child could also reside in various sub-folders of parent resource.
      2. Bunch of information is constructed by combining information from various content hierarchies. In such cases, if the information doesn’t change frequently, pre-cache the information as per link [1]

      More details can also be found at: https://docs.adobe.com/docs/en/aem/6-2/deploy/best-practices/best-practices-for-queries-and-indexing.html#When to Use Queries
      [1]: https://docs.adobe.com/docs/en/aem/6-2/develop/best-practices/jcr-integration.html#Avoid queries wherever possible

      Queries should still be used where Result sets are based on complex filters. Example: fulltext, range, custom predicates etc.

      Like

  2. Nice article..One doubt.. is this for traversal along nodes only or can we perform any operation on nodes also during traversing like modify jcr properties.

    2. Like through query builder we are able to read jcr properties based on some conditions and sending back to front end in json.
    Here is this possible as return type is void.

    Thanks

    Like

    1. Hello Chandrakant,

      Sure you can perform operation on nodes during traversal. Please commit the changes in batches (say 100) and not all at once.

      For 2nd Query regarding json, it might be worth to look at an implementation at link [2]. At link [2],
      – a class variable Set has been declared in WCMViewsResourceVisitor (i.e. during Step-2 in the blog post)
      – Values in Set are populated during traversal.
      – Once completed a public getter getWCMViews() is used to access the value from the instance of WCMViewsResourceVisitor (i.e. via WCMViewsResourceVisitor instance created during Step-3 )
      You can replace the Set with a JSONObject for the implementation

      [2]: https://github.com/Adobe-Consulting-Services/acs-aem-commons/blob/master/bundle/src/main/java/com/adobe/acs/commons/wcm/views/impl/WCMViewsServlet.java

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s