servletsaemquery-builderpredicatesling

How to get properties of "jcr:content" of nested page


I am working in Adobe Experience Manager. I have one parent page News. This parent page have several nested pages. I am trying to get properties of all jcr:content node of nested pages. But I am getting null response.

Here down is the snapshot of CRDXE Page. I need all properties of jcr:content enter image description here

Here down is my code

NewsServiceImpl

@Component(service = NewsService.class)
public class NewsServiceImpl implements NewsService {

    
    @Reference
    private QueryBuilder queryBuilder;
    
    @Override
    public Optional<Iterator<Resource>> getNews(SlingHttpServletRequest request, String searchPath) {
        Iterator<Resource> resourceIterator = null;
        Session session = request.getResourceResolver().adaptTo(Session.class);
        final Map<String, String> map = new HashMap<>();
        map.put("path", searchPath);
        map.put("1_property", "sling:resourceType");
        map.put("1_property.value", "xxx/components/page");

        Query query = queryBuilder.createQuery(PredicateGroup.create(map), session);
        SearchResult result = query.getResult();
        resourceIterator = result.getResources();
        return Optional.ofNullable(resourceIterator);
    }
    
}

Servlet

@Component(service = Servlet.class, property = { Constants.SERVICE_DESCRIPTION + "= Get All News",
        SLING_SERVLET_METHODS + "=GET", SLING_SERVLET_PATHS + "=/bin/news" })
public class NewsServlet extends SlingSafeMethodsServlet {

    @Reference
    transient NewsService newsService;

    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("application/json;charset=utf-8");
        JsonArray resultArray = new JsonArray();
        Optional<Iterator<Resource>> isNews = newsService.getNews(request, request.getParameter("searchPath"));
        if (isNews.isPresent()) {
            Iterator<Resource> news = isNews.get();
            while (news.hasNext()) {
                Resource parentPageResource = news.next();
                        
                // is jcr:content present, Store response in resultArray
                if (parentPageResource.getChild("jcr:content") != null)
                {
                    resultArray.add(parentPageResource.getChild("jcr:content").getValueMap().toString());
                }
            }
        }
        response.getWriter().print(resultArray);
    }
}

Solution

  • Your Query finds the jcr:content nodes, as they contain the sling:resourceType property. For those nodes the getChild("jcr:content") will return null. Queries are searching for JCR-nodes, not for pages.

    FIRST I would strongly recommend to use the PageManager API to iterate over the entire news page-tree. Use queries only, if they are much more specific and touch much less content. But usually then you need to define an a pretty matching Oak:Index as well. Prefer NOT to use queries in page-rendering.

    SECOND If you search for pages, you can specify a type. This can improve performance significantly, as better (more specific) Oak:indexes can be used. QueryBuilder (and XPath) also support child-properties.

    type:              cq:Page
    path:              <searchPath...> 
    1_property:        jcr:content/sling:resourceType
    1_property.value:  xxx/components/page
    

    The alternative would be to search for cq:PageContent nodes (like your query)

    type:              cq:PageContent
    path:              <searchPath...> 
    1_property:        sling:resourceType
    1_property.value:  xxx/components/page