Skip to main content

Overriding Out Of The Box (OOTB) servlet

Sometimes it happens that we want to override a default behaviour in AEM.

If the behaviour that we want to override is a component in crx/de, then we can easily use Overlaying/Overriding concepts in Sling.

But if we wish to override an OOTB sling servlet, then things get tricky. This blog post tackles this situation. It discusses step by step process of overriding an OOTB sling servlet.

Concept

We know that Servlets in AEM are basically OSGi services which implement javax.servlet.Servlet interface. For more information about servlets in AEM, see this post.

A service listener (org.apache.sling.servlets.resolver.internal.SlingServletResolver) listens for the OSGi services implementing javax.servlet.Servlet interface and registers its reference. 

When a request hits the server, this SlingServletResolver kicks in to executes its sling script resolution procedure to choose the right servlet to respond to the request.

Problem Statement

There is one servlet OOTB that handles the RSS/Atom feed requests in AEM. We need to override this behaviour. As of now, we do not have any idea about how to override this functionality. We only have our request now.

The request in this use case is - http://<host>:<port>/<content-path>.feedentry.rss.xml. With the help of this request, we will proceed further

Steps

Step #1

Navigate to http://<host>:<port>/system/console/requests and search for your request
Recent requests in AEM

Step #2 

Click on the request to see the RequestProgressTrackerInfo. There you will find the servlet that is handling this request.
Request progress tracker
Here you can see that this request is being handled by com.day.cq.commons.servlets.FeedRendererServlet

Step #3

Now, we have to find the parameters on which this servlet has been registered. To do this, navigate to  http://<host>:<port>/system/console/depfinder and search for your class. Then you will find the artifact id and group id of the OSGi bundle in which this OOTB servlet is present.

Depfinder

Step #4

Now to know about the properties by which this servlet is registered, navigate to http://<host>:<port>/system/console/bundles and search for the artifact id.
Felix Console

Step #5

Open the bundle details by clicking on it and search for your servlet. Since every servlet is an OSGi service, our servlet must have a service id corresponding to it.
Servlet details

Step #6

Click on the service id to open the servlet details i.e. properties by which it is registered
Services

Note: Sometimes it may happen that the servlet which we are trying to override is registered with a service ranking, then we need to make sure our custom servlet has service ranking greater than that. This can be done by using the property service.ranking. Default service ranking is 0 and if some servlet has ranking other than 0, it will be shown in the above console too.

Step #7

Since we have all the properties with us, we can now start creating a custom servlet which overrides the OOTB servlet.
Below is the sample code that I have created to override this servlet.
import java.io.IOException;

import javax.servlet.Servlet;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Anirudh Sharma
 *
 */
@Component(immediate = true, service = Servlet.class, 
  property = {
    "sling.servlet.methods=" + HttpConstants.METHOD_GET,
    "sling.servlet.methods=" + HttpConstants.METHOD_POST,
    "sling.servlet.resourceTypes=" + "sling/servlet/default",
    "sling.servlet.selectors="+"feed",
    "sling.servlet.selectors="+"feedentry",
    "sling.servlet.extensions="+"xml", "service.ranking=" + 101})
public class CustomFeedRendererServlet extends SlingAllMethodsServlet {
 
 private final Logger log = LoggerFactory.getLogger(this.getClass());

 // Generated serialVersionUID
 private static final long serialVersionUID = 362516459145838595L;
 
 @Override
 protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) {
  try {
   log.info("Inside GET method");
   response.getWriter().println("Custom servlet invoked from GET");
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
 
 @Override
 protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) {
  try {
   log.info("Inside POST method");
   response.getWriter().println("Custom servlet invoked from POST");
  } catch (IOException e) {
   e.printStackTrace();
  }
 }

}

Step #8 

Build and deploy the code. Hit your request again and this time you will see your custom servlet getting executed. You can verify this at Recent requests console as well.

Similarly, you can override any OOTB servlet in AEM.

Conclusion

Congratulations! 🙋 you have successfully overridden OOTB servlet in AEM.

I would love to hear your thoughts on this post and would like to have suggestions from you to make this post better. 

Feel free to befriend me on Facebook, Twitter or Linked In or say Hi by email.


Comments

Post a Comment

Popular posts from this blog

Day 00: AEM Developer Series

Hello everyone! Welcome to this AEM development series. We can all see that the revolution of Digital Marketing today. Companies are dying to be a part of it and they have made this a war for the Digital Marketing tools.

Adobe was way ahead in this war and have gained a lot of market capture. They are leaders in the Digital Marketing platforms since the 2014-15. One of the flagship product in its Digital Marketing suite is Adobe Experience Manager (AEM).

Since AEM is in huge demand, the people who know how to develop on AEM are also in huge demand. But developing on AEM is not easy as it is made up of various open-source technologies such as Apache Felix (OSGi), Apache Sling, Apache Oak and Adobe's own technologies like Granite, HTL etc. Learning all these technologies in conjunction can sometimes become confusing and frustrating 😫.

When I first started learning AEM in 2016, I was dumbfounded to see there is so much going on under the hood. I then spent months to gather all the …

Day 01: Introduction to AEM

Day 04: Developing first OSGi bundle