May 10, 2020
Estimated Post Reading Time ~

How to query JCR data in Adobe AEM

Different handy techniques to write JCR query in AEM/CQ:
For a Detailed Study on JCR Queries Please see this article.
JCR SQL 2 FULL Tutorial: CHEAT SHEET

Java content repository, better known as JCR is a modern approach to our database solutions.
While working on JCR I found many rather simple techniques to write JCR queries from our JAVA application.
Some of them have been described below to help fellow developers.

For this example, we will try to fetch all the "employee" nodes under the "codermagnet" parent node.
Jcr%2BQuery%2BExample%2Bby%2BCodermagnet

Download the Jack Rabbit Jar File form
http://www.apache.org/dyn/closer.cgi/jackrabbit/2.8.1/jackrabbit-standalone-2.8.1.jar
and place the Jack Rabbit jar in the build path of your project.

OPTION 1: Querying JCR using QueryManager API
Create a new class file as shown below.

File: JCRQueryExample.java
package net.codermag.jcr.test;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Repository;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;

import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.jackrabbit.core.TransientRepository;

public class JCRQueryExample { 
 public static void main(String[] args) throws Exception {

  // Create a Session
  Repository repository = new TransientRepository();
  repository = JcrUtils.getRepository("http://localhost:4502/crx/server");
  Session session = repository.login(new SimpleCredentials("admin","admin".toCharArray()));

  //Building and Executing the Query
  QueryManager queryManager = session.getWorkspace().getQueryManager();
  String sqlStatement = "SELECT * FROM [nt:base] AS s WHERE ISDESCENDANTNODE([/content/codermagnet/employees])";
  Query query = queryManager.createQuery(sqlStatement, "JCR-SQL2");
  QueryResult result = query.execute();

  //Doing Something with the nodes returned.. Printing the paths
  NodeIterator iterator = result.getNodes();
  while (iterator.hasNext()) {
   System.out.println(((Node) iterator.next()).getPath());
  }
 }
}

Output:
/content/codermagnet/employees/kuper
/content/codermagnet/employees/john
/content/codermagnet/employees/harry
/content/codermagnet/employees/smith

OPTION 2: Quering JCR using ResourceResolver.findResources() method.
Another very handy and short way of doing this is illustrated below. This is my favorite as its a one-liner query and is cute, clean, and fast. One point that we need to remember while doing this is that for this second option we need the implicit "ResourceResolver" object. So this is more appropriate to be used as some sort of sling service inside our JCR application.

File: JCRQueryExample2.java
package net.codermag.jcr.test;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.jcr.Node;
import javax.jcr.query.Query;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;

public class JCRQueryExample2 {

 public List<Node> getNodes(SlingHttpServletRequest request)
   throws Exception {

  List<Node> nodes = new ArrayList<Node>();
  ResourceResolver resolver = request.getResourceResolver();
  
  // Executing query in One Line....!!!!
  Iterator<Resource> nodeIter = resolver
    .findResources("SELECT * FROM [nt:base] AS s WHERE ISDESCENDANTNODE([/content/codermagnet/employees])",
      Query.JCR_SQL2);
   
  // Converting the Resource object to Node and then storing as arraylist
  while (nodeIter.hasNext()) {
   nodes.add(nodeIter.next().adaptTo(Node.class));
  }
  return nodes;
 }
}

Option 3: Quering JCR using QueryBuilder API
File:JCRQueryExample3.java

Note: For testing the below XPATH query beforehand you can use the QueryBuilder debugger console at this URL
http://localhost:4502/libs/cq/search/content/querydebug.html

package com.realogy.sir.core.servlets;

import java.util.HashMap;
import java.util.Map;
import javax.jcr.Session;
import org.apache.sling.api.SlingHttpServletRequest;
import com.day.cq.search.PredicateGroup;
import com.day.cq.search.Query;
import com.day.cq.search.QueryBuilder;
import com.day.cq.search.result.Hit;
import com.day.cq.search.result.SearchResult;

public class JCRQueryExample3 {

 public void getNodes(SlingHttpServletRequest request)throws Exception {

  //Form the map and fill all the required parameters in the map
  Map<String,String> map = new HashMap<String,String>();
  map.put("path", "/content/codermagnet/employees");
  map.put("type", "nt:base");
  map.put("orderby","@name");
  
  //Quering JCR using com.day.cq.search.QueryBuilder API
  PredicateGroup predicateGroup = PredicateGroup.create(map);
  QueryBuilder builder = request.getResourceResolver().adaptTo(QueryBuilder.class);
  Query query = builder.createQuery(predicateGroup, request.getResourceResolver().adaptTo(Session.class));
  SearchResult result = query.getResult();

  //Do something with the results
  for (Hit hit : result.getHits()) {
   String path = hit.getPath();
   System.out.println(path);
  } 
 }
}

Output:
/content/codermagnet/employees/harry
/content/codermagnet/employees/john
/content/codermagnet/employees/kuper
/content/codermagnet/employees/smith

You can use Option 2 and Option 3 when writing servlets or inside scriptlet tags in AEM JSP pages where you have access or can derive the "resourceResolver" implicit object. In the above option, I have derived the "resourceResolver" object from the org.apache.sling.api.SlingHttpServletRequest that is passed to the method.


By aem4beginner

No comments:

Post a Comment

If you have any doubts or questions, please let us know.