AEM Sling Dynamic Include

   
    Sling Dynamic Include (SDI) is an OSGi service that enables to automatically replace configured components with the include tags. 

Firstly download and install the Sling Dynamic Include bundle from the link in AEM bundles console.

Configure the SDI configuration in Felix console like in below screenshot.

Enter list of components (specify their resourceTypes) in configuration & update include tag type (SSI, ESI or AJAX) so that SDI will do the rest.




After this, AEM Page will not show the component on UI but was included as part of SDI configuration can see in view source of page.

For Component to be visible on front-end UI do following in httpd.conf file

1> Un-Comment below line - which includes all files.
   LoadModule include_module libexec/apache2/mod_include.so

2> Update the vhost file to respect include directives, add bolded & underlined text below
<VirtualHost *:80>
   <Directory /Library/WebServer/docroot/publish>
      ...
      # Add Includes to enable SSI Includes used by Slind Dynamic Include
      Options FollowSymLinks Includes
   
      # Set includes to process .html files
      AddOutputFilter INCLUDES .html
      ...
   </Directory>
</VirtualHost>

Now Component can be seen but Wait here it wont be updating content dyamically. It is served from cache content. 

Now we need to tell dispatcher that nocache selector which is the name we defined in SDI configuration need NOT to be Cached.

/cache {
  /glob "*.nocache.html*"
  /type "deny"
  /enableTTL "1"
}

Now Restart Apache Web Server after making changes to HTTPD configuration files or the dispatcher.any.

Now AEM Components whose resource types are mentioned in AEM SDI configuration will not be cached it always serve dynamic content not from cache.



AEM Sling redirect


Update below properties on jcr:content node of the page on which redirect to happen


AEM Desktop App

AEM Desktop app maps the AEM Assets to a network directory. 
This helps to view the AEM assets in Windows/Mac Explorer/Finder. 
The assets can also be edited using various image-editing apps. 
All changes are reflected immediately in AEM Assets and gets synced quickly.

Which version of OS supported by AEM Desktop App?

   At present the Windows(Version 7 and 10) and MacOSX(10.10 or later)

Where to get installer?

   Go to helpx.adobe site and access the path 'experience-manager/kb/download-companion-app.html'. Select the version and download the app.

How does the desktop app sync the data?

   AEM Desktop app saves files first in local system. Later, the upload to AEM Server happens on back end. This ensures that user is not interrupted on bigger uploads and all versions are maintained intact. Also Desktop App upload monitoring dialog option to monitor the upload process.

Installation steps

Download the installer.
Double click on .msi file (for Windows)








Connecting AEM Desktop App with AEM Instance

    Select the AEM Desktop app from start
    Enter the Connection root - your AEM Instance url > Enter 'Go'








        On task bar we can see the AEM icon, clicking on this will give us options to work with AEM Desktop app





Options

  • To see the assets of connected host, click on 'Explore Assets'
  • To see any upload status, click on 'Show back ground upload queue status'
  • We can also forget, disconnect current connection.
  • Configuration includes , connect on application start & Launch application on startup.
  • Advanced options provides log info , clear cache.

Debug AEM Desktop App installer issues

Cases where the app will not launch after installation.
1) When other apps are running on the same port.
2) When bit locker in locked if you are using it.

AEM MK (Microkernels) - TarMK and MongoMK


AEM comes with Oak storage. Oak(Apache Jackrabbit Product) is a new JCR implementation with a completely new internal architecture. 


There are two options for the AEM persistence layer back-end used by Oak : TarMK and MongoMK


Main differences b/w TarMK and MongoMK




Adobe recommendation says we must consider MongoMK when we come across below metrics
  • Number of named users connected in a day: in the thousands or more.
  • Number of concurrent users: in the hundreds or more.
  • Volume of asset ingestion per day: in hundreds of thousands or more.
  • Volume of page edits per day: in hundreds of thousands or more (including automated updates via Multi Site Manager or news feed ingestion for example).
  • Volume of searches per day: in tens of thousands or more.


     TarMK is optimized for single node performance whereas MongoMK is designed for scalability and clustered deployments also volume of data.



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

AEM Sling Queries

SlingQuery is a sling resource tree traversal tool inspired by the jQuery JavaScript API.

Sling Query is a bundle which is not a part of AEM Felix console till now, but after knowing the bright side of this particular bundle,I am surprised that why it is not the part of AEM.
But not to worry, we can do it by ourselves and take the advantages of it.

