SlideShare a Scribd company logo
Sling Models
Justin Edelson – Technical Architect, Adobe
Sling models by Justin Edelson
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”
Sling models by Justin Edelson
• 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 (20)

PDF
AEM Best Practices for Component Development
Gabriel Walt
 
PPTX
Rest and Sling Resolution
DEEPAK KHETAWAT
 
PDF
AEM Sightly Template Language
Gabriel Walt
 
PPTX
Osgi
Heena Madan
 
PDF
AEM Sightly Deep Dive
Gabriel Walt
 
PDF
Basics of Solr and Solr Integration with AEM6
DEEPAK KHETAWAT
 
PPTX
Mastering the Sling Rewriter
Justin Edelson
 
PDF
slingmodels
Ankur Chauhan
 
PPTX
Omnisearch in AEM 6.2 - Search All the Things
Justin Edelson
 
PDF
Introduction to Sightly
Ankit Gubrani
 
PPTX
Sightly - Part 2
Prabhdeep Singh
 
PDF
Spring Data JPA
Cheng Ta Yeh
 
PDF
Apache Jackrabbit Oak - Scale your content repository to the cloud
Robert Munteanu
 
PDF
AWS 고객이 주로 겪는 운영 이슈에 대한 해법-AWS Summit Seoul 2017
Amazon Web Services Korea
 
PDF
Managing Omnichannel Experiences with Adobe Experience Manager (AEM)
Gabriel Walt
 
PDF
SPA Editor - Adobe Experience Manager Sites
Gabriel Walt
 
PPTX
HTML/CSS/java Script/Jquery
FAKHRUN NISHA
 
PDF
Spring Data JPA from 0-100 in 60 minutes
VMware Tanzu
 
PDF
AWS Black Belt Online Seminar 2017 Amazon S3
Amazon Web Services Japan
 
PDF
Adobe Experience Manager Core Components
Gabriel Walt
 
AEM Best Practices for Component Development
Gabriel Walt
 
Rest and Sling Resolution
DEEPAK KHETAWAT
 
AEM Sightly Template Language
Gabriel Walt
 
AEM Sightly Deep Dive
Gabriel Walt
 
Basics of Solr and Solr Integration with AEM6
DEEPAK KHETAWAT
 
Mastering the Sling Rewriter
Justin Edelson
 
slingmodels
Ankur Chauhan
 
Omnisearch in AEM 6.2 - Search All the Things
Justin Edelson
 
Introduction to Sightly
Ankit Gubrani
 
Sightly - Part 2
Prabhdeep Singh
 
Spring Data JPA
Cheng Ta Yeh
 
Apache Jackrabbit Oak - Scale your content repository to the cloud
Robert Munteanu
 
AWS 고객이 주로 겪는 운영 이슈에 대한 해법-AWS Summit Seoul 2017
Amazon Web Services Korea
 
Managing Omnichannel Experiences with Adobe Experience Manager (AEM)
Gabriel Walt
 
SPA Editor - Adobe Experience Manager Sites
Gabriel Walt
 
HTML/CSS/java Script/Jquery
FAKHRUN NISHA
 
Spring Data JPA from 0-100 in 60 minutes
VMware Tanzu
 
AWS Black Belt Online Seminar 2017 Amazon S3
Amazon Web Services Japan
 
Adobe Experience Manager Core Components
Gabriel Walt
 

Similar to Sling models by Justin Edelson (20)

PDF
Deepak khetawat sling_models_sightly_jsp
DEEPAK KHETAWAT
 
PPTX
Integration patterns in AEM 6
Yuval Ararat
 
PDF
Sling Models Using Sightly and JSP by Deepak Khetawat
AEM HUB
 
PDF
Angular.js Primer in Aalto University
SC5.io
 
PPTX
Framework prototype
DevMix
 
PPTX
Framework prototype
DevMix
 
PPTX
Framework prototype
DevMix
 
PDF
Jersey
Yung-Lin Ho
 
PDF
Ajax Tags Advanced
AkramWaseem
 
PDF
13 java beans
snopteck
 
PDF
Prototype-1
tutorialsruby
 
PDF
Prototype-1
tutorialsruby
 
PDF
java beans
lapa
 
PDF
jQuery-1-Ajax
guestcf600a
 
PDF
&lt;img src="../i/r_14.png" />
tutorialsruby
 
PDF
jQuery-1-Ajax
guestcf600a
 
PDF
Microsoft PowerPoint - &lt;b>jQuery&lt;/b>-1-Ajax.pptx
tutorialsruby
 
PDF
Scala for Java Programmers
Eric Pederson
 
PDF
Using hilt in a modularized project
Fabio Collini
 
KEY
Application Frameworks: The new kids on the block
Richard Lord
 
Deepak khetawat sling_models_sightly_jsp
DEEPAK KHETAWAT
 
Integration patterns in AEM 6
Yuval Ararat
 
Sling Models Using Sightly and JSP by Deepak Khetawat
AEM HUB
 
