AEM — Script for Property and Value Finder Based on Resource Type and Root Page Path
When working with data validation or content, it’s often necessary to verify that certain property names and values exist OR not exist and…
AEM — Script for Property and Value Finder Based on Resource Type and Root Page Path
When working with data validation or content, it’s often necessary to verify that certain property names and values exist OR not exist and behave as expected.
To streamline this process, developed a generic, reusable script designed to handle common search scenarios efficiently. This script can be easily adapted and integrated into various projects for quick checks and validations.
Every project, regardless of size or complexity, will likely require this type of validation at some point. Having a ready-to-use script like this helps avoid repetitive coding and ensures consistency across teams and environments.
It covers all generic senarios and feel free to customize and extend the script to fit your particular project needs.
Below inline generic script/code will allow us to validate the following search scenarios based on root page path, resource type, property names and values:
- Exact match of property name Exist or NOT
- Exact match of property name and value
- Exact match of property name and contains value

Scenarios
The script supports the following key use cases:
Exact Match — Property Name Exists or Not:
Quickly determine whether a specific property name is present in the data structure or configuration.
Property Not Exist: Find out node names if given property Not Exist for particular resource type:
Property Exist: Find out node names if given property Exist for particular resource type irrespective of value.
Exact Match — Property Name and Value:
Ensure that a property not only exists but also holds the exact value you’re expecting.
Exact Match — Property Name and Contains Value:
Validate that a property contains a specific substring or partial value, helpful for pattern-based validations.
Java Code Script
Copy and paste the recursive code snippet below into your project, then access the provided URL to verify whether the we-retail content hierarchy is present.
If the we-retail content is not available in your environment, update the request parameters to match your project’s specific structure.
import com.adobe.aemds.guide.utils.JcrResourceConstants;
import com.adobe.granite.rest.Constants;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@Component(
immediate = true,
service = Servlet.class,
property = {
"sling.servlet.extensions=json",
"sling.servlet.paths=/services/findnodes",
"sling.servlet.methods="+ HttpConstants.METHOD_GET
}
)
public class OpenInNewTabServlet extends SlingAllMethodsServlet {
private final Logger LOGGER = LoggerFactory.getLogger(OpenInNewTabServlet.class);
/*
Property Not Exist
http://localhost:4502/services/findnodes?rootPagePath=/content/we-retail&resourceType=weretail/components/content/heroimage&propertyName=useFullWidth&existNotExist=notExist
Property Exist
http://localhost:4502/services/findnodes?rootPagePath=/content/we-retail&resourceType=weretail/components/content/heroimage&propertyName=useFullWidth&existNotExist=exist
Property Exist && Having Value
http://localhost:4502/services/findnodes?rootPagePath=/content/we-retail&resourceType=weretail/components/content/heroimage&propertyName=useFullWidth&propertyValue=true
Property Exist && Contains Value
http://localhost:4502/services/findnodes?rootPagePath=/content/we-retail&resourceType=weretail/components/content/title&propertyName=jcr:title&propertyValue=Discover&valueSearchType=contains
*/
// Below are REQUIRED parameters.
private static final String ROOT_PAGE_PATH_PARAM = "rootPagePath";
private static final String RESOURCE_TYPE_PARAM = "resourceType";
private static final String PROPERTY_NAME_PARAM = "propertyName";
// Below are all the OPTIONAL parameters.
// This is an optional parameter to pass if value need to get check.
private static final String PROPERTY_VALUE_PARAM = "propertyValue";
// valueSearchType = contains ; This is an option parameter is required only for checking if value contains.
private static final String PROPERTY_VALUE_SEARCH_TYPE = "valueSearchType";
/*
This is an optional parameter to check property key name exists or not
excludeInclude = exist OR excludeInclude = notExist.
*/
private static final String EXIST_NOT_EXIST = "existNotExist";
@Reference
private PracticePathUtilsService practicePathUtilsService;
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
// Collect values from all request Parameters
String rootPagePath = request.getParameter(ROOT_PAGE_PATH_PARAM);
String resourceType = request.getParameter(RESOURCE_TYPE_PARAM);
String propertyName = request.getParameter(PROPERTY_NAME_PARAM);
String propertyValue = request.getParameter(PROPERTY_VALUE_PARAM);
String existNotExist = request.getParameter(EXIST_NOT_EXIST);
String valueSearchType = request.getParameter(PROPERTY_VALUE_SEARCH_TYPE);
if (rootPagePath == null || rootPagePath.isEmpty()) {
response.sendError(SlingHttpServletResponse.SC_BAD_REQUEST, "Root page path parameter is required.");
return;
}
if (resourceType == null || resourceType.isEmpty()) {
response.sendError(SlingHttpServletResponse.SC_BAD_REQUEST, "Resource type parameter is required.");
return;
}
if (propertyName == null || propertyName.isEmpty()) {
response.sendError(SlingHttpServletResponse.SC_BAD_REQUEST, "Property name parameter is required.");
return;
}
PrintWriter out = getPrintWriter(response, resourceType, propertyName, existNotExist, propertyValue, valueSearchType);
List<String> componentNodes = findComponentsByResourceTypeWithoutProperty(rootPagePath,
resourceType, propertyName, propertyValue, existNotExist, valueSearchType, out);
out.println("</table>");
out.println("</br>");
out.println("<h3> Total Results : " + componentNodes.size() + " </h3> ");
out.close();
}
private List<String> findComponentsByResourceTypeWithoutProperty(String rootPagePath, String resourceType,
String propertyName, String propertyValue, String existNotExist, String valueSearchType, PrintWriter out) {
List<String> componentNodes = new ArrayList<>();
ResourceResolver resourceResolver = practicePathUtilsService.getSystemUserResourceResolver();
PageManager pageManager = resourceResolver.adaptTo(PageManager.class);
try {
Page rootPage = pageManager != null ? pageManager.getPage(rootPagePath) : null;
if (rootPage != null) {
Node rootPageNode = resourceResolver.getResource(rootPagePath).adaptTo(Node.class);
if (null != rootPageNode) {
findComponentsRecursively(resourceResolver, rootPageNode, componentNodes,
resourceType, propertyName, propertyValue, existNotExist, valueSearchType, out);
}
}
} catch (RepositoryException e) {
LOGGER.error("Error while searching for components: ", e);
}
return componentNodes;
}
private void findComponentsRecursively(ResourceResolver resolver, Node node, List<String> componentNodes, String resourceType,
String propertyName, String propertyValue, String existNotExist, String valueSearchType, PrintWriter out) throws RepositoryException {
if (node.hasProperty(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY) &&
node.getProperty(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY).getString().equals(resourceType)) {
boolean hasProperty = node.hasProperty(propertyName);
validateConditions(resolver, node, componentNodes, propertyName, propertyValue, existNotExist, valueSearchType, out, hasProperty);
}
NodeIterator nodeIterator = node.getNodes();
while (nodeIterator.hasNext()) {
Node childNode = nodeIterator.nextNode();
findComponentsRecursively(resolver, childNode, componentNodes, resourceType,
propertyName, propertyValue, existNotExist, valueSearchType, out);
}
}
private void validateConditions(ResourceResolver resolver, Node node, List<String> componentNodes, String propertyName, String propertyValue, String existNotExist, String valueSearchType, PrintWriter out, boolean hasProperty) throws RepositoryException {
if (hasProperty && StringUtils.isNotEmpty(propertyValue)) {
if (StringUtils.equalsIgnoreCase("contains", valueSearchType) &&
StringUtils.contains(node.getProperty(propertyName).getValue().getString(), propertyValue)) {
collectValuesInList(resolver, node, componentNodes, out);
} else if (StringUtils.equalsIgnoreCase(node.getProperty(propertyName).getValue().getString(), propertyValue)) {
collectValuesInList(resolver, node, componentNodes, out);
}
} else if (StringUtils.isNotEmpty(existNotExist) && StringUtils.isEmpty(propertyValue)){
if (existNotExist.equalsIgnoreCase("notExist") && !hasProperty ||
existNotExist.equalsIgnoreCase("exist") && hasProperty) {
collectValuesInList(resolver, node, componentNodes, out);
}
}
}
private Page getPageFromNode(ResourceResolver resolver, Node node) throws RepositoryException {
Resource pageResource = resolver.getResource(node.getPath());
PageManager pageManager = resolver.adaptTo(PageManager.class);
return pageManager != null ? pageManager.getContainingPage(pageResource) : null;
}
private void collectValuesInList(ResourceResolver resolver, Node node,
List<String> componentNodes, PrintWriter out) throws RepositoryException {
Page currentPage = getPageFromNode(resolver, node);
String pageName = null != currentPage ? currentPage.getName() : StringUtils.EMPTY;
out.println("<tr><td>" + (componentNodes.size() + 1) + "</td><td>" + pageName + "</td><td> " + node.getName() + "</td><td>" + node.getPath() + "</td></tr>");
componentNodes.add(pageName + " - " + node.getName() + " - " + node.getPath());
}
private static PrintWriter getPrintWriter(SlingHttpServletResponse response, String resourceType, String propertyName, String existNotExist, String propertyValue, String valueSearchType) throws IOException {
response.setContentType(Constants.CT_TEXT_HTML);
PrintWriter out = response.getWriter();
out.println("<html><head><title>Response</title></head><body>");
out.println("<h1>Search Results</h1>");
out.println("<h3> Resource Type : " + resourceType + " </h3> ");
out.println("<h3> Property Name : " + propertyName + " </h3> ");
if (StringUtils.isNotEmpty(existNotExist)) {
if (StringUtils.equalsIgnoreCase(existNotExist, "exist")) {
out.println("<h3> Property Exists OR Not : Exists </h3> ");
} else {
out.println("<h3> Property Exists OR Not : Not Exists </h3> ");
}
}
if (StringUtils.isNotEmpty(propertyValue)) {
out.println("<h3> Property Value : " + propertyValue + " </h3> ");
if (StringUtils.isNotEmpty(valueSearchType)) {
out.println("<h3> Search Type : " + valueSearchType + " </h3> ");
}
}
out.println("</br>");
out.println("<table border='1' style='border-collapse: collapse;'>");
out.println("<tr><th>No.</th><th>Page Name</th><th>Node Name</th><th>Node Path</th></tr>");
return out;
}
}
Request Parameters:
Required Parameters:
// Below are the REQUIRED request parameters: rootPagePath=/content/we-retail resourceType=weretail/components/content/heroimage propertyName=useFullWidth
// Below are all the OPTIONAL request parameters.
// Optional parameter for just to check given property exists or not existNotExist = exist OR existNotExist = notExist
// Optional parameter to pass if value need to get check. propertyValue=Accessibility Text
// Optional parameter only for checking if value contains passed keyword. valueSearchType=contains
OUTPUT:

