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
javax.servlet.GenericServlet
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
javax.servlet.GenericServlet
org.apache.sling.api.servlets.SlingSafeMethodsServlet
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:-
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.
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
}
}
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
Post a Comment