AEM - Manipulate Nodes Using A Servlet (Java)
This post details how to manipulate nodes in AEM using a Java servlet.
Often times we come across a situation where bunch of nodes need to be added to a certain “component” to every occurrence of that component in a specific folder. Sounds mouthful :-) We have several options for this.. write a javascript, run some groovy scripts and through a servlet.
tl;dr
This post details how to manipulate nodes in AEM using a Java servlet. Code
The Servlet
A servlet that has some path to be accessible. Remember this (can be) a one-time used code.
The sample I used the path as “/bin/sampleapp/manipulatecontent”. You may use any.
The input to the servlet is the path. So the above can be called as “/bin/sampleapp/manipulatecontent?searchpath=/content/sampleapp”
1: Search query
In this example I am looking for all occurrences of the component “bg” and then adding extra nodes to that component. “SearchPath” would be the input (or if you know the path, you may hard code it).
Map<String, String> queryParameterMap = new HashMap<>();
queryParameterMap.put("path", searchPath);
queryParameterMap.put("type", JcrConstants.NT_UNSTRUCTURED);
queryParameterMap.put("1_property", "sling:resourceType");
queryParameterMap.put("1_property.value", "sampleapp/components/content/bg");2: Find the component’s node
Find all the paths that have the component.
List<Hit> hits = searchResult.getHits();
if (CollectionUtils.isNotEmpty(hits)) {
for (Hit hit : hits) {
hitPath = hit.getPath();
pageResource = resourceResolver.getResource(hitPath);
nodeToUpdate = resourceResolver.getResource(hitPath).adaptTo(Node.class);
...3: Add the extra nodes
Add the properties you’d like to add to the component’s node.
Note: If you look at the example, I added some extra checks before adding nodes.
nodeToUpdate.setProperty("backgroundSpacing", "theme-3");
session.save();That’s it!
Note: This is by no means THE solution. This worked for us. I would love to see ore such examples and code more simpler or efficient.
Code snippet
| package com.web.core.servlets; | |
| import com.day.cq.commons.jcr.JcrConstants; | |
| 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; | |
| import org.apache.commons.collections.CollectionUtils; | |
| 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.resource.ValueMap; | |
| import org.apache.sling.api.servlets.HttpConstants; | |
| import org.apache.sling.api.servlets.SlingAllMethodsServlet; | |
| import org.osgi.framework.Constants; | |
| import org.osgi.service.component.annotations.Component; | |
| import org.slf4j.Logger; | |
| import org.slf4j.LoggerFactory; | |
| import javax.jcr.Node; | |
| import javax.jcr.Session; | |
| import javax.servlet.Servlet; | |
| import javax.servlet.ServletException; | |
| import java.io.IOException; | |
| import java.io.PrintWriter; | |
| import java.util.HashMap; | |
| import java.util.List; | |
| import java.util.Map; | |
| import org.json.JSONArray; | |
| import org.json.JSONObject; | |
| @Component(service = Servlet.class, name = "com.web.core.servlets.ManipulateContentServlet", | |
| immediate = true, | |
| property = { | |
| Constants.SERVICE_DESCRIPTION | |
| + "=Servlet that manipulates content", | |
| "sling.servlet.methods=" + HttpConstants.METHOD_GET, | |
| "sling.servlet.paths=" + "/bin/sampleapp/manipulatecontent"}) | |
| public class ManipulateContentServlet extends SlingAllMethodsServlet { | |
| private static final Logger LOGGER = LoggerFactory.getLogger(ManipulateContentServlet.class); | |
| protected void doGet(final SlingHttpServletRequest request, | |
| final SlingHttpServletResponse response) | |
| throws ServletException, IOException { | |
| LOGGER.info("ManipulateContentServlet() {}"); | |
| response.setContentType("application/json"); | |
| response.setCharacterEncoding("UTF-8"); | |
| try { | |
| String searchPath = request.getParameter("searchpath"); | |
| if (searchPath == null) { | |
| response.getWriter().print("Search PATH missing in query parameter!"); | |
| return; | |
| } | |
| ResourceResolver resourceResolver = request.getResourceResolver(); | |
| if (resourceResolver == null) return; | |
| Session session = resourceResolver.adaptTo(Session.class); | |
| QueryBuilder queryBuilder = resourceResolver.adaptTo(QueryBuilder.class); | |
| // | |
| Map<String, String> queryParameterMap = new HashMap<>(); | |
| queryParameterMap.put("path", searchPath); | |
| queryParameterMap.put("type", JcrConstants.NT_UNSTRUCTURED); | |
| queryParameterMap.put("1_property", "sling:resourceType"); | |
| queryParameterMap.put("1_property.value", "sampleapp/components/content/background"); | |
| Query query = queryBuilder.createQuery(PredicateGroup.create(queryParameterMap), session); | |
| if (query != null) { | |
| SearchResult searchResult = query.getResult(); | |
| if (searchResult != null) { | |
| //LOGGER.info("Query : '{}'", searchResult.getQueryStatement()); | |
| String hitPath; | |
| Resource pageResource; | |
| Node nodeToUpdate; | |
| Boolean found = false; | |
| List<Hit> hits = searchResult.getHits(); | |
| if (CollectionUtils.isNotEmpty(hits)) { | |
| for (Hit hit : hits) { | |
| hitPath = hit.getPath(); | |
| pageResource = resourceResolver.getResource(hitPath); | |
| //LOGGER.info("\npageResource::" + pageResource); | |
| nodeToUpdate = resourceResolver.getResource(hitPath).adaptTo(Node.class); | |
| LOGGER.info("\n------ nodeToUpdate::" + nodeToUpdate.toString()); | |
| for (Map.Entry entry : pageResource.getValueMap().entrySet()) { | |
| if (entry.getKey().equals("backgroundSpacing")) { | |
| found = true; | |
| LOGGER.info("\n------ FOUND"); | |
| } | |
| } | |
| if (!found) { | |
| LOGGER.info("\n------ Updating Path:" + hitPath); | |
| /* here you can add / remove any node property. An exampl below*/ | |
| nodeToUpdate.setProperty("backgroundSpacing", "theme-3"); | |
| session.save(); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| LOGGER.info("\n----- COMPLETED"); | |
| response.getWriter().print("Completed!"); | |
| } catch(Exception ex){ | |
| LOGGER.info("Exception", ex); | |
| } | |
| } | |
| } |
Resources
Complete servlet at
Using Groovy scripts - <TBD>
Using Javascript - <TBD>

