Sling Servlet in AEM

Writing a Sling Servlet in AEM is one of the basic building block to start working with AEM. Sling servlet are basically used when front end developers need to make ajax call and want to get response in form of json. There are two ways in which a developer can register a servlet using path or selector.

In this tutorial i will tell you which approach is better and what are the best practices to create sling servlet in AEM.

After completing this tutorial , you will have a clear understanding about:-

Pre-requisite:-

You have setup you eclipse and code base. If not go through this tutorial to Set up AEM Project in Eclipse.

Write Sling Servlet using path in AEM

Lets write a sling servlet that returns json data by registering using path. When you create a project using AEM plugin, it will create a sample servlet file for you under core–> servlet

  • Open SimpleServlet.java file and paste below code, i will explain the code line by line.
/*
 *  Copyright 2015 Adobe Systems Incorporated
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.training.aemcq5tutorials.core.servlets;

import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.sling.SlingServlet;
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.SlingAllMethodsServlet;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;

import javax.jcr.Repository;
import javax.servlet.ServletException;
import java.io.IOException;

/**
 * Servlet that writes some sample content into the response. It is mounted for
 * all resources of a specific Sling resource type. The
 * {@link SlingSafeMethodsServlet} shall be used for HTTP methods that are
 * idempotent. For write operations use the {@link SlingAllMethodsServlet}.
 */