We can directly upload this bundle in the Felix console and add the dependency in pom.xml
<dependency>
      <groupId>org.apache.sling</groupId>
      <artifactId>org.apache.sling.query</artifactId>
      <version>3.0.0</version>
      <scope> provided</scope>
</dependency>

                                             Why Sling Query?

Sling Query saves us from a lot of code writing. It is a good to use this functionality.
It provides us results as an iterator.
  • useful operations to traverse the resource tree,
  • flexible filtering syntax,
  • lazy evaluation of the query result,
  • SlingQuery object is immutable (thread-safe),
  • fluent, friendly, jQuery-like API.
                                     When to use Sling Query?

Before using this concept, we need to understand the use cases where sling query will be best suited.
It is not an alternative of JCR Queries at all.It doesn’t indexes and for large set of tree traversal, it’s performance is so slow.
As a rule of thumb -
  • if you have a complex Java loop reading resource children or parents and processing them somehow, rewriting it to SlingQuery will be a good choice.
  • If you have a recursive method trying to get some resource ancestor, using SlingQuery will be a good choice.
  • On the other hand, if you have a large resource subtree and want to find all cq:Pages, using SlingQuery is a bad choice.
pros and cons.PNG
Fig- Diff between JCR and Sling Query

Methods list of Sling Query
There are a lot of methods that can be used efficiently to make the programming task much easier.
1).$(resource): Creates a sling query object using passed resource as an initial collection.
Resource resource = resourceResolver.getResource(“/content/we-retail”);
$(resource)

2).children() : fetch all the child resources of a resource.
$(resource).listChildren();

3) .children(String filter): To iterate the children of a resource of particular resource  type(here cq:Page) or any other filter condition.
$(resource).children(“cq:Page”);
$(resource).children(“cq:Page[jcr:title=test]”);

4) .closest(String selector): The closest applies on the ancestors of the resource with all the conditions.First it will check the parent of the resource ,than its parents and it will keep on going.
$(resource).closest(“cq:Page”)

5).eq(int index): Sling Query returns a iterator. If there is a need of getting the resource on the basis of index, this function is important.
$(resource).listChildren(“cq:Page”).eq(0);

6).filter(String selector): Filter given collection based on some selector.
final Calendar someTimeAgo = Calendar.getInstance();
someTimeAgo.add(Calendar.HOUR, -5);
// get children pages modified in the last 5 hours
SlingQuery query = $(resource).children("cq:Page").filter(new Predicate<Resource>() { @Override
public boolean accepts(Resource resource) {
return resource.adaptTo(Page.class).getLastModified().after(someTimeAgo);
}});

7) .has(String selector): If the collection has the particular resource based on the selector.
// If the resource fetch all its children having a property value as  foundation/components/redirect”
$(resource).children().has("foundation/components/redirect")

8).add(Resource...resource): To add resources in a slingQuery Iterator object.
// Now the SlingQuery iterator will have all the children of a resource and resource itself.
$(resource).children().add($(resource)

9).asList: The iterator of SlingQuery can be converted to a list and get a particular resource on the basis of index.
// Get the path of the first child resource of a particular resource
$(resource).children("cq:Page").asList().get(0).getPath();

10).find(): search through the matched elements’ child, grandchild, great-grandchild…any levels down.For each resource in collection return all its descendants using selected strategy. Please notice that invoking this method on a resource being a root of a large subtree may and will cause performance problems.
//the resource finds all the richtext resources which can be find in the children,sub-children of the resource
$(resource).find(foundation/components/richtext);

11).next():
// If a resource is having child1, child2 and child3,child2 will be returned.
$(resource).children().first().next();

12).nextAll():
// If a resource is having child1, child2, child3 and child4, child2, child3 and child4  will be returned.
$(resource).children().first().nextAll();

13).nextUntil():Return all following siblings for each resource in the collection up to, but not including, resource matched by a selector.

// let's assume that resource have 4 children: child1, child2, child3 and child4 additionaly, child4 has property jcr:title=Page
// return child2 and child3
$(resource).children().first().nextUntil("[jcr:title=Page]");

14).parent: Return the parent of the resource.
$(resource).parent();

15).parents:For each element in the collection find all of its ancestors, optionally filtering them by a selector.
//create page breadcrumbs for the given resource
$(resource).parents(“cq:Page”);

16) .parentsUntil():For each element in the collection find all of its ancestors until a resource matching the selector is found.
// It will not include that resource which satisfies the condition of cq:page.
$(resource).parentsUntil(“cq:Page”);

17).prev():Return the previous sibling for each resource in the collection and optionally filter it by a selector. If the selector is given, but the sibling doesn't match it, empty collection will be returned.
// let's assume that resource have 3 children: child1, child2 and child3
// return child2
$(resource).children().last().prev();

