April 10, 2020
Estimated Post Reading Time ~

Overriding Out Of The Box (OOTB) servlet

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

If the behavior 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 that implement javax.servlet.Servlet interface.

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 behavior. 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://localhost:4502/editor.html/content/we-retail/language-masters/en/men.feedentry.rss.xml. With the help of this request, we will proceed further

Steps
Step #1
Navigate to http://localhost:4502/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://localhost:4502/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://localhost:4502/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. The 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 that 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 = 362516459145838595 L;

 @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 the Recent requests console as well.

Similarly, you can override any OOTB servlet in AEM.


By aem4beginner

No comments:

Post a Comment

If you have any doubts or questions, please let us know.