Sling Models are "pure" POJOs that maps Sling objects (resources, request objects, etc.).
Since Sling Models are annotation-driven Plain Old Java Objects (POJOs), annotations are used a lot. They allow you to map resource properties, assign default values, inject OSGi services and much more.
Without making a further delay, let's see the concepts in action.
Working with Sling Models
For AEM 6.2
- Download the latest Sling Models API and Implementation bundles from here and upload them to ./system/console/bundles
- In the project’s pom files, make sure the version numbers for Sling Models API and Implementation are updated based on the ones installed in your AEM server.
- In your core module pom.xml file, check for maven-bundle-plugin, and make sure you have all packages that contain the model classes or interfaces in header Sling-Model-Packages, so that your models can be picked up.
For AEM 6.3+
- Since AEM 6.3 is built on Sling 1.3, we don't have to install any bundles in our AEM server.
- But we need to make sure that the Sling Models API version in AEM matches with the one in our project's pom files.
Example
Now let us look at an example for sling models
- Create a new AEM project using AEM Multimodule Project and deploy it in your AEM instance.
- Go to CRXDE and under your project in /apps create a new component with the following configuration
Create a Component |
- Now create the cq:dialog node under the component node with the following configuration.
<?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="nt:unstructured"
jcr:title="User Component"
sling:resourceType="cq/gui/components/authoring/dialog">
<content
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/layouts/tabs"
type="nav"/>
<items jcr:primaryType="nt:unstructured">
<properties
jcr:primaryType="nt:unstructured"
jcr:title="User Properties"
sling:resourceType="granite/ui/components/foundation/container">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"/>
<items jcr:primaryType="nt:unstructured">
<columns
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<firstName
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/textfield"
class="field-whitespace"
fieldDescription="Please enter the first name"
fieldLabel="First Name"
name="./firstName"/>
<lastName
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/textfield"
class="field-whitespace"
fieldDescription="Please enter the last name"
fieldLabel="Last Name"
name="./lastName"/>
<gender
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/select"
fieldDescription="Select your grnder"
fieldLabel="gender"
name="./gender">
<items jcr:primaryType="nt:unstructured">
<male
jcr:primaryType="nt:unstructured"
text="Male"
value="Male"/>
<female
jcr:primaryType="nt:unstructured"
text="Female"
value="Female"/>
<other
jcr:primaryType="nt:unstructured"
text="Other"
value="Other"/>
</items>
</gender>
<country
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/select"
fieldDescription="Select your country"
fieldLabel="Country"
name="./country">
<items jcr:primaryType="nt:unstructured">
<option1
jcr:primaryType="nt:unstructured"
text="India"
value="India"/>
<option2
jcr:primaryType="nt:unstructured"
text="Canada"
value="Canada"/>
<option3
jcr:primaryType="nt:unstructured"
text="Israel"
value="Israel"/>
<option4
jcr:primaryType="nt:unstructured"
text="Other"
value="Other"/>
</items>
</country>
</items>
</columns>
</items>
</properties>
</items>
</content>
</jcr:root>
- Create a new class UserModel.java in your project and paste the following code into it
package org.redquark.demo.core.models;
import javax.inject.Inject;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Model;
/**
* @author Anirudh Sharma
*
* User Component model class
*/
@Model(adaptables = Resource.class)
public class UserModel {
@Inject
private String firstName;
@Inject
private String lastName;
@Inject
private String gender;
@Inject
private String country;
/**
* @return the firstName
*/
public String getFirstName() {
return firstName;
}
/**
* @return the lastName
*/
public String getLastName() {
return lastName;
}
/**
* @return the gender
*/
public String getGender() {
return gender;
}
/**
* @return the country
*/
public String getCountry() {
return country;
}
}
- Let us understand the code of the class. We are using @Model annotation to specify that this model class is a Sling Model. Each data member is annotated with @Inject. This class will be mapped to a resource in JCR.
- Drag and drop the component on the page and configure it
Configure the component |
- After saving the component, the data will save under the page node as shown in the figure
Data stored in JCR |
- To access this resource in the JCR, let us create a Sling Servlet and paste the following code in it.
package org.redquark.demo.core.servlets;
import javax.servlet.Servlet;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.redquark.demo.core.models.UserModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Anirudh Sharma
*
* Servlet to consume the Sling Model
*/
@Component(service = Servlet.class, property = {
Constants.SERVICE_DESCRIPTION + "=Sling Demo Servlet",
"sling.servlet.methods=" + HttpConstants.METHOD_GET,
"sling.servlet.paths=" + "/bin/slingmodel/user"
})
public class SlingModelServlet extends SlingSafeMethodsServlet {
/**
* Generated serialVersionUID
*/
private static final long serialVersionUID = 7558680464517017317 L;
/**
* Logger
*/
private static final Logger log = LoggerFactory.getLogger(SlingModelServlet.class);
/**
* Overridden method
*/
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) {
try {
log.info("----------< Processing starts >----------");
/**
* Getting the instance of resource resolver
*/
ResourceResolver resourceResolver = request.getResourceResolver();
/**
* Getting the resource which has the data stored
*/
Resource resource = resourceResolver
.getResource("/content/we-retail/language-masters/en/user/jcr:content/root/responsivegrid/user");
/**
* Adapting the resource to the UserModel class
*/
UserModel model = resource.adaptTo(UserModel.class);
/**
* Printing the value stored on the browser window
*/
response.getWriter()
.print("Data stored in the resource is:\nFirst Name: " + model.getFirstName() + "\nLast Name: " +
model.getLastName() + "\nGender: " + model.getGender() + "\nCountry: " +
model.getCountry());
/**
* Closing the resource resolver
*/
resourceResolver.close();
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
- In line #54-55, we are getting the resource and in line #60, we are adapting the resource to our UserModel class
- Note that we are not setting any data in the model object, we are just calling the getters to access the data stored in the JCR.
- Now, deploy the code in your AEM server (how? see here) and hit the request - http://<host>:<port>/bin/slingmodel/user you will see the following result.
Data stored in the resource is:
First Name: Anirudh
Last Name: Sharma
Gender: Male
Country: India
- As you see, we can directly access a Sling Resource using Sling Model classes. This saves us a lot of boilerplate code and lets us do separation of concerns.
No comments:
Post a Comment
If you have any doubts or questions, please let us know.