18).prevAll():Return all preceding siblings for each resource in the collection, optionally filtering them by a selector.
// let's assume that resource have 3 children: child1, child2 and child3
$(resource).children().last().prevAll(); // return child1 and child2

19).prevUntil():Return all preceding siblings for each resource in the collection up to, but not including, resource matched by a selector. 
// let's assume that resource have 4 children: child1, child2, child3 and child4
// additionally, child1 has property jcr:title=Page
$(resource).children().last().prevUntil("[jcr:title=Page]"); // return child2 and child3

20).siblings():Return siblings for the given resources, optionally filtered by a selector.
$(resource).closest("cq:Page").siblings("cq:Page"); // return all sibling pages
$(resource).children("cq:Page").first().siblings();// return all sibling of first child page

21).slice():Reduce the collection to a sub-collection specified by a given range. Both from and to are inclusive and 0-based indices. If the to parameter is not specified, the whole sub-collection starting with from will be returned.
// let's assume that resource have 4 children: child1, child2, child3 and child4
$(resource).children().slice(1, 2); // return child1 and child2

22).searchStrategy():Select new search strategy, which will be used in following find() and has() function invocations. There 3 options:
DFS and BFS iterate through descendants using appropriate algorithm. QUERY strategy tries to transform SlingQuery selector into a SQL2 query and invokes it. Because there are SlingQuery operations that can't be translated (eg. :has() modifier), the SQL2 query result is treated as an initial collection that needs further processing. 
  1. $(resource).searchStrategy(SearchStrategy.BFS).find("cq:Page");
  2. $(resource).searchStrategy(SearchStrategy.DFS).find("cq:Page");
  3. $(resource).searchStrategy(SearchStrategy.QUERY).find("cq:Page");

23).first():Filter resource collection to the first element. Equivalent to .eq(0) or .slice(0, 0).
$(resource).siblings().first(); // get the first sibling of the current resource

24).last():Filter resource collection to the last element.
$(resource).siblings().last(); // get the last sibling of the current resource

25).not():Reduce the set of matched elements to those which doesn't match the selector. The selector may contain other modifiers as well, however in this case the function will be evaluated eagerly:
  1. $(resource).children().not("cq:Page"); // remove all cq:Pages from the collection
  2. $(resource).children().not(":first").not(":last"); // remove the first and the last element of the collection

Sling Query Modifiers
Sling Query object is immutable.
$(resource).listChildren().first();

Here three objects gets created ,because slingQuery object is immutable.
  • $(resource)
  • $(resource).listChildren()
  • $(resource).listChildren().first();
Instead of creating many objects, modifiers helps to create less number of objects.
  1. :eq(index) : resource at a particular index can be fetch using eq(index) modifier.
$(resource).find("weretail/components/content/title:eq(0)")

  1. :gt(index) : fetch all the resources greater than the index using gt(index)modifier.
$(resource).children("cq:Page:gt(2)");

  1. :lt(index): fetch all the resources less than the index value using lt(index) modifier.
$(resource).find("weretail/components/content/title:lt(8):first");

  1. :even : fetch all the resources at the even place of the iterator.
$(resource).find("foundation/components/richtext:even");

  1. :odd :fetch all the resources at the odd place of the iterator.
$(resource).find("foundation/components/richtext:odd");

  1. :first :fetch first resources of the iterator.
$(resource).children("cq:Page:first");

  1. :last :fetch lastresources of the iterator.
$(resource).children("cq:Page:last");

  1. :parent : fetch the parent of the resource.
$(resource).find("foundation/components/richtext:parent");

  1. :has(selector) :Reduce the set of the matched elements to those which have descendant matching the selector.
// get children pages containing richtext component
$(resource).children("cq:Page:has(foundation/components/richtext)]");

  1. :not(selector) :Reduce the set of matched elements to those which doesn't match the selector. The selector may contain other modifiers as well, however in this case the function will be evaluated eagerly:
$(resource).children("cq:Page:not(:last)");

Operator list

  • Contains [name*=value]
  • Contains a word [name~=value]
  • Has attribute [name]
  • Starts with [name^=value]
  • Ends with [name$=value]
  • Equals [name=value]
  • Not equal [name!=value]

Hierarchy operator list
  • Child operator (parent > child)
  • Descendant operator (ancestor descendant)
  • Next adjacent operator (prev + next)
  • Next siblings operator (prev ~ next)
References: https://github.com/Cognifide/Sling-Query/wiki/Hierarchy-operator-list

References: