AEM Sling Servlet


We can register our servlet as an OSGI service in AEM. There are two types of Servlet supported in AEM.

1:- Sling Safe Methods Servlet (GET, HEAD):-  

Servlet implementation that responds to “Safe” HTTP Requests. It is a Read only Implementation & only supports GET &Head method.

java.lang.Object
  extended by javax.servlet.GenericServlet
      extended by org.apache.sling.api.servlets.SlingSafeMethodsServlet


public class DemoServlet extends SlingSafeMethodsServlet

2:- Sling All Methods Servlet (GET, HEAD, POST, PUT, DELETE):- 

Servlet implementation that responds to all HTTP methods. Primarily used for POST Requests.

java.lang.Object
  extended by javax.servlet.GenericServlet
      extended by org.apache.sling.api.servlets.SlingSafeMethodsServlet
          extended by org.apache.sling.api.servlets.SlingAllMethodsServlet

public class DemoServlet extends SlingAllMethodsServlet

How to declare Sling Servlet in AEM:-

There are couple of ways to declare sling servlet in AEM.

1:- Old way of declaring Sling Servlet using  SCR Annotations:-
2:- New way of declaring Sling Servlet using OSGi Annotations

Using Old SCR Annotations:-

There are two ways of doing this, either with a Sling-specific @SlingServlet annotation or using maven-scr-plugin annotations.                                                         

@SlingServlet annotation:-


 @SlingServlet(

resourceTypes="/apps/my-project/my-page",

selectors="mobile",

extensions="html",
methods="GET"
)
public class DemoServlet extends SlingSafeMethodsServlet{
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response){
//write your custom code for servlet here
}
}

@Properties and @Property annotations:-

@Component(metatype=true)
@Service(Servlet.class)
@Properties({
@Property(name="sling.servlet.resourceTypes",value="/apps/my-project/my-page"),
@Property(name="sling.servlet.selectors",value="mobile"),
@Property(name="sling.servlet.extensions",value="html"),
@Property(name="sling.servlet.methods",value="GET")
})
public class MyServlet extends SlingSafeMethodsServlet{

@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response){
// write your custom code here
}
}

Using New OSGi Annotations:-

With the introduction of OSGi annotations @service annotation is removed & now it is part of @component annotation using property service.

@Component(service=Servlet.class,
           property={
                   Constants.SERVICE_DESCRIPTION + "=Simple Demo Servlet",
                   "sling.servlet.methods=" + HttpConstants.METHOD_GET,
                   "sling.servlet.resourceTypes="+ "SaurabhAEM/components/structure/page",
                   "sling.servlet.extensions=" + "txt"
           })
public class SimpleServlet extends SlingSafeMethodsServlet {
    private static final long serialVersionUid = 1L;
    @Override
    protected void doGet(final SlingHttpServletRequest req,
            final SlingHttpServletResponse resp) throws ServletException, IOException {
        final Resource resource = req.getResource();
        resp.setContentType("text/plain");
        resp.getWriter().write("Title = " + resource.adaptTo(ValueMap.class).get("jcr:title"));
    }

}

Registering Sling Servlet using Paths:-

We can also register our servlet using paths. Paths always takes precedence over resourceType.

The property resourceTypes is ignored if the paths property is set.

@SlingServlet annotation:-

@SlingServlet(
paths={"/bin/customservlet/test"}
)
public class DemoServlet extends SlingAllMethodsServlet{
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response){
//Write your custom code here
}
@Override
protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response){
//Write your custom code here
}
}

@Properties and @Property annotations:-

@Component(metatype=true)
@Service(Servlet.class)
@Properties({
@Property(name="sling.servlet.paths",value="/bin/myservlet"),
        @Property(name="sling.servlet.resourceTypes",value="/apps/my-project/my-page"),
@Property(name="sling.servlet.selectors",value="mobile"),
@Property(name="sling.servlet.extensions",value="html"),
@Property(name="sling.servlet.methods",value="GET")
})
public class MyServlet extends SlingSafeMethodsServlet{
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response){
// write your custom code here
}
}

The registration properties sling.servlet.resourceTypes, sling.servlet.selectors and sling.servlet.extensions are ignored because the sling.servlet.paths property is set.

Using OSGi Annotation:-

@Component(
service = Servlet.class, 
property = {
Constants.SERVICE_DESCRIPTION + "=JSON Servlet to read the data from the external webservice",
"sling.servlet.methods=" + HttpConstants.METHOD_GET, "sling.servlet.paths=" + "/bin/readjson" 
})
public class DemoServlet extends SlingSafeMethodsServlet {
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) {
//write your custom code here
}
}

Why resourceType is preferred for writing SlingServlets than path?

Registering a servlet using path is relatively easier than using resourceType because we dont have to take care of extensions,selectors etc. but it is still much more preferential to use resorceType instead of path because of following reasons.
  • While defining a path, you must be specific what all paths are allowed to be used in the ServletResourceOSGi service. If you define something randomly, your servlet might not be fucntional. 
  • Only a limited paths are allowed and the rest are blocked unless you open them up. This is resolved using resourceType.
  • You may have also configure the dispatcher , if you use some random path for your servlet. This might be a potential security threat.
  • You might also have to specify the paths to your consumers for your servlet and any change in that path will not invoke servlet. This might not be the case when you use resourceType.
  • When we use resourceType is then the Sling Engine will take care of permissions for you. Users who do not have permission to access a particular resource will not be able to invoke the servlet.

Comments

Popular posts from this blog

AEM Scheduler

Event Handling in AEM