Hello Everyone,
From AEM 6.0 onward, Sling Models has made AEM Development easier. I, being an AEM Dev realized that we are taking very less benefits of sling models.so I decided to go in deep and find out what sling model can provide us in all.We are now standing on AEM 6.3 with sling models 1.3.2 version.
So we will start from the basics and will touch each and every concept in detail.
Design Goals of Sling Models
- Entirely annotation driven. "Pure" POJOs.
- Use standard annotations where possible.
- Pluggable
- OOTB, support resource properties (via ValueMap), SlingBindings, OSGi services, request attributes
- Adapt multiple objects - minimal required Resource and SlingHttpServletRequest
- Client doesn't know/care that these objects are different than any other adapter factory
- Support both classes and interfaces.
- Work with existing Sling infrastructure (i.e. not require changes to other bundles).
How to start using Sling Models
1.Add maven dependency to the pom.xml. If you are working with AEM 6.3, Make sure you are using the recent sling model version (1.3.2)
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.models.api</artifactId>
<version>1.3.2</version>
<scope>provided</scope>
</dependency>
|
2. Create a package under which you will be writing all sling models and make an entry of that package (here com.sling.models.core.models) in bundle(core) ‘s pom.xml in Sling-Model-Packages tag within maven-bundle-plugin.
Here:
Validate that your class is actually working as a sling model.
Let’s understand these injectors with the help of examples.
Note: Here it is mandatory to use the object name “currentPage”. If there is a need to change the name of page object(currentPage), the “name” attribute can help us to do so.
ChildResource annotations with its attributes:
Note: ChildResource is adaptable to resource,but in the above sample, adaptables is a request.So "via" attribute is used to tell the property that the property is supposed to be fetch via resource.
The ValueMapValue annotation using its attributes:
➤ You can directly inject a path as a resource using this annotation.
5. OSGiService: If we need to inject OSGiService in Sling Models, we can use it like this:
The sightly script calls the sling Model using input parameter :
The Demonstration video on @SlingObject, @Self and @RequestAttribute annotations:
Here:
<plugin>
<groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Sling-Model-Packages>
com.sling.models.core.models
</Sling-Model-Packages>
</instructions>
</configuration>
</plugin>
|
Validate that your class is actually working as a sling model.
- Go to Felix Console.
- Click on Sling Adapters from the Sling tab.
Fig- Sling Adapters in Felix Console |
- Sling Model class must be visible over here.
How to write a basic sling model?
// This model gets the path of the resource . @Model(adaptables = Resource.class)
public class TestModel { @Inject Resource resource; public String getPath() { return resource.getPath(); } } |
In the initial state of sling models, we used to use @Inject annotation to inject services, pagemanager, sling objects etc. This is a generic Injector.
- @Inject queries all Injector implementations “First Match” wins based on the service ranking.
- Usage of Injector-specific annotations (Introduced in sling models Impl 1.0.6) will reduce the overall work of the internal execution as it specify the source explicitly so it is good to use Injector specific annotations.
Injector Specific Annotations in Sling Model
In AEM Felix console, you can see all the available injectors in sling models 1.3.2
Fig - Injector Specific Annotations in Sling Model |
Fig - List of specific injectors |
1. Script Variable: This Injector is used to get the currentPage, PageManager, Design, PageProperties etc. This injector is adaptable to request.This injector is adaptable to SlingHttpServletRequest.
ScriptVariable annotation has these attributes:
ScriptVariable annotation has these attributes:
- name
- injectionStrategy: The Strategy can be Optional, Required or Default.
@Model(adaptables = SlingHttpServletRequest.class)
public class TestModel {
// Injects currentPage using ScriptVariable annotation
@ScriptVariable(name="currentPage")
Page page;
public String getPagePath() {
return page.getPath();
}
}
|
The sightly script to call a sling model is:
<div data-sly-use.example="com.sling.models.core.models.TestModel">
${example.pagePath}<br/>
</div>
|
2. ChildResource : This injector is adaptable to resource and is used to get the specific child of a resource.
The attributes of the ChildResource are:
- name
- injectionStrategy
- via
It works like:
@Model(adaptables = Resource.class)
public class TestModel {
// Injects the child of the resource using ChildResource annotation
@ChildResource(name="content")
Resource child;
public String getChildPath() {
return child.getPath();
}
}
|
Fig - Inject Child resource directly |
ChildResource annotations with its attributes:
@Model(adaptables = SlingHttpServletRequest.class)
public class TestModel {
// Injects the child of the resource using ChildResource annotation
@ChildResource(name="content",injectionStrategy= InjectionStrategy.OPTIONAL,via = "resource")
Resource child;
public String getChildPath() {
return child.getPath();
}
}
|
Note: ChildResource is adaptable to resource,but in the above sample, adaptables is a request.So "via" attribute is used to tell the property that the property is supposed to be fetch via resource.
The Demonstration video on @ScriptVariable and @ChildResource annotation:
3.ValueMapValue: This injector is adaptable to resource.Through this injector,the properties of the resource can be directly injected in the sling models.
3.ValueMapValue: This injector is adaptable to resource.Through this injector,the properties of the resource can be directly injected in the sling models.
The attributes of the ValueMapValue is:
- name
- injectionStrategy
- via
@Model(adaptables = Resource.class)
public class TestModel {
// Injects Resource and get ValueMap from the resource
@SlingObject
Resource resource;
public String getTitle() {
ValueMap valueMap = resource.adaptTo(ValueMap.class);
return valueMap.get(“title”, String.class);
}
}
|
In place of adapting valueMap from the resource and getting title from valueMap,we can directly use ValueMapValue annotation in sling models.
@Model(adaptables = Resource.class)
public class TestModel {
// Injects title from ValuMapValue
@ValueMapValue
String title;
public String getTitle() {
return title;
}
}
|
Fig - Value Map Sample |
The ValueMapValue annotation using its attributes:
@Model(adaptables = SlingHttpServletRequest.class)
public class Test {
// Injects title from ValuMap annotation using its attributes
@ValueMapValue(name = "title",via = "resource",injectionStrategy = InjectionStrategy.REQUIRED)
String pageTitle;
public String getTitle() {
return pageTitle;
}
}
|
4.ResourcePath:
➤ If a resource is having a property whose value is a path, you can directly use that property as a resource.➤ You can directly inject a path as a resource using this annotation.
The attributes of the ResourcePath annotation is:
- name
- injectionStrategy
- path
- paths[]
@Model(adaptables = Resource.class )
public class TestModel {
//directly inject a path as a resource
@ResourcePath(path = ”/etc/social”)
Resource pathResource;
@ResourcePath(name = "path")
Resource resourcePath;
@ResourcePath(paths = {"/etc/social","/etc/tags"})
Resource[] paths;
}
|
Fig - Get the Resource by passing the path dynamically in sling model |
5. OSGiService: If we need to inject OSGiService in Sling Models, we can use it like this:
@Model(adaptables = Resource.class)
public class TestModel {
@OSGiService
SlingSettings slingSetttings;
}
|
The Demonstration video on @ValueMapValue, @ResourcePath and @OSGiService annotations:
6. SlingObject: Supports sling based Objects like request,response, ResourceResolver, Resource and Sling ScriptHelper.
6. SlingObject: Supports sling based Objects like request,response, ResourceResolver, Resource and Sling ScriptHelper.
@Model(adaptables = SlingHttpServletRequest.class)
public class TestModel {
@SlingObject
Resource resource;
@SlingObject
ResourceResolver resourceResolver;
}
|
7.Self:
➤ Injects the adaptable object itself.
➤ An object that can be adapted from it if self annotation is present.
The only attribute in Self annotation is injectionStrategy.
➤ An object that can be adapted from it if self annotation is present.
The only attribute in Self annotation is injectionStrategy.
@Model(adaptables = SlingHttpServletRequest.class)
public class SelfExampleModel {
@Self
Node node;
public String getNodePath() throws RepositoryException
{
return node.getPath();
}
}
|
8. Request Attributes: When there are input parameters while initializing the sling model , and you want to get these parameters in the sling model, you can use this annotation.
The attributes of RequestAttribute annotation are:
The attributes of RequestAttribute annotation are:
- name
- injectionStrategy
@Model(adaptables = SlingHttpServletRequest.class)
public class TestModel {
//Injects all the input parameters from sightly injects as RequestAttribute in Sling Models
@RequestAttribute(name = "color")
String param;
public String getParam() {
return param;
}
}
|
The sightly script calls the sling Model using input parameter :
<div data-sly-use.example="${'com.sling.models.core.models.TestModel ’ @ color='red'}">
${example.param}<br/>
</div>
|
If you have any query or suggestion then kindly comment or mail us at sgaem.blog02@gmail.com
Hope it will help you guys !!
Thanks and Happy Learning.
Wow.. didnt know so many different flavors in sling model. Always used to experiment first time and simply copy paste for following years. This helps to explore and try out other options. Thanks for sharing.
ReplyDeleteGreat information. Thanks for your great work.
ReplyDeleteNicely explained.. Thanks for sharing this.. :)
ReplyDeleteCongratulations, the article explains all different options in a simple way, provides examples and also demonstrates in video 10/10
ReplyDeleteThanks to all for your lovely comments. These comments are my motivation to write more and better.
ReplyDeleteWell articulated. Thanks for your innovative thinking & contributions here. All the Best!
ReplyDeleteBest article and content that I have ever read very well explained.
ReplyDeleteI am glad that u like it.
DeleteHi Shivani,
ReplyDeleteAre you aware of any probable reason for sling model class not showing in sling adapters.
Only one reason, you didn't follow the step 2 from blog of "How to create sling models".
DeleteHi shivani
ReplyDeleteIs it possible to share the package for this code?
Thanks a ton Shivani !
ReplyDeleteThankyou Shivani for a wonderful article.
ReplyDeleteYour Article is help me a lot and tried with osgiservice annotation. but
ReplyDelete@osgiservice class return null object.Any probable reason behind this.
very short explanation like for @self annotation, didnt understand the use of that.
ReplyDeleteThis is exactly I need.. thanks to clear my concept
ReplyDeleteCan you please share the package for the code?
ReplyDeleteThanks guys for putting this up, I didn't knew there were so many options available for the same task by sling model itself, This is a great help indeed.
ReplyDeleteKeep up the good work, Kudos!
https://medium.com/techie-talks/working-with-sling-models-in-aem-b025cebdbf47
ReplyDeleteWorking with sling model -
ReplyDeletehttps://medium.com/techie-talks/working-with-sling-models-in-aem-b025cebdbf47
Hi,
ReplyDeleteCurrently I am trying to get the cookie value from sightly.I tried the annotation @RequestAttribute that you mentioned here.
But i am getting error like RequestAttribute cannot find symbol.
Can you please helpe to take the value from dightly to java.
This comment has been removed by the author.
ReplyDeleteThank you for the clear content on annotations.
ReplyDeleteCould you also explain when to choose Resource or SlingHttpServletRequest as adaptables while creating a model?