In the past, AEM developers would heavily focus on building AEM components with Java Server Pages (JSPs) & JavaServer Pages Standard Tag Libraries (JSTLs).
There are special JSTLs for AEM JSP components to speed up the development. One popular JSTL is called the Sling Taglib. The Sling Taglib is popular when it comes to writing AEM JSP components which provide the AEM component with the ability to invoke JSP scripts, including Resources and interact with the Sling Repository, all with JSP tags and Expression Language (EL) functions.
This is all great but JSP’s are becoming less common for writing AEM components as Sightly has become more mainstream and best practice. That being said, these JSPs are legacy and needs to be upgraded.
One common task for AEM developers is to upgrade JSP components to Sightly components.
1 2 | Target TagLib: <%@taglib prefix="sling" uri="http://sling.apache.org/taglibs/sling" %> |
Note: While writing AEM Sightly components, AEM global objects are available and should have most of the AEM’s core JSTL functionalities.
Quick Links
1. adaptTo() to Sling Model & Sightly
Adapts an Adaptable to another class.
Returns: java.lang.Object
Accepts:
- org.apache.sling.api.adapter.Adaptable – The object to adapt
- java.lang.String – The name of the class to which to adapt the adaptable
Since: 1.3
JSP: Sling Tablib example usage:
1 2 3 4 | <c:set var="valueMap" value="${sling:adaptTo(resource,'org.apache.sling.api.resource.ValueMap')}" /> <c:set var="page" value="${sling:adaptTo(resource,'com.day.cq.wcm.api.Page')}" /> ${valueMap} ${page} |
Non-JSP & Non-JSTL implementation
Sightly:
1 2 3 4 5 | <div class="cmp-examplemodel" data-sly-use.examplemodel="com.sourcedcode.aem.core.models.ExampleModel"> ${examplemodel.valueMap} ${examplemodel.page} </div> |
Sling Model:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | package com.sourcedcode.aem.core.models; import com.day.cq.wcm.api.Page; import lombok.Getter; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ValueMap; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.injectorspecific.ScriptVariable; import javax.inject.Inject; import javax.inject.Named; @Model(adaptables = Resource.class) public class ExampleModel { @Getter private ValueMap valueMap; @Getter private Page page; @Inject protected void ExampleModel(@ScriptVariable @Named("resource") final Resource resource) { valueMap = resource.adaptTo(ValueMap.class); // example here page = resource.adaptTo(Page.class); } } |
2. encode() to Sling Model & Sightly
Writes properly Cross-Site Scripting (XSS) encoded text to the response using the OWASP ESAPI. Supports a number of encoding modes.
Returns: java.util.String – An encoded text
Accepts:
- java.lang.String – The text to encode
- java.lang.String – The encoding mode, one of HTML, HTML_ATTR, XML, XML_ATTR, JS
Since: 1.4
JSP: Sling Tablib example usage:
1 | ${sling:encode('<script>alert("Bad Stuff!");</script>','HTML')} |
Non-JSP & Non-JSTL implementation
Sightly:
1 | ${'<script>alert("Bad Stuff!");</script>' @ context='html'} |
3. findResources() to Sling Model & Sightly
Searches for resources using the given query formulated in the given language.
Returns: java.util.Iterator – An Iterator of Resource objects matching the query.
Accepts:
- org.apache.sling.api.resource.ResourceResolver – The Resource Resolver to use for the query.
- java.lang.String – The query string to use to find the resources.
- java.lang.String – The language in which the query is formulated.
Since: 1.3
JSP: Sling Tablib example usage:
1 2 3 | <c:forEach var="resourceItem" items="${sling:findResources(resourceResolver,'/jcr:root//*[jcr:contains(., 'Sling')] order by @jcr:score','xpath')"> <li>${resourceItem.path}</li> </c:forEach> |
Non-JSP & Non-JSTL implementation
Sightly:
1 2 3 4 5 6 | <div class="cmp-examplemodel" data-sly-use.examplemodel="com.sourcedcode.aem.core.models.ExampleModel"> <ul data-sly-list.resourceItem="${examplemodel.resources}"> <li>${resourceItem.name}</li> </ul> </div> |
Sling Model:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | package com.sourcedcode.aem.core.models; import lombok.Getter; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.injectorspecific.SlingObject; import javax.inject.Inject; import javax.inject.Named; import javax.jcr.query.Query; import java.util.Iterator; @Model(adaptables = Resource.class) public class ExampleModel { @Getter private Iterator<Resource> resources; @Inject protected void ExampleModel(@SlingObject @Named("resourceResolver") final ResourceResolver resolver) { resources = resolver .findResources("/jcr:root//*[jcr:contains(., 'Sling')] order by @jcr:score", Query.XPATH); // Query.XPATH depricated, recommended to use Query.JCR_SQL2 // resources = resolver // .findResources("SELECT * FROM [nt:base] AS s WHERE ISDESCENDANTNODE([/content/sourcedcode])", // Query.JCR_SQL2); } } |
4. getAbsoluteParent() to Sling Model & Sightly
Method for retrieving an absolute parent resource.
Returns: org.apache.sling.api.resource.Resource – The parent resource at the specified level
Accepts:
- org.apache.sling.api.resource.Resource – The current resource
- java.lang.String – The absolute level for the parent resource to retrieve
Since: Bundle 2.3.0
JSP: Sling Tablib example usage:
1 2 | <c:set var="absoluteParentResource" value="${sling:getAbsoluteParent(resource,'2')}" /> ${absoluteParentResource.title} |
Non-JSP & Non-JSTL implementation
Sightly:
1 2 3 4 | <div class="cmp-examplemodel" data-sly-use.examplemodel="com.sourcedcode.aem.core.models.ExampleModel"> <h1>${examplemodel.absoluteParentResource.title}</h1> </div> |
Sling Model:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package com.sourcedcode.aem.core.models; import com.day.cq.wcm.api.Page; import lombok.Getter; import org.apache.sling.api.resource.Resource; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.injectorspecific.ScriptVariable; import javax.inject.Inject; import javax.inject.Named; @Model(adaptables = Resource.class) public class ExampleModel { @Getter private Page absoluteParentResource; @Inject protected void ExampleModel(@ScriptVariable @Named("currentPage") final com.day.cq.wcm.api.Page currentPage) { absoluteParentResource = currentPage.getAbsoluteParent(2); } } |
5. getParents() to Sling Model & Sightly
Function for retrieving all of the parent resources of a specified resource, returning them in hierarchy order.
Returns: java.lang.Iterator – an iterator of the parent resources in order
Accepts:
- org.apache.sling.api.resource.Resource – The current resource for which to retrieve the parents
- java.lang.String – The depth at which to start, for example given a path of: /content/page1/page2/page3 and a start depth of 3, the parents page2/page3 would be returned
Since: Bundle 2.3.0
JSP: Sling Tablib example usage:
1 2 3 4 | <c:set var="parentResources" value="${sling:getParents(resource,'2')}" /> <c:forEach var="parentResourceItem" items="${parentResources}"> <div>${parentResourceItem.path}</div> </c:forEach> |
Non-JSP & Non-JSTL implementation
Sightly:
1 2 3 4 5 6 | <div class="cmp-examplemodel" data-sly-use.examplemodel="com.sourcedcode.aem.core.models.ExampleModel"> <ul data-sly-list.parentResourceItem="${examplemodel.parentResources}"> <li>${parentResourceItem.name}</li> </ul> </div> |
Sling Model:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | package com.sourcedcode.aem.core.models; import lombok.Getter; import org.apache.sling.api.resource.Resource; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.injectorspecific.ScriptVariable; import javax.inject.Inject; import javax.inject.Named; import java.util.Iterator; @Model(adaptables = Resource.class) public class ExampleModel { @Getter private Iterator<Resource> parentResources; @Inject protected void ExampleModel(@ScriptVariable @Named("resource") final Resource resource) { parentResources = getParents(resource, 2); } // no Sling API found, this is custom code private Iterator<Resource> getParents(Resource resource, int depth) { Resource currentResource = resource; for (int i = 0; i < depth; i++) { if (currentResource.getParent() != null) { currentResource = currentResource.getParent(); } } return resource.listChildren(); } } |
6. getRelativeResource() to Sling Model & Sightly
Gets the resource at the relative path to the provided resource.
Returns: org.apache.sling.api.resource.Resource – The resource at the relative path.
Accepts:
- org.apache.sling.api.resource.Resource – The resource relative to which to find the path.
- java.lang.String – The relative path at which to find the resource.
Since: 1.3
JSP: Sling Tablib example usage:
1 2 | <c:set var="myResource" value="${sling:getRelativeResource(resource,'jcr:content')}" /> ${myResource.name} |
Non-JSP & Non-JSTL implementation
Sightly:
1 2 3 4 | <div class="cmp-examplemodel" data-sly-use.examplemodel="com.sourcedcode.aem.core.models.ExampleModel"> <p>${examplemodel.myResource.name}</p> </div> |
Sling Model:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package com.sourcedcode.aem.core.models; import lombok.Getter; import org.apache.sling.api.resource.Resource; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.injectorspecific.ScriptVariable; import javax.inject.Inject; import javax.inject.Named; @Model(adaptables = Resource.class) public class ExampleModel { @Getter private Resource myResource; @Inject protected void ExampleModel(@ScriptVariable @Named("resource") final Resource resource) { myResource = resource.getChild("jcr:content"); } } |
7. getResource() to Sling Model & Sightly
Method allow for the retrieval of resources.
Returns: org.apache.sling.api.resource.Resource – The resource at the path.
Accepts:
- org.apache.sling.api.resource.ResourceResolver – The current resource resolver.
- java.lang.String – The path at which to find the resource.
Since: 1.3
JSP: Sling Tablib example usage:
1 2 | <c:set var="myResource" value="${sling:getResource(resourceResolver,'/content')}" /> ${myResource.name} |
Non-JSP & Non-JSTL implementation
Sightly:
1 2 3 4 | <div class="cmp-examplemodel" data-sly-use.examplemodel="com.sourcedcode.aem.core.models.ExampleModel"> <p>${examplemodel.myResource.name}</p> </div> |
Sling Model:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package com.sourcedcode.aem.core.models; import lombok.Getter; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.injectorspecific.ScriptVariable; import javax.inject.Inject; import javax.inject.Named; @Model(adaptables = Resource.class) public class ExampleModel { @Getter private Resource myResource; @Inject protected void ExampleModel(@ScriptVariable @Named("resolver") final ResourceResolver resolver) { myResource = resolver.getResource("/content"); } } |
8. getValue() to Sling Model & Sightly
Gets the value of the specified key from the ValueMap and either coerses the value into the specified type or uses the specified type as a default depending on the parameter passed in.
If the third parameter is a class, the resulting value will be coersed into the class, otherwise, the third parameter is used as the default when retrieving the value from the ValueMap.
Returns: java.lang.Object – The value.
Accepts:
- org.apache.sling.api.resource.ValueMap – The ValueMap from which to retrieve the value.
- java.lang.String – The key for the value to retrieve
- java.lang.Object – Either the default value or the class to which to coerce the value.
Since: 1.3
JSP: Sling Tablib example usage:
1 2 | <c:set var="myResourceTitle" value="${sling:getValue(properties,'jcr:title',resource.name)}" /> ${myResourceTitle} |
Non-JSP & Non-JSTL implementation
Sightly:
1 2 3 | <div class="cmp-examplemodel"> ${properties.jcr:title} </div> |
9. getResource() to Sling Model & Sightly
Method allow for the retrieval of resources.
Returns: org.apache.sling.api.resource.Resource – The resource at the path.
Accepts:
- org.apache.sling.api.resource.ResourceResolver – The current resource resolver.
- java.lang.String – The path at which to find the resource.
Since: 1.3
JSP: Sling Tablib example usage:
1 2 | <c:set var="myResource" value="${sling:getResource(resourceResolver,'/content')}" /> ${myResource.name} |
Non-JSP & Non-JSTL implementation
Sightly:
1 2 3 4 | <div class="cmp-examplemodel" data-sly-use.examplemodel="com.sourcedcode.aem.core.models.ExampleModel"> <p>${examplemodel.myResource.name}</p> </div> |
Sling Model:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package com.sourcedcode.aem.core.models; import lombok.Getter; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.injectorspecific.ScriptVariable; import javax.inject.Inject; import javax.inject.Named; @Model(adaptables = Resource.class) public class ExampleModel { @Getter private Resource myResource; @Inject protected void ExampleModel(@ScriptVariable @Named("resolver") final ResourceResolver resolver) { myResource = resolver.getResource("/content"); } } |
10. hasChildren() to Sling Model & Sightly
Return true if the specified resource has child resources.
Returns: java.lang.Boolean – True if there are child resource of the specified resource
Accepts:
- org.apache.sling.api.resource.Resource – The resource of which to check for children.
Since: 1.3
JSP: Sling Tablib example usage:
1 2 3 | <c:if test="${sling:hasChildren(resource)"> <h1>This resource has children</h1> </c:if> |
Non-JSP & Non-JSTL implementation
Sightly:
1 2 3 4 5 | <div class="cmp-examplemodel"> <div data-sly-test="${resource.hasChildren}"> <h1>This resource has children</h1> </div> </div> |
11. listChildren() to Sling Model & Sightly
Method for allowing the invocation of the Sling Resource listChildren method.
Returns: java.util.Iterator – The children of the resource.
Accepts:
- org.apache.sling.api.resource.Resource – The resource of which to list the children.
Since: 1.3
JSP: Sling Tablib example usage:
1 2 3 | <c:forEach var="child" items="${sling:listChildren(resource)"> <li>${child.path}</li> </c:forEach> |
Non-JSP & Non-JSTL implementation
Sightly:
1 2 3 4 5 | <div class="cmp-examplemodel"> <ul data-sly-list.child="${resource.listChildren}"> <li>${child.path}</li> </ul> </div> |