Expand my Community achievements bar.

SOLVED

Groovy script to insert jcr:Content node at folder level

Avatar

Level 3

Hi, after running Best Practices Analyzer tool, we have found lot of issues with " is missing mandatory 'jcr:content' child node." in some of our folders. how to fix this issue? i know a groovy script can be used, but any other ways?

with groovy script can we insert an empty jcr:content node to fix the issue? if yes, any code snipped to help achieve this?

thank

 

I went through https://github.com/hashimkhan786/aem-groovy-scripts , but couldn't find any script to help in the direction iam looking for

Topics

Topics help categorize Community content and increase your ability to discover relevant content.

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hey @ASP_Corp ,

Yes, a Groovy script can be used to fix this issue efficiently. Below is a Groovy script that recursively scans and adds the missing jcr:content nodes to cq:Page under a given path. Similarly, you can update for other node primary types.

import com.day.cq.commons.jcr.JcrUtil
import javax.jcr.*

def session = resourceResolver.adaptTo(Session)
def rootPath = "/content/we-retail/it" // Change this to the desired root path

def processNode(node) {
    if (!node.hasNode("jcr:content")) {
        def contentNode = node.addNode("jcr:content", "nt:unstructured")
        contentNode.setProperty("createdBy", session.getUserID())
        contentNode.setProperty("createdDate", Calendar.getInstance())
        println "Added missing jcr:content node at: ${node.path}"
    }
}

// Recursively scan folders and add missing jcr:content nodes
def scanAndFixMissingContentNodes(node) {
    
    if (node.isNodeType("cq:Page")) { //Use other condition to handle the allowed primanryType to add child jcr:content
        processNode(node)
    }
    def nodeIterator = node.getNodes()
    while (nodeIterator.hasNext()) {
        scanAndFixMissingContentNodes(nodeIterator.nextNode())
    }
}

def rootNode = session.getNode(rootPath)
scanAndFixMissingContentNodes(rootNode)

session.save()
println "Completed processing for missing jcr:content nodes."

Regards,

Shiv Prakash

View solution in original post

5 Replies

Avatar

Correct answer by
Community Advisor

Hey @ASP_Corp ,

Yes, a Groovy script can be used to fix this issue efficiently. Below is a Groovy script that recursively scans and adds the missing jcr:content nodes to cq:Page under a given path. Similarly, you can update for other node primary types.

import com.day.cq.commons.jcr.JcrUtil
import javax.jcr.*

def session = resourceResolver.adaptTo(Session)
def rootPath = "/content/we-retail/it" // Change this to the desired root path

def processNode(node) {
    if (!node.hasNode("jcr:content")) {
        def contentNode = node.addNode("jcr:content", "nt:unstructured")
        contentNode.setProperty("createdBy", session.getUserID())
        contentNode.setProperty("createdDate", Calendar.getInstance())
        println "Added missing jcr:content node at: ${node.path}"
    }
}

// Recursively scan folders and add missing jcr:content nodes
def scanAndFixMissingContentNodes(node) {
    
    if (node.isNodeType("cq:Page")) { //Use other condition to handle the allowed primanryType to add child jcr:content
        processNode(node)
    }
    def nodeIterator = node.getNodes()
    while (nodeIterator.hasNext()) {
        scanAndFixMissingContentNodes(nodeIterator.nextNode())
    }
}

def rootNode = session.getNode(rootPath)
scanAndFixMissingContentNodes(rootNode)

session.save()
println "Completed processing for missing jcr:content nodes."

Regards,

Shiv Prakash

Avatar

Level 5

@ASP_Corp  by any chance folders are indexed and if jcr:content nodes are missing in multiple paths where each path contains huge data then better to go with (SQL2 query + groovy script) instead of iterating the nodes in groovy script . To avoid putting a check for each node and checking if is a folder and then folder has node jcr:content, you can directly write a SQL2 query  which will directly give you the folders which doesn't have jcr:content nodes. Sample code is 

import javax.jcr.Session
import javax.jcr.query.Query
import javax.jcr.query.QueryManager
import javax.jcr.query.QueryResult

def session = resourceResolver.adaptTo(Session.class)//get resolver first and then session
def queryManager = session.workspace.queryManager// get query manager

def folderPath = "/path/to/your/folder" // Replace with your folder path

// SQL2 query to find folders missing jcr:content nodes
def sql2Query = """
    SELECT * FROM [nt:folder] AS folder
    WHERE ISDESCENDANTNODE(folder, '${folderPath}')
    AND NOT EXISTS (SELECT * FROM [nt:base] AS content WHERE ISCHILDNODE(content, folder) AND NAME(content) = 'jcr:content')
"""
//You can try below query in above sql2Query variable: 
SELECT * FROM [nt:folder] AS folder
WHERE ISDESCENDANTNODE(folder, '/path/to/your/folder')
AND folder.[jcr:content/jcr:primaryType] IS NULL


def query = queryManager.createQuery(sql2Query, Query.JCR_SQL2)
def result = query.execute()

result.nodes.each { node ->
    def folderNode = node
    if (!folderNode.hasNode("jcr:content")) {
        def jcrContentNode = folderNode.addNode("jcr:content", "nt:unstructured")
        jcrContentNode.setProperty("jcr:primaryType", "nt:unstructured")
        session.save()
        println "Added jcr:content node to ${folderNode.path}"
    }
}

 

Thanks

Ramesh

Avatar

Level 3

Hi Ramesh,

thanks for the help. the query 

SELECT * FROM [nt:folder] AS folder
WHERE ISDESCENDANTNODE(folder, '/path/to/your/folder')
AND folder.[jcr:content/jcr:primaryType] IS NULL

is giving out a lot of results and along with the folders it is giving the renditions too. for e.g it gives /content/dam/_folder and also /content/dam/_CSS/_OOTB/AudioCaptionsButton_sprite.png/jcr:content/renditions ..etc...we are expecting 345 results from the BPA but the query is giving around 60000 results

Avatar

Administrator

@ASP_Corp Did you find the suggestion helpful? Please let us know if you need more information. If a response worked, kindly mark it as correct for posterity; alternatively, if you found a solution yourself, we’d appreciate it if you could share it with the community. Thank you!



Kautuk Sahni

Avatar

Administrator

@ASP_Corp Did you find the suggestions helpful? Please let us know if you need more information. If a response worked, kindly mark it as correct for posterity; alternatively, if you found a solution yourself, we’d appreciate it if you could share it with the community. Thank you!



Kautuk Sahni