Expand my Community achievements bar.

SOLVED

How to how to get the page of child pages in aem java using servlet and base path

Avatar

Level 3

I want to create a servlet which will be using a base path for example : /content/abc/xyz/qwe

I need to access specific child properties of the given base path and convert it into JSON format using java servlet.

Please help me with the process and explaining the steps involved like how will my java servlet get data from /content/abc/xyz/qwe i.e what will be code to use this path and how to access specific properties and converting into JSON.

1 Accepted Solution

Avatar

Correct answer by
Employee Advisor

Hi @ShagunMalik!

I assume that you don't want to get a JSON response of only one path but different areas of your content tree.

While there are different ways to register a servlet (see [1]), the recommended way - that should perfectly match your use case - is to bind it to a resource type and not to a path as mentioned under [2]:

"Given these drawbacks it is strongly recommended to bind servlets to resource types rather than paths."

 

So my recommendation is to create a servlet that binds to your required resource type(s) and to the JSON extension. If you need to be more specific, you can also add a custom selector for differentiation. Your servlet can then access the requested resource, read the required properties from it and return them in the form that you want.

 

Please also note that there already is an OOTB JSON renderer.

So if you need to access certain properties of your example path /content/abc/xyz/qwe you can just request the following:

  • /content/abc/xyz/qwe.1.json

This will return all properties of the "qwe" node in JSON format. If the consumer for that information is able to filter on the required properties and ignore the rest, there is no need for custom implementation on the AEM side. If you need a specific structure of your JSON response the above mentioned approach with a custom servlet is the way to go.

 

Please find an example implementation based on the AEM Maven Archetype [3] below:

 

package com.mysite.core.servlets;

import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.servlets.annotations.SlingServletResourceTypes;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.propertytypes.ServiceDescription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.day.cq.commons.jcr.JcrConstants;

@Component(service = { Servlet.class })
@SlingServletResourceTypes(resourceTypes = "mysite/components/page", methods = HttpConstants.METHOD_GET, extensions = "json")
@ServiceDescription("Simple JSON Servlet")
public class JsonServlet extends SlingSafeMethodsServlet {
	private final static Logger LOG = LoggerFactory.getLogger(JsonServlet.class);

	@Activate
	protected void activate() {
		LOG.debug("{} activated.", getClass());
	}

	@Override
	protected void doGet(final SlingHttpServletRequest request, final SlingHttpServletResponse response)
			throws ServletException, IOException {
		// Getting the current resource
		final Resource resource = request.getResource();
		// Getting a property
		String titleProperty = (String) resource.getValueMap().get(JcrConstants.JCR_TITLE);
		// TODO compose your JSON response and write it to the response
		response.setContentType("text/plain");
		response.getWriter().write("Title = " + titleProperty);
	}
}

 

 

Hope that helps!

 

[1] https://sling.apache.org/documentation/the-sling-engine/servlets.html#servlet-registration-1

[2] https://sling.apache.org/documentation/the-sling-engine/servlets.html#caveats-when-binding-servlets-...

[3] https://github.com/adobe/aem-project-archetype/blob/develop/src/main/archetype/core/src/main/java/co...

View solution in original post

2 Replies

Avatar

Community Advisor

Hi @ShagunMalik 

 

You can use something like below:

 

@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
log.info("***** :: doGet :: Start :: *****");
String requestPath = "/content/we-retail/language-masters/en/experience"; // Here you will read the page path form your input

ResourceResolver resourceResolver = request.getResourceResolver();
Resource requestResource = resourceResolver.getResource(requestPath);
Iterator<Resource> resourceIterator = requestResource.listChildren();

List<PageVO> pageVOList = new ArrayList<>();
resourceIterator.forEachRemaining(resource -> {
PageManager pageManager = resourceResolver.adaptTo(PageManager.class);
if (pageManager != null) {
Page page = pageManager.getContainingPage(resource);
if (page != null) {
PageVO pageVO = new PageVO();
final Resource contentResource = page.getContentResource();
final ValueMap pageValueMap = contentResource.getValueMap();
final String pageTitle = pageValueMap.get(NameConstants.PN_PAGE_TITLE) != null ? pageValueMap.get(NameConstants.PN_PAGE_TITLE).toString() : pageValueMap.get(NameConstants.PN_TITLE).toString();
final String resourceType = pageValueMap.get(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY) != null ? pageValueMap.get(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY).toString() : StringUtils.EMPTY;
pageVO.setPageTile(pageTitle);
pageVO.setResourceType(resourceType);
pageVOList.add(pageVO);
}
}
});

