AEM Sling Model


A Sling Model is implemented as an OSGi bundle. 


AEM’s component development needs a back end logic to retrieve values from back end. Sightly is a templating language which together with WCMPojo helps to create components.

Adobe recommends Sling Models as a best way of implementing AEM WCM Components from version AEM 6.1.


A Java class located in the OSGi bundle is annotated with @Model and the adaptable class (for example, @Model(adaptables = Resource.class)

The data members (Fields) use @Inject annotations. These data members map to node properties.


In simple terms Sling Models are simple POJO classes which are mapped automatically with Sling Objects (resource, request objects..) and allow us to access jcr node property values directly into java classes.


@PostConstruct annotation can be used to add methods which are invoked upon completion of all injections:

Sample Java Class:-

@Model(adaptables = Resource.class) public class UserInfo { @Inject private String firstName; @Inject private String lastName; public String getFirstName() { return firstName; } public String getLastName() { return lastName; }
@PostConstruct

protected void sayHello(){

logger.info("Hello");
}
}

        Sling model works on injection, once all injections are completed this method (@postconstruct) gets called.


         PostConstruct is only used by sling-models. 
While using WCMUsePojo you have the activate method.


Advantages of using Sling Models 
  • Pure POJO classes. 
  • Entirely annotation driven (Need to write less code). 
  • Can adapt multiple objects – Minimal required Resource and SlingHttpServletRequest OOTB, support resource properties (via ValueMap), SlingBindings, OSGi services, request attributes 
  • Support both classes and interfaces. Plugabble. 
  • Work with existing Sling infrastructure (i.e. not require changes to other bundles).
In order for these classes to be picked up, there is an header which must be added into our bundle's manifest:

              <Sling-Model-Packages>
                  org.apache.sling.models.it.models
              </Sling-Model-Packages>

Header must contain all packages which contain model classes or interfaces. However, sub-packages need not be listed individually, e.g. the header in above syntax will also pick up model classes listed in subpackage i.e. org.apache.sling.models.it.models.sub

Multiple packages can be listed with comma-separated list like below (any white space will be removed):

           <Sling-Model-Packages>
                  org.apache.sling.models.it.models,
                 org.apache.sling.other.models
           </Sling-Model-Packages>

We can also list out all classes individually that are Sling Models classes via the Sling-Model-Classes header.

If we use Sling Models bnd plugin all required bundle headers are generated automatically at build time

Few Sling Annotation Reference
@Model : declares a model class or interface
@Inject : marks a field or method as injectable
@Named : declare a name for the injection (otherwise,  defaults based on field or method name).
@Optional : marks a field or method injection as optional
@Source : explicitly tie an injected field or method to a particular injector (by name). Can also be on other annotations.
@Filter : an OSGi service filter
@PostConstruct : methods to call upon model option creation (only for model classes)
@Via : change the adaptable as the source of the injection
@Default : set default values for a field or method
@Path : only used together with the resource-path injector to specify the path of a resource
@Exporter/@Exporters/@ExporterOption/@ExporterOptions : for Exporter Framework

Difference Between WCMUsePojo Vs Sling Models

  • Mixed POJOs - Pure POJOs
  • Extends from WCMUsePojo class - Define Standalone class with '@Model' annotation and having no keyword
  • More code required to retrieve common objects or property values - Easier methods to retrieve common objects or property values
  • Uses  Felix annotation '@Reference' to reference to an available OSGI service - Uses '@Inject' or '@OSGiService'
  • In case of WCMUsePojo, we have to overwrite the activate() method - init() method will be called in the @PostConstruct annotation
  • Not annotation driven - Annotation driven