@SuppressWarnings("serial")
@SlingServlet(paths = "/bin/custom/path")
public class SimpleServlet extends SlingSafeMethodsServlet {
	@Reference
	private Repository repository;
    @Override
    protected void doGet(final SlingHttpServletRequest req,
            final SlingHttpServletResponse resp) throws ServletException, IOException {
    	resp.setContentType("application/json");
    	String keys[] = repository.getDescriptorKeys();
    	JSONObject jsonobject = new JSONObject();
    	for(int i=0;i<keys.length;i++){
    		try {
				jsonobject.put(keys[i], repository.getDescriptor(keys[i]));
			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    	resp.getWriter().println(jsonobject.toString());

    }
}

  • Here i am registering our simple servlet at path /bin/custom/path.
  • Then i am setting the content type as json.
  • Finally i am returning the response.

Ajax call that you can use to call this servlet using Rest API:-

		$.ajax({
			type : "GET",
			url : '/bin/custom/path',
			/*data : {
				pass your request parameter here, currently we are not passing any data
			},*/
			success : function(data, textStatus, jqXHR) {
				//write your logic that you need to perform on sucess
                        },
			error : function(XMLHttpRequest, textStatus, errorThrown) {
				//write your logic that you need to perform on error
			}
		});

Now go to your browser type http://localhost:4502/bin/custom/path and you can see you json, This url can be used by front end developers to get the json response and process it accordingly.

sling servlet register path

Write Sling Servlet using a resource type and selector

Lets write a sling servlet that returns json data by registering using resource type and selector.

  • Again Open SimpleServlet.java file and paste below code, i will explain the code line by line.
/*
 *  Copyright 2015 Adobe Systems Incorporated
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.training.aemcq5tutorials.core.servlets;

import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.sling.SlingServlet;
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.SlingAllMethodsServlet;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;

import javax.jcr.Repository;
import javax.servlet.ServletException;
import java.io.IOException;

/**
 * Servlet that writes some sample content into the response. It is mounted for
 * all resources of a specific Sling resource type. The
 * {@link SlingSafeMethodsServlet} shall be used for HTTP methods that are
 * idempotent. For write operations use the {@link SlingAllMethodsServlet}.
 */
@SuppressWarnings("serial")
@SlingServlet(resourceTypes = "geometrixx/components/homepage",
selectors = "data",
extensions = "html",
methods = "GET",
metatype =true)
public class SimpleServlet extends SlingSafeMethodsServlet {
	@Reference
	private Repository repository;
    @Override
    protected void doGet(final SlingHttpServletRequest req,
            final SlingHttpServletResponse resp) throws ServletException, IOException {
    	resp.setContentType("application/json");
    	String keys[] = repository.getDescriptorKeys();
    	JSONObject jsonobject = new JSONObject();
    	for(int i=0;i<keys.length;i++){
    		try {
				jsonobject.put(keys[i], repository.getDescriptor(keys[i]));
			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    	resp.getWriter().println(jsonobject.toString());

    }
}

  • Here i am registering our simple servlet at resourceType geometrixx/components/homepage and selector data.

resourcetype sling servlet aem

Ajax call that you can use to call this servlet using Rest API:-

		$.ajax({
			type : "GET",
			url : '/content/geometrixx/en.data.html,
			/*data : {
				pass your request parameter here, currently we are not passing any data
			},*/
			success : function(data, textStatus, jqXHR) {
				//write your logic that you need to perform on sucess
                        },
			error : function(XMLHttpRequest, textStatus, errorThrown) {
				//write your logic that you need to perform on error
			}
		});

Now go to your browser type http://localhost:4502/content/geometrixx/en.data.html and you can see you json, This url can be used by front end developers to get the json response and process it accordingly.

sling servlet register resourceType and selector

Advantages of registering servlet using selector over path:-


Adobe recommends using resourceType instead of using path because of following reasons:-

  • When we register a servlet using path , we must be specific what all paths are allowed as If we define something randomly, our servlet might not be function properly. Only a limited set of paths are allowed and the rest are blocked. We can add more path using Apache Sling Servlet / Script Resolver and Error Handler. Allowing more paths to execute servlet make you application vulnerable. That’s why you should not open more doors for servlets to run until and unless it is required.

Apache sling servlet resolver error handler

  • You might also need to tell specific paths to your consumers , who are consuming servlet response using ajax and any change in that path could have a serious affect. This might not be the case when you use resourceType.
  • Sling Engine will take care of permissions if you register servlet using Resource Type. Users who cannot access a particular resource will not be able to invoke the servlet.

Sling Servlet Best Practices:-

DO’S
@SlingServlet(
resourceTypes = "sling/servlet/default",
selectors = "selector",
extensions = "tab",
methods = HttpConstants.METHOD_GET
)
DONT
@Component
@Service(value = javax.servlet.Servlet.class)
@Properties({ @Property(name = "sling.servlet.resourceTypes", value = { "sling/servlet/default" }),
@Property(name = "sling.servlet.selectors", value = { "selector" }),
@Property(name = "sling.servlet.extensions", value = { "tab" }),
@Property(name = "sling.servlet.methods", value = { HttpConstants.METHOD_GET }) })
DO’S
@SlingServlet(
resourceTypes = "sling/servlet/default", selectors = "selector",
extensions = "tab", methods = HttpConstants.METHOD_GET
)
@Properties({
@Property(name = Constants.SERVICE_VENDOR, value = "Cognifide"),
@Property(name = Constants.SERVICE_DESCRIPTION, value = "Some description")
})
DONT
@SlingServlet(methods = "GET")
@Properties({
@Property(name = Constants.SERVICE_VENDOR, value = "Cognifide"),
@Property(name = Constants.SERVICE_DESCRIPTION, value = "Some description"),
@Property(name = "sling.servlet.selectors", value = "selector"),
@Property(name = "sling.servlet.extensions", value = "tab"),
@Property(name = "sling.servlet.resourceTypes", value = { "sling/servlet/default" })
})
DO’S
@SlingServlet(
resourceTypes = "sling/servlet/default", selectors = "selector",
extensions = "tab", methods = HttpConstants.METHOD_GET
)
DONT
@Service
@Component
@SlingServlet(
resourceTypes = "sling/servlet/default", selectors = "selector",
extensions = "tab", methods = HttpConstants.METHOD_GET
)

That’s all about working with Sling Servlet in AEM.

Spread the love

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.