Angular.js Primer in Aalto University
SC5.io
 
Framework prototype
DevMix
 
Framework prototype
DevMix
 
Framework prototype
DevMix
 
Jersey
Yung-Lin Ho
 
Ajax Tags Advanced
AkramWaseem
 
13 java beans
snopteck
 
Prototype-1
tutorialsruby
 
Prototype-1
tutorialsruby
 
java beans
lapa
 
jQuery-1-Ajax
guestcf600a
 
&lt;img src="../i/r_14.png" />
tutorialsruby
 
jQuery-1-Ajax
guestcf600a
 
Microsoft PowerPoint - &lt;b>jQuery&lt;/b>-1-Ajax.pptx
tutorialsruby
 
Scala for Java Programmers
Eric Pederson
 
Using hilt in a modularized project
Fabio Collini
 
Application Frameworks: The new kids on the block
Richard Lord
 
Ad

More from AEM HUB (20)

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

Recently uploaded (20)

PPTX
AI Code Generation Risks (Ramkumar Dilli, CIO, Myridius)
Priyanka Aash
 
PDF
Brief History of Internet - Early Days of Internet
sutharharshit158
 
PDF
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
PDF
OpenInfra ID 2025 - Are Containers Dying? Rethinking Isolation with MicroVMs.pdf
Muhammad Yuga Nugraha
 
PDF
Build with AI and GDG Cloud Bydgoszcz- ADK .pdf
jaroslawgajewski1
 
PPTX
AI in Daily Life: How Artificial Intelligence Helps Us Every Day
vanshrpatil7
 
PDF
Responsible AI and AI Ethics - By Sylvester Ebhonu
Sylvester Ebhonu
 
PPTX
AVL ( audio, visuals or led ), technology.
Rajeshwri Panchal
 
PPTX
PCU Keynote at IEEE World Congress on Services 250710.pptx
Ramesh Jain
 
PPTX
Simple and concise overview about Quantum computing..pptx
mughal641
 
PDF
GDG Cloud Munich - Intro - Luiz Carneiro - #BuildWithAI - July - Abdel.pdf
Luiz Carneiro
 
PPTX
Applied-Statistics-Mastering-Data-Driven-Decisions.pptx
parmaryashparmaryash
 
PDF
How ETL Control Logic Keeps Your Pipelines Safe and Reliable.pdf
Stryv Solutions Pvt. Ltd.
 
PPTX
IT Runs Better with ThousandEyes AI-driven Assurance
ThousandEyes
 
PDF
Researching The Best Chat SDK Providers in 2025
Ray Fields
 
PDF
Lecture A - AI Workflows for Banking.pdf
Dr. LAM Yat-fai (林日辉)
 
PDF
Market Insight : ETH Dominance Returns
CIFDAQ
 
PDF
The Future of Mobile Is Context-Aware—Are You Ready?
iProgrammer Solutions Private Limited
 
PDF
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 
PDF
Economic Impact of Data Centres to the Malaysian Economy
flintglobalapac
 
AI Code Generation Risks (Ramkumar Dilli, CIO, Myridius)
Priyanka Aash
 
Brief History of Internet - Early Days of Internet
sutharharshit158
 
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
OpenInfra ID 2025 - Are Containers Dying? Rethinking Isolation with MicroVMs.pdf
Muhammad Yuga Nugraha
 
Build with AI and GDG Cloud Bydgoszcz- ADK .pdf
jaroslawgajewski1
 
AI in Daily Life: How Artificial Intelligence Helps Us Every Day
vanshrpatil7
 
Responsible AI and AI Ethics - By Sylvester Ebhonu
Sylvester Ebhonu
 
AVL ( audio, visuals or led ), technology.
Rajeshwri Panchal
 
PCU Keynote at IEEE World Congress on Services 250710.pptx
Ramesh Jain
 
Simple and concise overview about Quantum computing..pptx
mughal641
 
GDG Cloud Munich - Intro - Luiz Carneiro - #BuildWithAI - July - Abdel.pdf
Luiz Carneiro
 
Applied-Statistics-Mastering-Data-Driven-Decisions.pptx
parmaryashparmaryash
 
How ETL Control Logic Keeps Your Pipelines Safe and Reliable.pdf
Stryv Solutions Pvt. Ltd.
 
IT Runs Better with ThousandEyes AI-driven Assurance
ThousandEyes
 
Researching The Best Chat SDK Providers in 2025
Ray Fields
 
Lecture A - AI Workflows for Banking.pdf
Dr. LAM Yat-fai (林日辉)
 
Market Insight : ETH Dominance Returns
CIFDAQ
 
The Future of Mobile Is Context-Aware—Are You Ready?
iProgrammer Solutions Private Limited
 
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 
Economic Impact of Data Centres to the Malaysian Economy
flintglobalapac
 

Sling models by Justin Edelson

  • 1. Sling Models Justin Edelson – Technical Architect, Adobe
  • 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”
  • 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