There are several tutorials on creating sling servlets. All of them use paths, e.g.
"sling.servlet.paths=" + "/bin/readjson"
(and this can be hit on www.mysite.com/bin/readjason )
All of them say its better to use resource types, e.g.
"sling.servlet.resourceTypes="+ "noidea",
but how do I hit the servlet? www.mysite.com/noidea doesnt work.
What needs to be setup, and how, to use a resource type (and setup in source code - not in the local running AEM instance, where it cannot be distributed to other instances)? Presumably there is some configuration somewhere which ties the resource type to a URL.
If you have an API with say 20 endpoints, so you have say 20 URLs, its easy to give each one its own path in the servlet directly, e.g. /bin/api/login or /bin/api/register. This concept doesn't really map onto resource type, as you would have to manually create a resource type for each endpoint, and there may be 100 endpoints in some APIs. We assume selector could be used, or may be postfix, but the documentation implies sector should only be used to define how the result should be formatted, not what the URL endpoint is?
Solved! Go to Solution.
Hi @TB3dock
When we register a servlet using path, we must be specify what all paths are allowed as if we define something randomly, our servlet might not be functioning 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 servlets makes our application vulnerable. That’s why we should not open more doors for servlets to run until and unless it is required and cannot be achieved using resource type.
We 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. Path-bound servlets cannot be access controlled using the default JCR repository ACLs.
@Component(service = Servlet.class, property = {"process.label=Some Servlet",
Constants.SERVICE_DESCRIPTION + "=This Servlet is responsible for Something."})
@SlingServletResourceTypes(resourceTypes = ServiceConstants.YOUR_SERVLET_RESOURCE_TYPE,
methods = HttpConstants.METHOD_POST,
extensions = "json",
selectors = "something")
public class SomeServlet extends SlingAllMethodsServlet {
// Code
}
Links to refer:
Very detailed article:
http://www.sgaemsolutions.com/2017/12/apache-sling-servlets-and-scripts.html
Thanks!
Hi @TB3dock
When we register a servlet using path, we must be specify what all paths are allowed as if we define something randomly, our servlet might not be functioning 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 servlets makes our application vulnerable. That’s why we should not open more doors for servlets to run until and unless it is required and cannot be achieved using resource type.
We 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. Path-bound servlets cannot be access controlled using the default JCR repository ACLs.
@Component(service = Servlet.class, property = {"process.label=Some Servlet",
Constants.SERVICE_DESCRIPTION + "=This Servlet is responsible for Something."})
@SlingServletResourceTypes(resourceTypes = ServiceConstants.YOUR_SERVLET_RESOURCE_TYPE,
methods = HttpConstants.METHOD_POST,
extensions = "json",
selectors = "something")
public class SomeServlet extends SlingAllMethodsServlet {
// Code
}
Links to refer:
Very detailed article:
http://www.sgaemsolutions.com/2017/12/apache-sling-servlets-and-scripts.html
Thanks!
Thanks for the reply; Everything you have said I already know - writing the servlet to use a resource type is easy, but there are no tutorials or guides which tell you how to do the magic step of configuring the resource type and mapping it to a path. This is the missing from every servlet tutorial unfortunately, and means we have to use the path option. In your example you have "
ServiceConstants.YOUR_SERVLET_RESOURCE_TYPE
Where does this come from? where is is YOUR_SERVLET_RESOURCE_TYPE defined and linked to a path?
Hi @TB3dock
The below screenshot gives the complete details how the request is mapped to a servlet which is registered using resource type and the resource resolution happnes.
If you go through the link below you will be able to get the complete idea about the resource based servlet.
http://www.sgaemsolutions.com/2017/12/apache-sling-servlets-and-scripts.html
Now coming to
ServiceConstants.YOUR_SERVLET_RESOURCE_TYPE
it's just a constant that I have defined in my code. You can either define in your code and use it else you can directly use like below:
@Component(service = Servlet.class, property = {"process.label=Some Servlet",
Constants.SERVICE_DESCRIPTION + "=This Servlet is responsible for Something."})
@SlingServletResourceTypes(resourceTypes = "/project/component/someresource",
methods = HttpConstants.METHOD_POST,
extensions = "json",
selectors = "something")
public class SomeServlet extends SlingAllMethodsServlet {
// Code
}
Views
Replies
Total Likes
Thanks for the comment. We know the source code we need to put in the servlet. We dont know what files and file content to put into our git to make the resource type magically appear, and how to link a resource type to the URL to it the servlet.. You have a screen shot of something which appears to have been setup, but how? how to you create or configure a resource type? This is the missing piece from all the turorials and information pages. What do we need to add to our git to make a resource type magically appear when we deploy the code to one of our envs using mvn clean install -PautoInsallSinglePackage?
Looking at the screen shot you kindly provided, it shows a resource type of "community-componets/component/componet-page" however, the URL which appears to be being used to access the content is "/content/community-components/en/tagcloud/jcr:content/sample. There seems to be no correlation between the URL and the resource type, and we dont know how to configure the resource type.
Views
Replies
Total Likes
Hi @TB3dock
You can create separate nodes (nt:unstructured) which will be called as resource and for each of the resource you can define the sling:resourceType property which will hold the value which will be used in the servlet.
Let's say we are creating these nodes under /content/wknd as /services/api1 and api2 as below:
Please consider only the highlighted part below which will be used to generate the node via code and deployed via git. you need to adjust the filter.xml.
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="cq:Page">
<jcr:content
cq:allowedTemplates="[/conf/wknd/settings/wcm/templates/landing-page-template,/conf/wknd/settings/wcm/templates/article-page-template,/conf/wknd/settings/wcm/templates/content-page-template,/conf/wknd/settings/wcm/templates/adventure-page-template]"
cq:conf="/conf/wknd"
cq:lastModified="{Date}2020-01-06T15:53:34.296-08:00"
cq:lastModifiedBy="admin"
jcr:primaryType="cq:PageContent"
jcr:title="WKND Site"
sling:configRef="/conf/wknd"
sling:redirect="true"
sling:redirectStatus="{Long}302"
sling:resourceType="foundation/components/redirect"
redirectTarget="/content/wknd/en">
<image jcr:primaryType="nt:unstructured">
<file/>
</image>
</jcr:content>
<services
jcr:primaryType="nt:unstructured">
<api1
jcr:primaryType="nt:unstructured"
sling:resourceType="api/service1">
</api1>
<api2
jcr:primaryType="nt:unstructured"
sling:resourceType="api/service1">
</api2>
</services>
</jcr:root>
Now each of the node has a sling:resourceType property which will be used in the servlet and when the resource path will be invoked, it will internally invoke the servlet whose resource type will match.
@Component(service = Servlet.class, property = {"process.label=Some Servlet",
Constants.SERVICE_DESCRIPTION + "=This Servlet is responsible for Something."})
@SlingServletResourceTypes(resourceTypes = "api/service1",
methods = HttpConstants.METHOD_POST,
extensions = "json",
selectors = "something")
public class SomeServlet extends SlingAllMethodsServlet {
// Code
}
Here the servlet is registered using api/service1 as the resource type and can be invoked by using the resource path i.e. /content/wknd/services/api1 with something as the selector and json as the extension.
Request URL: /content/wknd/services/api1.something.json which will invoke the servlet.
If you do not want to register using any selector and extension then the same can be removed from servlet and the request will become only /content/wknd/services/api1
Hope this helps!
Thanks!
Views
Replies
Total Likes
Views
Replies
Total Likes
Views
Replies
Total Likes
Hi, where is ui.content filter? We dont seem to have anything like filter.xml in the source code. If we need to add it, which directory does it go in?
Below is the source code for wknd. We cant find anything like filter.xml or ui.content/filter.
Views
Replies
Total Likes
Hi @TB3dock
filter.xml is always available within the META-INF/vault folder. Please see the screenshot below:
Here it's part of aem-guides-wknd.ui.content.sample module for WKND tutorial.
In this way it will be deployed into all AEM instances.
If you do not want to keep it in code base, then you need to move it as a content package which is again a manual process and opens a chance of human error as we might forget to move certain node and it will break the application on upper environments.
Filter.xml file already has the entry for /content/wknd so here we do not have to make any change, but if it;s not there then we need to add it.
Thanks!
Views
Replies
Total Likes
Awesome thanks. We have been looking for a tutorial on how to get required content into the git repo for some time, and this might be it. We found the filter.xml in WEB-INF as you say, but are not sure how to combine it with the content you posted. is it this?
<?xml version="1.0" encoding="UTF-8"?>
<workspaceFilter version="1.0">
<filter root="/conf/wknd" mode="merge"/>
<filter root="/content/wknd" mode="merge"/>
<filter root="/content/dam/wknd" mode="merge"/>
<filter root="/content/experience-fragments/wknd" mode="merge"/>
<filter root="/content/cq:tags/wknd" mode="merge"/>
<filter root="/content/cq:graphql" mode="merge" />
<jcr:content
cq:allowedTemplates="[/conf/wknd/settings/wcm/templates/landing-page-template,/conf/wknd/settings/wcm/templates/article-page-template,/conf/wknd/settings/wcm/templates/content-page-template,/conf/wknd/settings/wcm/templates/adventure-page-template]"
cq:conf="/conf/wknd"
cq:lastModified="{Date}2020-01-06T15:53:34.296-08:00"
cq:lastModifiedBy="admin"
jcr:primaryType="cq:PageContent"
jcr:title="WKND Site"
sling:configRef="/conf/wknd"
sling:redirect="true"
sling:redirectStatus="{Long}302"
sling:resourceType="foundation/components/redirect"
redirectTarget="/content/wknd/en">
<image jcr:primaryType="nt:unstructured">
<file/>
</image>
</jcr:content>
<services
jcr:primaryType="nt:unstructured">
<api1
jcr:primaryType="nt:unstructured"
sling:resourceType="api/service1">
</api1>
<api2
jcr:primaryType="nt:unstructured"
sling:resourceType="api/service1">
</api2>
</services>
</workspaceFilter>
Or should it be just this?
<?xml version="1.0" encoding="UTF-8"?>
<workspaceFilter version="1.0">
<filter root="/conf/wknd" mode="merge"/>
<filter root="/content/wknd" mode="merge"/>
<filter root="/content/dam/wknd" mode="merge"/>
<filter root="/content/experience-fragments/wknd" mode="merge"/>
<filter root="/content/cq:tags/wknd" mode="merge"/>
<filter root="/content/cq:graphql" mode="merge" />
<services
jcr:primaryType="nt:unstructured">
<api1
jcr:primaryType="nt:unstructured"
sling:resourceType="api/service1">
</api1>
<api2
jcr:primaryType="nt:unstructured"
sling:resourceType="api/service1">
</api2>
</services>
</workspaceFilter>
Views
Replies
Total Likes
Hi @TB3dock
You need to add the XML snippet in the .context.xml file of wknd node in ui.content.sample package as it's being used by the wknd tutorial. Please see the screenshot below:
No update is required here for filter.xml as the parent node /content/wknd is already present in the filter.xml
Thanks!
Views
Replies
Total Likes
Registering Servlet using ResourceType:
I have a component Demo (/apps/ata/components/demo). Now am registering the Servlet with the resource type of my demo component.
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.SlingSafeMethodsServlet;
import org.apache.sling.servlets.annotations.SlingServletResourceTypes;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.propertytypes.ServiceDescription;
@Component(service = { Servlet.class })
@SlingServletResourceTypes(
resourceTypes="ata/components/demo",
methods=HttpConstants.METHOD_GET,
extensions="txt")
@ServiceDescription("Demo Component ResourceType Servlet")
public class DemoResourceTypeServlet extends SlingSafeMethodsServlet{
@Override
public void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) {
//Code
}
}
How to hit the servlet registered using ResourceType:
Servlet can be registered using html and json extension as well. Refer: https://sling.apache.org/documentation/the-sling-engine/servlets.html#example-registration-by-resour...
Views
Likes
Replies
Views
Likes
Replies