Remove ghost nodes for multiple pages at once | Community
Skip to main content
April 24, 2024
Solved

Remove ghost nodes for multiple pages at once

  • April 24, 2024
  • 3 replies
  • 1131 views

Hi,

We have more than 260 pages with the ghost nodes.

For example on this path(/content/products/en-us//Efficiency/compressor-monitoring/jcr:content/root/body-container/scrolling_panel/item_1657619257205/download_library) we deleted download library panel component inside the live copy AEM creates a placeholder ghost component for it. 

Like this, we have multiple pages .

Is there any way to remove ghost nodes like any shell script or any other way.

 

 

 

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by sravs

Write a groovy script to fetch the nodes with the resource type as wcm/msm/components/ghost and delete them. Once upon the deletion save the session. Please refer sample snippet

 

 

import javax.jcr.query.Query; import javax.jcr.Node; import java.util.List import groovy.transform.Field def query = createSQL2Query() def result = query.execute(); def rows = result.rows def total = 0 List<String> list = new ArrayList<>(); List<String> updatedList = new ArrayList<>(); rows.each{ row -> println row.path; Resource res = resourceResolver.getResource(row.path); Node currentNode = res.adaptTo(javax.jcr.Node); currentNode.remove(); session.save(); total++ } println "Total nodes :: "+ total def createSQL2Query(){ def queryManager = session.workspace.queryManager def statement = "select child.[jcr:path] from [cq:Page] AS page INNER JOIN [cq:PageContent] AS jcrContent ON ISCHILDNODE(jcrContent, page) INNER JOIN [nt:unstructured] AS child ON ISDESCENDANTNODE(child, jcrContent) where ISDESCENDANTNODE(page, '/content/PROJECT_DIR') and child.[sling:resourceType] = 'wcm/msm/components/ghost'"; //println statement def query = queryManager.createQuery(statement,Query.JCR_SQL2) query.setLimit(3000); query.setOffset(0); query }

 

 

You can run a dry run by commenting session.save() to check whether its listing exact paths or not.

Hope this helps!!

3 replies

sravs
Community Advisor
sravsCommunity AdvisorAccepted solution
Community Advisor
April 24, 2024

Write a groovy script to fetch the nodes with the resource type as wcm/msm/components/ghost and delete them. Once upon the deletion save the session. Please refer sample snippet

 

 

import javax.jcr.query.Query; import javax.jcr.Node; import java.util.List import groovy.transform.Field def query = createSQL2Query() def result = query.execute(); def rows = result.rows def total = 0 List<String> list = new ArrayList<>(); List<String> updatedList = new ArrayList<>(); rows.each{ row -> println row.path; Resource res = resourceResolver.getResource(row.path); Node currentNode = res.adaptTo(javax.jcr.Node); currentNode.remove(); session.save(); total++ } println "Total nodes :: "+ total def createSQL2Query(){ def queryManager = session.workspace.queryManager def statement = "select child.[jcr:path] from [cq:Page] AS page INNER JOIN [cq:PageContent] AS jcrContent ON ISCHILDNODE(jcrContent, page) INNER JOIN [nt:unstructured] AS child ON ISDESCENDANTNODE(child, jcrContent) where ISDESCENDANTNODE(page, '/content/PROJECT_DIR') and child.[sling:resourceType] = 'wcm/msm/components/ghost'"; //println statement def query = queryManager.createQuery(statement,Query.JCR_SQL2) query.setLimit(3000); query.setOffset(0); query }

 

 

You can run a dry run by commenting session.save() to check whether its listing exact paths or not.

Hope this helps!!

Kamal_Kishor
Community Advisor
Community Advisor
April 24, 2024

@vani1012 : This could be useful for you: https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/issue-with-wcm-msm-components-ghost/m-p/371261

basically, instead of deleting the ghost nodes, you can implement the approach mentioned in the previously accepted response. These ghost nodes will be needed if you have to restore the inheritance for removed section at some point in future which is a valid use-case to re-store the previously existing content.

thanks.

HrishikeshKagne
Community Advisor
Community Advisor
May 5, 2024

Hi @vani1012 ,

Yes, you can use a Java-based approach to remove ghost nodes from multiple pages in Adobe Experience Manager (AEM). You can write a custom Java program to iterate over the pages and remove the ghost nodes programmatically. Here's a general outline of how you can do it:

  1. Identify Ghost Nodes:

    • Use the CRXDE Lite or QueryBuilder to identify the paths of pages containing ghost nodes. Ghost nodes typically have a type of sling:nonexisting.
  2. Develop a Java Program:

    • Write a custom Java program using AEM's Java API to remove the identified ghost nodes. You can use the ResourceResolver API to access and manipulate resources in the JCR repository.
  3. Example Java Code:

    • Here's a simplified example of Java code to remove ghost nodes from multiple pages:

 

import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.Workspace; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.ResourceResolverFactory; public class RemoveGhostNodes { private ResourceResolver resourceResolver; public RemoveGhostNodes(ResourceResolverFactory resourceResolverFactory) { try { // Get a resource resolver resourceResolver = resourceResolverFactory.getServiceResourceResolver(null); } catch (Exception e) { // Handle exception } } public void removeGhostNodes(String[] paths) { for (String path : paths) { try { // Get the page resource Resource pageResource = resourceResolver.getResource(path); if (pageResource != null) { Node pageNode = pageResource.adaptTo(Node.class); if (pageNode != null) { // Remove ghost nodes NodeIterator childNodes = pageNode.getNodes(); while (childNodes.hasNext()) { Node childNode = childNodes.nextNode(); if (childNode.isNodeType("sling:nonexisting")) { childNode.remove(); } } pageNode.getSession().save(); } } } catch (RepositoryException e) { // Handle exception } } } public static void main(String[] args) { // Initialize the RemoveGhostNodes class with a resource resolver factory // (Inject the resource resolver factory as needed) RemoveGhostNodes remover = new RemoveGhostNodes(resourceResolverFactory); // Call the removeGhostNodes method with paths containing ghost nodes remover.removeGhostNodes(new String[] { "/content/products/en-us/page1", "/content/products/en-us/page2", ... }); } }

 

  1. Execute the Java Program:

    • Compile the Java program and execute it in your AEM environment.
  2. Testing and Validation:

    • Test the Java program thoroughly in a non-production environment before applying it to production. Ensure that it successfully removes ghost nodes without causing any unintended side effects.

This Java-based approach allows you to programmatically remove ghost nodes from multiple pages in AEM efficiently. However, always exercise caution when making changes directly to the content repository and test thoroughly before applying changes in a production environment.

Hrishikesh Kagane