How to add a selector to a json servlet?

Avatar

Avatar

jkpanera

Avatar

jkpanera

jkpanera

08-05-2020

Hi guys,

I'm working in AEM 6.3 and writing a servlet that will be producing json data. I'm using the following annotation based configuration:

 

 

@Slf4j
@Component(
        immediate = true,
        service = Servlet.class,
        property = {
                "sling.servlet.methods=get",
                "sling.servlet.resourceTypes=resourceName",
                "sling.servlet.selectors=js",
                "sling.servlet.extensions=json"
        },
        configurationPid = "com.package.ServletName"
)

 

 

I have a resource of sling:resourceType at /content/path/jcr:content and when I place a GET request to http://localhost:4502/content/path/jcr:content.js.json, I expect to see the results of my servlet, but I see this:

 

Invalid recursion selector value 'js'
Cannot serve request to /content/path/jcr:content.js.json on this server

 

If I change my servlet to hardcode the path using sling.servlet.paths, it works, but I don't want to hardcode the path.

 

Any help would be appreciated.I would also appreciate any general explanations as to how AEM prioritizes matching on path, resourceType, selector, and extension when choosing which servlet to delegate to.

 

Thanks much!!!

 

 

Accepted Solutions (1)

Accepted Solutions (1)

Avatar

Avatar

Ankur_Khare

MVP

Avatar

Ankur_Khare

MVP

Ankur_Khare
MVP

08-05-2020

Hi,

First of all you are accesing the page incorrectly-

 

Please remove jcr:content.

 

And access this link to read about selectors usage.

http://www.aemcq5tutorials.com/tutorials/sling-servlet-in-aem/

 

 

Answers (1)

Answers (1)

Avatar

Avatar

Theo_Pendle

MVP

Avatar

Theo_Pendle

MVP

Theo_Pendle
MVP

09-05-2020

Hello @jkpanera,

I'm sorry but I find this line confusing: "I have a resource of sling:resourceType at /content/path/jcr:content". sling:resourceType is a property, its the value of that property which will dictate which servlet is called, so what sling:resourceType that you want to render?

Since the resource in question has a jcr:content child, I'm assuming its a page? In that case, here is some working code:

@Component(
        immediate = true,
        service = Servlet.class,
        property = {
                "sling.servlet.methods=" + HttpConstants.METHOD_GET,
                "sling.servlet.resourceTypes=" + "demo/components/structure/page",
                "sling.servlet.selectors=js",
                "sling.servlet.extensions=" + "json"
        })
@ServiceDescription("JS JSON Servlet")
public class SimpleServlet extends SlingSafeMethodsServlet {

    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(final SlingHttpServletRequest req,
                         final SlingHttpServletResponse resp) throws IOException {
        resp.setContentType("text/plain");
        resp.getWriter().write("Request processed by " + this.getClass().getName());
    }
}

Then you call it like so:

http://localhost:4502/content/demo/us/test/jcr:content.js.json

Here is a screenshot:

Selection_143.png

In order to call a servlet which is mapped to a resource type, you must provide a path to the JCR resource which a sling:resourceType property. For example:

  • If the resource is a component at /content/site/page/root/component, then the request should be to /content/site/page/root/component.js.json because that's the node which has a sling:resourceType property.
  • If the resource is a page at /content/site/page, then the request should be to /content/site/page/jcr:content.js.json because the jcr:content child node is the one with the sling:resourceType property

Hope this helps 🙂