Gson gson = new Gson();
String toJson = gson.toJson(pageVOList);

response.setContentType(ContentType.APPLICATION_JSON.toString());
response.getWriter().write(toJson);

 

PageVO.java -> For now I have added only 2 property. You can include whatever property you want.

public class PageVO {
private String pageTile;
private String resourceType;

public String getPageTile() {
return pageTile;
}

public void setPageTile(String pageTile) {
this.pageTile = pageTile;
}

public String getResourceType() {
return resourceType;
}

public void setResourceType(String resourceType) {
this.resourceType = resourceType;
}
}

 

Response:

[
{
pageTile:"Experience",
resourceType:"weretail/components/structure/page"
},
{
pageTile:"Arctic Surfing In Lofoten",
resourceType:"weretail/components/structure/page"
},
{
pageTile:"48 hours of Wilderness",
resourceType:"weretail/components/structure/page"
},
{
pageTile:"Fly-fishing the Amazon",
resourceType:"weretail/components/structure/page"
},
{
pageTile:"Skitouring",
resourceType:"weretail/components/structure/page"
},
{
pageTile:"Steelhead and Spines in Alaska",
resourceType:"weretail/components/structure/page"
},
{
pageTile:"Camping in Western Australia",
resourceType:"weretail/components/structure/page"
}
]

Avatar

Correct answer by
Employee Advisor

Hi @ShagunMalik!

I assume that you don't want to get a JSON response of only one path but different areas of your content tree.

While there are different ways to register a servlet (see [1]), the recommended way - that should perfectly match your use case - is to bind it to a resource type and not to a path as mentioned under [2]:

"Given these drawbacks it is strongly recommended to bind servlets to resource types rather than paths."

 

So my recommendation is to create a servlet that binds to your required resource type(s) and to the JSON extension. If you need to be more specific, you can also add a custom selector for differentiation. Your servlet can then access the requested resource, read the required properties from it and return them in the form that you want.

 

Please also note that there already is an OOTB JSON renderer.

So if you need to access certain properties of your example path /content/abc/xyz/qwe you can just request the following:

  • /content/abc/xyz/qwe.1.json

This will return all properties of the "qwe" node in JSON format. If the consumer for that information is able to filter on the required properties and ignore the rest, there is no need for custom implementation on the AEM side. If you need a specific structure of your JSON response the above mentioned approach with a custom servlet is the way to go.

 

Please find an example implementation based on the AEM Maven Archetype [3] below:

 

package com.mysite.core.servlets;

import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.servlets.annotations.SlingServletResourceTypes;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.propertytypes.ServiceDescription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.day.cq.commons.jcr.JcrConstants;

@Component(service = { Servlet.class })
@SlingServletResourceTypes(resourceTypes = "mysite/components/page", methods = HttpConstants.METHOD_GET, extensions = "json")
@ServiceDescription("Simple JSON Servlet")
public class JsonServlet extends SlingSafeMethodsServlet {
	private final static Logger LOG = LoggerFactory.getLogger(JsonServlet.class);

	@Activate
	protected void activate() {
		LOG.debug("{} activated.", getClass());
	}

	@Override
	protected void doGet(final SlingHttpServletRequest request, final SlingHttpServletResponse response)
			throws ServletException, IOException {
		// Getting the current resource
		final Resource resource = request.getResource();
		// Getting a property
		String titleProperty = (String) resource.getValueMap().get(JcrConstants.JCR_TITLE);
		// TODO compose your JSON response and write it to the response
		response.setContentType("text/plain");
		response.getWriter().write("Title = " + titleProperty);
	}
}

 

 

Hope that helps!

 

[1] https://sling.apache.org/documentation/the-sling-engine/servlets.html#servlet-registration-1

[2] https://sling.apache.org/documentation/the-sling-engine/servlets.html#caveats-when-binding-servlets-...

[3] https://github.com/adobe/aem-project-archetype/blob/develop/src/main/archetype/core/src/main/java/co...