SlideShare a Scribd company logo
Sling Models
Justin Edelson – Technical Architect, Adobe
Let’s say you want to adapt a Resource into some domain object…
public class OldModel {
private String title;
private String description;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
@Component
@Service
@Properties({
@Property(name=AdapterFactory.ADAPTABLE_CLASSES, value="org.apache.sling.api.Resource"),
@Property(name=AdapterFactory.ADAPTER_CLASSES,
value="com.adobe.people.jedelson.slingmodels.demo.OldModel")
})
public class OldModelAdapterFactory implements AdapterFactory {
@SuppressWarnings("unchecked")
public <AdapterType> AdapterType getAdapter(Object adaptable, Class<AdapterType> type) {
if (adaptable instanceof Resource && type.equals(OldModel.class)) {
OldModel model = new OldModel();
ValueMap map = ResourceUtil.getValueMap((Resource) adaptable);
model.setTitle(map.get(”title", String.class));
model.setDescription(map.get(”description", String.class));
return (AdapterType) model;
} else {
return null;
}
}
}
OldModel myModel = resource.adaptTo(OldModel.class)
<sling:adaptTo adaptable="${resource}" adaptTo=”…
OldModel" var=”myModel" />
<div data-sly-use.myModel =“…OldModel”></div>
@Model(adaptables = Resource.class)
public class NewModel {
@Inject
private String title;
@Inject
private String description;
public String getTitle() {
return title;
}
public String getDescription() {
return description;
}
}
NewModel myModel = resource.adaptTo(NewModel.class)
<sling:adaptTo adaptable="${resource}" adaptTo=”…
NewModel" var=”myModel" />
<div data-sly-use.myModel=“…NewModel”></div>
• The “old” way: 30+ LOC
• The “new” way: 13 LOC
– Plus one extra bundle header:
<Sling-Model-Packages>com.adobe.people.jedelson.slingmodels.demo</Sling-Model-Packages>
@Model(adaptables = Resource.class)
public interface NewModel2 {
@Inject
public String getTitle();
@Inject
public String getDescription();
}
• 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).
• December 2013 – YAMF prototype
announced on sling-dev
• January 2014 – API formalized and renamed
to Sling Models
• Feburary 2014 – 1.0.0 release; Included in
AEM 6.0 Beta
• March 2014 – 1.0.2 release; Included in AEM
6.0 Release
• Standard Injectors
– SlingBindings objects
– ValueMap properties
– Child Resources
– Request Attributes
– OSGi Services
• @org.apache.sling.models.annotations.Model
• @javax.inject.Inject
• @javax.inject.Named
• @org.apache.sling.models.annotations.Optional
• @org.apache.sling.models.annotations.Source
• @org.apache.sling.models.annotations.Filter
• @javax.inject.PostConstruct
• @org.apache.sling.models.annotations.Via
• @org.apache.sling.models.annotations.Default
• @Model(adaptables = Resource.class)
• @Model(adaptables = SlingHttpServletRequest.class)
• @Model(adaptables = { Resource.class, ValueMap.class })
• @Inject private String title;
– valueMap.get(“title”, String.class);
• @Inject public String getTitle();
– valueMap.get(“title”, String.class);
• @Inject private String[] columnNames;
– valueMap.get(“columnNames”, String[].class);
• @Inject private List<Filter> filters;
– bundleContext.getServiceReferences(“javax.servlet.Filter”)
• By default, the name of the field or method is
used to perform the injection.
• @Inject @Named(“jcr:title”) private String
title;
– valueMap.get(“jcr:title”, String.class);
• By default, all @Inject points are required.
• resource.adaptTo(Model.class) <- returns null
• @Inject @Optional private String title;
• request.getAttribute(“text”) <- returns “goodbye”
• slingBindings.get(“text”) <- returns “hello”
• @Inject
private String text; <- “hello” (SlingBindings is checked first)
• @Inject @Source(“request-attributes”)
private String text; <- “goodbye”
• Specifically for OSGi services:
• @Inject @Filter("(sling.servlet.extensions=json)") private
List<Servlet> servlets;
• Implicitly applies @Source(“osgi-services”)
• @Inject private String text;
• @PostConstruct
protected void doSomething() { log.info("text = {}", text); };
• Superclass @PostConstruct methods called first.
@Model(adaptables = SlingHttpServletRequest.class)
public class ViaModel {
@Inject @Via("resource")
private String firstProperty;
public String getFirstProperty() {
return firstProperty;
}
}
• @Inject @Default(values=“default text”)
private String text;
• Also
– booleanValues
– doubleValues
– floatValues
– intValues
– longValues
– shortValues
If you need the adaptable itself:
@Model(adaptables = SlingHttpServletRequest.class)
public class ConstructorModel {
private final SlingHttpServletRequest request;
public ConstructorModel(SlingHttpServletRequest r) {
this.request = r;
}
public SlingHttpServletRequest getRequest() {
return request;
}
}
@Model(adaptables = Resource.class)
public interface ChildValueMapModel {
@Inject
public ValueMap getFirstChild();
}
resource.getChild(“firstChild”).adaptTo(ValueMap.class)
@Model(adaptables = Resource.class)
public interface ParentModel {
@Inject
public ChildModel getFirstChild();
}
Works even if resource.adaptTo(ChildModel.class) isn’t done
by Sling Models
• Injectors are OSGi services implementing the
org.apache.sling.models.spi.Injector interface
• Object getValue(Object adaptable, String name, Type
type, AnnotatedElement element, DisposalCallbackRegistry
callbackRegistry)
• adaptable – the object being adapted
• name – the name (either using @Named or the default
name)
• element – the method or field
• callbackRegistry – Injector gets notified when the adapted
model is garbage collected
public Object getValue(Object adaptable, String name,
Type type, AnnotatedElement element, DisposalCallbackRegistry callbackRegistry) {
Resource resource = getResource(adaptable);
if (resource == null) {
return null;
} else if (type instanceof Class<?>) {
InheritanceValueMap map = new
HierarchyNodeInheritanceValueMap(resource);
return map.getInherited(name, (Class<?>) type);
} else {
return null;
}
}
• Some injectors need extra data
– Example: OSGi service filters
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
@Source("resource-path")
public @interface ResourcePath {
String value();
}
public Object getValue(Object adaptable, String name,
Type declaredType, AnnotatedElement element,
DisposalCallbackRegistry callbackRegistry) {
ResourcePath path =
element.getAnnotation(ResourcePath.class);
if (path == null) {
return null;
}
ResourceResolver resolver = getResourceResolver(adaptable);
if (resolver == null) {
return null;
}
return resolver.getResource(path.value());
}
@Model(adaptables = Resource.class)
public interface ResourcePathModel {
@Inject @ResourcePath("/content/dam")
Resource getResource();
}
• More Standard Injectors
• AEM-specific injectors in ACS AEM Commons
• Pluggable @Via support
Questions?

More Related Content

What's hot

Rest and Sling Resolution
Rest and Sling ResolutionRest and Sling Resolution
Rest and Sling Resolution
DEEPAK KHETAWAT
 
Basics of Solr and Solr Integration with AEM6
Basics of Solr and Solr Integration with AEM6Basics of Solr and Solr Integration with AEM6
Basics of Solr and Solr Integration with AEM6
DEEPAK KHETAWAT
 

What's hot (20)

AEM Sightly Template Language
AEM Sightly Template LanguageAEM Sightly Template Language
AEM Sightly Template Language
 
Rest and Sling Resolution
Rest and Sling ResolutionRest and Sling Resolution
Rest and Sling Resolution
 
AEM Best Practices for Component Development
AEM Best Practices for Component DevelopmentAEM Best Practices for Component Development
AEM Best Practices for Component Development
 
Basics of Solr and Solr Integration with AEM6
Basics of Solr and Solr Integration with AEM6Basics of Solr and Solr Integration with AEM6
Basics of Solr and Solr Integration with AEM6
 
AEM - Client Libraries
AEM - Client LibrariesAEM - Client Libraries
AEM - Client Libraries
 
Heap Dump Analysis - AEM: Real World Issues
Heap Dump Analysis - AEM: Real World IssuesHeap Dump Analysis - AEM: Real World Issues
Heap Dump Analysis - AEM: Real World Issues
 
Osgi
OsgiOsgi
Osgi
 
AEM Rich Text Editor (RTE) Deep Dive
AEM Rich Text Editor (RTE) Deep DiveAEM Rich Text Editor (RTE) Deep Dive
AEM Rich Text Editor (RTE) Deep Dive
 
Apache Sling Generic Validation Framework
Apache Sling Generic Validation FrameworkApache Sling Generic Validation Framework
Apache Sling Generic Validation Framework
 
slingmodels
slingmodelsslingmodels
slingmodels
 
Sling Models Using Sightly and JSP by Deepak Khetawat
Sling Models Using Sightly and JSP by Deepak KhetawatSling Models Using Sightly and JSP by Deepak Khetawat
Sling Models Using Sightly and JSP by Deepak Khetawat
 
ReactJS presentation
ReactJS presentationReactJS presentation
ReactJS presentation
 
Spring beans
Spring beansSpring beans
Spring beans
 
SPA Editor - Adobe Experience Manager Sites
SPA Editor - Adobe Experience Manager SitesSPA Editor - Adobe Experience Manager Sites
SPA Editor - Adobe Experience Manager Sites
 
Spring MVC
Spring MVCSpring MVC
Spring MVC
 
ReactJS
ReactJSReactJS
ReactJS
 
ReactJS
ReactJSReactJS
ReactJS
 
React Hooks
React HooksReact Hooks
React Hooks
 
Introduction to React JS for beginners
Introduction to React JS for beginners Introduction to React JS for beginners
Introduction to React JS for beginners
 
Introduction to Sightly
Introduction to SightlyIntroduction to Sightly
Introduction to Sightly
 

Similar to Sling models by Justin Edelson

Framework prototype
Framework prototypeFramework prototype
Framework prototype
DevMix
 
Ajax Tags Advanced
Ajax Tags AdvancedAjax Tags Advanced
Ajax Tags Advanced
AkramWaseem
 
13 java beans
13 java beans13 java beans
13 java beans
snopteck
 
Microsoft PowerPoint - &lt;b>jQuery&lt;/b>-1-Ajax.pptx
Microsoft PowerPoint - &lt;b>jQuery&lt;/b>-1-Ajax.pptxMicrosoft PowerPoint - &lt;b>jQuery&lt;/b>-1-Ajax.pptx
Microsoft PowerPoint - &lt;b>jQuery&lt;/b>-1-Ajax.pptx
tutorialsruby
 
&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />
tutorialsruby
 

Similar to Sling models by Justin Edelson (20)

Deepak khetawat sling_models_sightly_jsp
Deepak khetawat sling_models_sightly_jspDeepak khetawat sling_models_sightly_jsp
Deepak khetawat sling_models_sightly_jsp
 
Integration patterns in AEM 6
Integration patterns in AEM 6Integration patterns in AEM 6
Integration patterns in AEM 6
 
Angular.js Primer in Aalto University
Angular.js Primer in Aalto UniversityAngular.js Primer in Aalto University
Angular.js Primer in Aalto University
 
Framework prototype
Framework prototypeFramework prototype
Framework prototype
 
Framework prototype
Framework prototypeFramework prototype
Framework prototype
 
Framework prototype
Framework prototypeFramework prototype
Framework prototype
 
Jersey
JerseyJersey
Jersey
 
Ajax Tags Advanced
Ajax Tags AdvancedAjax Tags Advanced
Ajax Tags Advanced
 
13 java beans
13 java beans13 java beans
13 java beans
 
Prototype-1
Prototype-1Prototype-1
Prototype-1
 
Prototype-1
Prototype-1Prototype-1
Prototype-1
 
java beans
java beansjava beans
java beans
 
jQuery-1-Ajax
jQuery-1-AjaxjQuery-1-Ajax
jQuery-1-Ajax
 
Microsoft PowerPoint - &lt;b>jQuery&lt;/b>-1-Ajax.pptx
Microsoft PowerPoint - &lt;b>jQuery&lt;/b>-1-Ajax.pptxMicrosoft PowerPoint - &lt;b>jQuery&lt;/b>-1-Ajax.pptx
Microsoft PowerPoint - &lt;b>jQuery&lt;/b>-1-Ajax.pptx
 
jQuery-1-Ajax
jQuery-1-AjaxjQuery-1-Ajax
jQuery-1-Ajax
 
&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />
 
Scala for Java Programmers
Scala for Java ProgrammersScala for Java Programmers
Scala for Java Programmers
 
Using hilt in a modularized project
Using hilt in a modularized projectUsing hilt in a modularized project
Using hilt in a modularized project
 
Application Frameworks: The new kids on the block
Application Frameworks: The new kids on the blockApplication Frameworks: The new kids on the block
Application Frameworks: The new kids on the block
 
Core Data Migrations and A Better Option
Core Data Migrations and A Better OptionCore Data Migrations and A Better Option
Core Data Migrations and A Better Option
 

More from AEM HUB

Socialize your Exceptional Web Experience – Adobe AEM & IBM Connections by He...
Socialize your Exceptional Web Experience – Adobe AEM & IBM Connections by He...Socialize your Exceptional Web Experience – Adobe AEM & IBM Connections by He...
Socialize your Exceptional Web Experience – Adobe AEM & IBM Connections by He...
AEM HUB
 
Sightly Beautiful Markup by Senol Tas
Sightly Beautiful Markup by Senol Tas Sightly Beautiful Markup by Senol Tas
Sightly Beautiful Markup by Senol Tas
AEM HUB
 

More from AEM HUB (20)

Microservices for AEM by Maciej Majchrzak
Microservices for AEM by Maciej MajchrzakMicroservices for AEM by Maciej Majchrzak
Microservices for AEM by Maciej Majchrzak
 
When dispatcher caching is not enough by Jakub Wądołowski
When dispatcher caching is not enough by Jakub WądołowskiWhen dispatcher caching is not enough by Jakub Wądołowski
When dispatcher caching is not enough by Jakub Wądołowski
 
PhoneGap Enterprise Viewer by Anthony Rumsey
PhoneGap Enterprise Viewer by Anthony RumseyPhoneGap Enterprise Viewer by Anthony Rumsey
PhoneGap Enterprise Viewer by Anthony Rumsey
 
Integrating Apache Wookie with AEM by Rima Mittal and Ankit Gubrani
Integrating Apache Wookie with AEM by Rima Mittal and Ankit GubraniIntegrating Apache Wookie with AEM by Rima Mittal and Ankit Gubrani
Integrating Apache Wookie with AEM by Rima Mittal and Ankit Gubrani
 
Mastering the Sling Rewriter by Justin Edelson
Mastering the Sling Rewriter by Justin EdelsonMastering the Sling Rewriter by Justin Edelson
Mastering the Sling Rewriter by Justin Edelson
 
Building Quality into the AEM Publication Workflow with Active Standards by D...
Building Quality into the AEM Publication Workflow with Active Standards by D...Building Quality into the AEM Publication Workflow with Active Standards by D...
Building Quality into the AEM Publication Workflow with Active Standards by D...
 
Touching the AEM component dialog by Mateusz Chromiński
Touching the AEM component dialog by Mateusz ChromińskiTouching the AEM component dialog by Mateusz Chromiński
Touching the AEM component dialog by Mateusz Chromiński
 
How to build a Social Intranet with Adobe Sites and 3rd Party products ... us...
How to build a Social Intranet with Adobe Sites and 3rd Party products ... us...How to build a Social Intranet with Adobe Sites and 3rd Party products ... us...
How to build a Social Intranet with Adobe Sites and 3rd Party products ... us...
 
How do you build flexible platforms that focuses on business needs? by Fahim...
How do you build flexible platforms that focuses on business needs?  by Fahim...How do you build flexible platforms that focuses on business needs?  by Fahim...
How do you build flexible platforms that focuses on business needs? by Fahim...
 
AEM Apps Enhanced: In-app Messaging and Beacons by John Fait
AEM Apps Enhanced: In-app Messaging and Beacons by John FaitAEM Apps Enhanced: In-app Messaging and Beacons by John Fait
AEM Apps Enhanced: In-app Messaging and Beacons by John Fait
 
Effectively Scale and Operate AEM with MongoDB by Norberto Leite
Effectively Scale and Operate AEM with MongoDB by Norberto LeiteEffectively Scale and Operate AEM with MongoDB by Norberto Leite
Effectively Scale and Operate AEM with MongoDB by Norberto Leite
 
Adobe Managed Services: Complicated Cloud Deployments by Adam Pazik, Mike Til...
Adobe Managed Services: Complicated Cloud Deployments by Adam Pazik, Mike Til...Adobe Managed Services: Complicated Cloud Deployments by Adam Pazik, Mike Til...
Adobe Managed Services: Complicated Cloud Deployments by Adam Pazik, Mike Til...
 
Adobe Marketing Cloud Integrations: Myth or Reality? by Holger Marsen
Adobe Marketing Cloud Integrations: Myth or Reality? by Holger MarsenAdobe Marketing Cloud Integrations: Myth or Reality? by Holger Marsen
Adobe Marketing Cloud Integrations: Myth or Reality? by Holger Marsen
 
Responsive Websites and Grid-Based Layouts by Gabriel Walt
Responsive Websites and Grid-Based Layouts by Gabriel Walt Responsive Websites and Grid-Based Layouts by Gabriel Walt
Responsive Websites and Grid-Based Layouts by Gabriel Walt
 
When Sightly Meets Slice by Tomasz Niedźwiedź
When Sightly Meets Slice by Tomasz NiedźwiedźWhen Sightly Meets Slice by Tomasz Niedźwiedź
When Sightly Meets Slice by Tomasz Niedźwiedź
 
Creativity without comprise by Cleve Gibbon
Creativity without comprise by Cleve Gibbon Creativity without comprise by Cleve Gibbon
Creativity without comprise by Cleve Gibbon
 
REST in AEM by Roy Fielding
REST in AEM by Roy FieldingREST in AEM by Roy Fielding
REST in AEM by Roy Fielding
 
Adobe Summit 2015 - Penguin Random House - Accelerating Digital Transformation
Adobe Summit 2015 - Penguin Random House - Accelerating Digital TransformationAdobe Summit 2015 - Penguin Random House - Accelerating Digital Transformation
Adobe Summit 2015 - Penguin Random House - Accelerating Digital Transformation
 
Socialize your Exceptional Web Experience – Adobe AEM & IBM Connections by He...
Socialize your Exceptional Web Experience – Adobe AEM & IBM Connections by He...Socialize your Exceptional Web Experience – Adobe AEM & IBM Connections by He...
Socialize your Exceptional Web Experience – Adobe AEM & IBM Connections by He...
 
Sightly Beautiful Markup by Senol Tas
Sightly Beautiful Markup by Senol Tas Sightly Beautiful Markup by Senol Tas
Sightly Beautiful Markup by Senol Tas
 

Recently uploaded

Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo DiehlFuture Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Peter Udo Diehl
 

Recently uploaded (20)

Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
 
IoT Analytics Company Presentation May 2024
IoT Analytics Company Presentation May 2024IoT Analytics Company Presentation May 2024
IoT Analytics Company Presentation May 2024
 
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
 
In-Depth Performance Testing Guide for IT Professionals
In-Depth Performance Testing Guide for IT ProfessionalsIn-Depth Performance Testing Guide for IT Professionals
In-Depth Performance Testing Guide for IT Professionals
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
IESVE for Early Stage Design and Planning
IESVE for Early Stage Design and PlanningIESVE for Early Stage Design and Planning
IESVE for Early Stage Design and Planning
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
 
UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2
 
Speed Wins: From Kafka to APIs in Minutes
Speed Wins: From Kafka to APIs in MinutesSpeed Wins: From Kafka to APIs in Minutes
Speed Wins: From Kafka to APIs in Minutes
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
10 Differences between Sales Cloud and CPQ, Blanka Doktorová
10 Differences between Sales Cloud and CPQ, Blanka Doktorová10 Differences between Sales Cloud and CPQ, Blanka Doktorová
10 Differences between Sales Cloud and CPQ, Blanka Doktorová
 
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
 
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya HalderCustom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
 
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo DiehlFuture Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
 

Sling models by Justin Edelson

  • 1. Sling Models Justin Edelson – Technical Architect, Adobe
  • 2.
  • 3. Let’s say you want to adapt a Resource into some domain object…
  • 4. public class OldModel { private String title; private String description; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } }
  • 5. @Component @Service @Properties({ @Property(name=AdapterFactory.ADAPTABLE_CLASSES, value="org.apache.sling.api.Resource"), @Property(name=AdapterFactory.ADAPTER_CLASSES, value="com.adobe.people.jedelson.slingmodels.demo.OldModel") }) public class OldModelAdapterFactory implements AdapterFactory { @SuppressWarnings("unchecked") public <AdapterType> AdapterType getAdapter(Object adaptable, Class<AdapterType> type) { if (adaptable instanceof Resource && type.equals(OldModel.class)) { OldModel model = new OldModel(); ValueMap map = ResourceUtil.getValueMap((Resource) adaptable); model.setTitle(map.get(”title", String.class)); model.setDescription(map.get(”description", String.class)); return (AdapterType) model; } else { return null; } } }
  • 6. OldModel myModel = resource.adaptTo(OldModel.class) <sling:adaptTo adaptable="${resource}" adaptTo=”… OldModel" var=”myModel" /> <div data-sly-use.myModel =“…OldModel”></div>
  • 7. @Model(adaptables = Resource.class) public class NewModel { @Inject private String title; @Inject private String description; public String getTitle() { return title; } public String getDescription() { return description; } }
  • 8. NewModel myModel = resource.adaptTo(NewModel.class) <sling:adaptTo adaptable="${resource}" adaptTo=”… NewModel" var=”myModel" /> <div data-sly-use.myModel=“…NewModel”></div>
  • 9. • The “old” way: 30+ LOC • The “new” way: 13 LOC – Plus one extra bundle header: <Sling-Model-Packages>com.adobe.people.jedelson.slingmodels.demo</Sling-Model-Packages>
  • 10. @Model(adaptables = Resource.class) public interface NewModel2 { @Inject public String getTitle(); @Inject public String getDescription(); }
  • 11. • 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).
  • 12. • December 2013 – YAMF prototype announced on sling-dev • January 2014 – API formalized and renamed to Sling Models • Feburary 2014 – 1.0.0 release; Included in AEM 6.0 Beta • March 2014 – 1.0.2 release; Included in AEM 6.0 Release
  • 13. • Standard Injectors – SlingBindings objects – ValueMap properties – Child Resources – Request Attributes – OSGi Services
  • 14. • @org.apache.sling.models.annotations.Model • @javax.inject.Inject • @javax.inject.Named • @org.apache.sling.models.annotations.Optional • @org.apache.sling.models.annotations.Source • @org.apache.sling.models.annotations.Filter • @javax.inject.PostConstruct • @org.apache.sling.models.annotations.Via • @org.apache.sling.models.annotations.Default
  • 15. • @Model(adaptables = Resource.class) • @Model(adaptables = SlingHttpServletRequest.class) • @Model(adaptables = { Resource.class, ValueMap.class })
  • 16. • @Inject private String title; – valueMap.get(“title”, String.class); • @Inject public String getTitle(); – valueMap.get(“title”, String.class); • @Inject private String[] columnNames; – valueMap.get(“columnNames”, String[].class); • @Inject private List<Filter> filters; – bundleContext.getServiceReferences(“javax.servlet.Filter”)
  • 17. • By default, the name of the field or method is used to perform the injection. • @Inject @Named(“jcr:title”) private String title; – valueMap.get(“jcr:title”, String.class);
  • 18. • By default, all @Inject points are required. • resource.adaptTo(Model.class) <- returns null • @Inject @Optional private String title;
  • 19. • request.getAttribute(“text”) <- returns “goodbye” • slingBindings.get(“text”) <- returns “hello” • @Inject private String text; <- “hello” (SlingBindings is checked first) • @Inject @Source(“request-attributes”) private String text; <- “goodbye”
  • 20.
  • 21. • Specifically for OSGi services: • @Inject @Filter("(sling.servlet.extensions=json)") private List<Servlet> servlets; • Implicitly applies @Source(“osgi-services”)
  • 22. • @Inject private String text; • @PostConstruct protected void doSomething() { log.info("text = {}", text); }; • Superclass @PostConstruct methods called first.
  • 23. @Model(adaptables = SlingHttpServletRequest.class) public class ViaModel { @Inject @Via("resource") private String firstProperty; public String getFirstProperty() { return firstProperty; } }
  • 24. • @Inject @Default(values=“default text”) private String text; • Also – booleanValues – doubleValues – floatValues – intValues – longValues – shortValues
  • 25. If you need the adaptable itself: @Model(adaptables = SlingHttpServletRequest.class) public class ConstructorModel { private final SlingHttpServletRequest request; public ConstructorModel(SlingHttpServletRequest r) { this.request = r; } public SlingHttpServletRequest getRequest() { return request; } }
  • 26. @Model(adaptables = Resource.class) public interface ChildValueMapModel { @Inject public ValueMap getFirstChild(); } resource.getChild(“firstChild”).adaptTo(ValueMap.class)
  • 27. @Model(adaptables = Resource.class) public interface ParentModel { @Inject public ChildModel getFirstChild(); } Works even if resource.adaptTo(ChildModel.class) isn’t done by Sling Models
  • 28. • Injectors are OSGi services implementing the org.apache.sling.models.spi.Injector interface • Object getValue(Object adaptable, String name, Type type, AnnotatedElement element, DisposalCallbackRegistry callbackRegistry) • adaptable – the object being adapted • name – the name (either using @Named or the default name) • element – the method or field • callbackRegistry – Injector gets notified when the adapted model is garbage collected
  • 29. public Object getValue(Object adaptable, String name, Type type, AnnotatedElement element, DisposalCallbackRegistry callbackRegistry) { Resource resource = getResource(adaptable); if (resource == null) { return null; } else if (type instanceof Class<?>) { InheritanceValueMap map = new HierarchyNodeInheritanceValueMap(resource); return map.getInherited(name, (Class<?>) type); } else { return null; } }
  • 30. • Some injectors need extra data – Example: OSGi service filters @Target({ ElementType.FIELD, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Qualifier @Source("resource-path") public @interface ResourcePath { String value(); }
  • 31. public Object getValue(Object adaptable, String name, Type declaredType, AnnotatedElement element, DisposalCallbackRegistry callbackRegistry) { ResourcePath path = element.getAnnotation(ResourcePath.class); if (path == null) { return null; } ResourceResolver resolver = getResourceResolver(adaptable); if (resolver == null) { return null; } return resolver.getResource(path.value()); }
  • 32. @Model(adaptables = Resource.class) public interface ResourcePathModel { @Inject @ResourcePath("/content/dam") Resource getResource(); }
  • 33. • More Standard Injectors • AEM-specific injectors in ACS AEM Commons • Pluggable @Via support