Multi-field Property Name and Value Search
Below is the code to search property and its value present as part of component’s multi-field.
SAMPLE URL:http://localhost:4502/services/findnodes?rootPagePath=/content/we-retail&resourceType=weretail/components/content/heroimage&propertyName=useFullWidth&existNotExist=notExist&multiFieldNodeName=multifieldname
import com.adobe.aemds.guide.utils.JcrResourceConstants;
import com.adobe.granite.rest.Constants;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@Component(
immediate = true,
service = Servlet.class,
property = {
"sling.servlet.extensions=json",
"sling.servlet.paths=/services/findnodes",
"sling.servlet.methods="+ HttpConstants.METHOD_GET
}
)
public class OpenInNewTabServlet extends SlingAllMethodsServlet {
private final Logger LOGGER = LoggerFactory.getLogger(OpenInNewTabServlet.class);
/*
Property Not Exist
http://localhost:4502/services/findnodes?rootPagePath=/content/we-retail&resourceType=weretail/components/content/heroimage&propertyName=useFullWidth&existNotExist=notExist&multiFieldNodeName=multifieldname
Property Exist
http://localhost:4502/services/findnodes?rootPagePath=/content/we-retail&resourceType=weretail/components/content/heroimage&propertyName=useFullWidth&existNotExist=exist&multiFieldNodeName=multifieldname
Property Exist && Having Value
http://localhost:4502/services/findnodes?rootPagePath=/content/we-retail&resourceType=weretail/components/content/heroimage&propertyName=useFullWidth&propertyValue=true&multiFieldNodeName=multifieldname
Property Exist && Contains Value
http://localhost:4502/services/findnodes?rootPagePath=/content/we-retail&resourceType=weretail/components/content/title&propertyName=jcr:title&propertyValue=Discover&valueSearchType=contains&multiFieldNodeName=multifieldname
*/
// Below are REQUIRED parameters.
private static final String ROOT_PAGE_PATH_PARAM = "rootPagePath";
private static final String RESOURCE_TYPE_PARAM = "resourceType";
private static final String PROPERTY_NAME_PARAM = "propertyName";
// Below are all the OPTIONAL parameters.
// This is an optional parameter to pass if value need to get check.
private static final String PROPERTY_VALUE_PARAM = "propertyValue";
// valueSearchType = contains ; This is an option parameter is required only for checking if value contains.
private static final String PROPERTY_VALUE_SEARCH_TYPE = "valueSearchType";
// NOTE: Pass this request parameter only ina case of multi-field property name and value search
private static final String MULTI_FIELD_NODE_NAME = "multiFieldNodeName";
/*
This is an optional parameter to check property key name exists or not
excludeInclude = exist OR excludeInclude = notExist.
*/
private static final String EXIST_NOT_EXIST = "existNotExist";
@Reference
private PracticePathUtilsService practicePathUtilsService;
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
String rootPagePath = request.getParameter(ROOT_PAGE_PATH_PARAM);
String resourceType = request.getParameter(RESOURCE_TYPE_PARAM);
String propertyName = request.getParameter(PROPERTY_NAME_PARAM);
String propertyValue = request.getParameter(PROPERTY_VALUE_PARAM);
String existNotExist = request.getParameter(EXIST_NOT_EXIST);
String valueSearchType = request.getParameter(PROPERTY_VALUE_SEARCH_TYPE);
String multiFieldNodeName = request.getParameter(MULTI_FIELD_NODE_NAME);
if (rootPagePath == null || rootPagePath.isEmpty()) {
response.sendError(SlingHttpServletResponse.SC_BAD_REQUEST, "Root page path parameter is required.");
return;
}
if (resourceType == null || resourceType.isEmpty()) {
response.sendError(SlingHttpServletResponse.SC_BAD_REQUEST, "Resource type parameter is required.");
return;
}
if (propertyName == null || propertyName.isEmpty()) {
response.sendError(SlingHttpServletResponse.SC_BAD_REQUEST, "Property name parameter is required.");
return;
}
PrintWriter out = getPrintWriter(response, resourceType, propertyName, existNotExist, propertyValue, valueSearchType);
List<String> componentNodes = findComponentsByResourceTypeWithoutProperty(rootPagePath,
resourceType, propertyName, propertyValue, existNotExist, valueSearchType, multiFieldNodeName, out);
out.println("</table>");
out.println("</br>");
out.println("<h3> Total Results : " + componentNodes.size() + " </h3> ");
out.close();
}
private static PrintWriter getPrintWriter(SlingHttpServletResponse response, String resourceType,
String propertyName, String existNotExist, String propertyValue, String valueSearchType) throws IOException {
response.setContentType(Constants.CT_TEXT_HTML);
PrintWriter out = response.getWriter();
out.println("<html><head><title>Response</title></head><body>");
out.println("<h1>Search Results</h1>");
out.println("<h3> Resource Type : " + resourceType + " </h3> ");
out.println("<h3> Property Name : " + propertyName + " </h3> ");
if (StringUtils.isNotEmpty(existNotExist)) {
if (StringUtils.equalsIgnoreCase(existNotExist, "exist")) {
out.println("<h3> Property Exists OR Not : Exists </h3> ");
} else {
out.println("<h3> Property Exists OR Not : Not Exists </h3> ");
}
}
if (StringUtils.isNotEmpty(propertyValue)) {
out.println("<h3> Property Value : " + propertyValue + " </h3> ");
if (StringUtils.isNotEmpty(valueSearchType)) {
out.println("<h3> Search Type : " + valueSearchType + " </h3> ");
}
}
out.println("</br>");
out.println("<table border='1' style='border-collapse: collapse;'>");
out.println("<tr><th>No.</th><th>Page Name</th><th>Node Name</th><th>Node Path</th></tr>");
return out;
}
private List<String> findComponentsByResourceTypeWithoutProperty(String rootPagePath, String resourceType,
String propertyName, String propertyValue, String existNotExist, String valueSearchType, String multiFieldNodeName, PrintWriter out) {
List<String> componentNodes = new ArrayList<>();
ResourceResolver resourceResolver = practicePathUtilsService.getSystemUserResourceResolver();
PageManager pageManager = resourceResolver.adaptTo(PageManager.class);
try {
Page rootPage = pageManager != null ? pageManager.getPage(rootPagePath) : null;
if (rootPage != null) {
Node rootPageNode = resourceResolver.getResource(rootPagePath).adaptTo(Node.class);
if (null != rootPageNode) {
findComponentsRecursively(resourceResolver, rootPageNode, componentNodes,
resourceType, propertyName, propertyValue, existNotExist, valueSearchType,
multiFieldNodeName, out);
}
}
} catch (RepositoryException e) {
LOGGER.error("Error while searching for components: ", e);
}
return componentNodes;
}
private void findComponentsRecursively(ResourceResolver resolver, Node node, List<String> componentNodes, String resourceType,
String propertyName, String propertyValue, String existNotExist, String valueSearchType,
String multiFieldNodeName, PrintWriter out) throws RepositoryException {
if (node.hasProperty(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY) &&
node.getProperty(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY).getString().equals(resourceType)) {
if (node.hasNode(multiFieldNodeName)) {
Node itemRootNode = node.getNode(multiFieldNodeName);
if (itemRootNode.hasNodes()) {
NodeIterator itemNodesItr = itemRootNode.getNodes();
while (itemNodesItr.hasNext()) {
Node itemNode = (Node) itemNodesItr.next();
boolean hasProperty = itemNode.hasProperty(propertyName);
validateConditions(resolver, itemNode, componentNodes, propertyName, propertyValue,
existNotExist, valueSearchType, out, hasProperty);
}
}
}
}
NodeIterator nodeIterator = node.getNodes();
while (nodeIterator.hasNext()) {
Node childNode = nodeIterator.nextNode();
findComponentsRecursively(resolver, childNode, componentNodes, resourceType,
propertyName, propertyValue, existNotExist, valueSearchType, multiFieldNodeName, out);
}
}
private void validateConditions(ResourceResolver resolver, Node node, List<String> componentNodes,
String propertyName, String propertyValue, String existNotExist, String valueSearchType,
PrintWriter out, boolean hasProperty) throws RepositoryException {
if (hasProperty && StringUtils.isNotEmpty(propertyValue)) {
if (StringUtils.equalsIgnoreCase("contains", valueSearchType) &&
StringUtils.contains(node.getProperty(propertyName).getValue().getString(), propertyValue)) {
collectValuesInList(resolver, node, componentNodes, out);
} else if (StringUtils.equalsIgnoreCase(node.getProperty(propertyName).getValue().getString(), propertyValue)) {
collectValuesInList(resolver, node, componentNodes, out);
}
} else if (StringUtils.isNotEmpty(existNotExist) && StringUtils.isEmpty(propertyValue)){
if (existNotExist.equalsIgnoreCase("notExist") && !hasProperty ||
existNotExist.equalsIgnoreCase("exist") && hasProperty) {
collectValuesInList(resolver, node, componentNodes, out);
}
}
}
private Page getPageFromNode(ResourceResolver resolver, Node node) throws RepositoryException {
Resource pageResource = resolver.getResource(node.getPath());
PageManager pageManager = resolver.adaptTo(PageManager.class);
return pageManager != null ? pageManager.getContainingPage(pageResource) : null;
}
private void collectValuesInList(ResourceResolver resolver, Node node,
List<String> componentNodes, PrintWriter out) throws RepositoryException {
Page currentPage = getPageFromNode(resolver, node);
String pageName = null != currentPage ? currentPage.getName() : StringUtils.EMPTY;
out.println("<tr><td>" + (componentNodes.size() + 1) + "</td><td>" + pageName + "</td><td> " + node.getName() + "</td><td>" + node.getPath() + "</td></tr>");
componentNodes.add(pageName + " - " + node.getName() + " - " + node.getPath());
}
}
I hope you found out this article interesting and informative. Please share it with your friends to spread the knowledge.
You can follow me for upcoming blogs follow. Thank you!
메타데이터
- post_id
- 0129e1a112fd
- slug
- aem-script-for-property-and-value-finder-based-on-resource-type-and-root-page-path-0129e1a112fd
- url
- https://medium.com/@toimrank/aem-script-for-property-and-value-finder-based-on-resource-type-and-root-page-path-0129e1a112fd
- canonical_url
- https://medium.com/@toimrank/aem-script-for-property-and-value-finder-based-on-resource-type-and-root-page-path-0129e1a112fd
- author_url
- https://medium.com/@toimrank
- status
- ok
- fetched_at
- 2026-07-19 19:27:23