Sling Resource Resolution and AEM - Part 2


Part 1 :- https://www.dhirubhai.net/pulse/sling-resource-resolution-aem-part-1-veena-vikraman/


I really want to share my understanding on this topic as I have seen a lot of developers in AEM struggle to understand how exactly a script/file is executed , when a content is rendered. Trust me it's not any rocket science. It is just some well written rules. That is what Sling Resolution is all about as far as I understand. If we understand these rules , it is simple. So what can we do ???? ? How about putting ourselves in SLING shoes (?? that's how I tried to learn SLING when I was taking my baby steps. I used to act like I am SLING and trace the path from one node to another in terms of SLING, till I clearly understood. It might sound funny I know ??)

Why don't we go for another walk in SLING ?? and try to understand this concept ? Let's give it a try

To help you understand this , let's do some initial setup in our local AEM instance. As I always do , I have setup the WKND project in my local. ( It has complete project setup with code , content and everything we need.)

Find it here :- https://docs.adobe.com/content/help/en/experience-manager-learn/getting-started-wknd-tutorial-develop/overview.html

Now once the setup is done, make sure you have all the pages up and running. In this article I am assuming your AEM is running on port 4502 . Else, replace the below URLs with your corresponding ports.

Now let's take example of a page . I like tacos ?? so I am going with https://localhost:4502/content/wknd/en/restaurants/best-tacos-in-the-city.html

Now, as you enter the above URL in the browser , you surely get a page rendered with a lot of content. So how does this content get rendered with everything in the correct place ? ???? ever wondered ?

If I quote the words from the official Sling documentation

Request Processing?— Sling takes a unique approach to handling requests in that a request URL is first resolved to a resource, then based on the resource (and only the resource) it selects the actual servlet or script to handle the request.
Resources?— The central mantra of Sling is the?Resource, which represents the resource addressed by any request URL. It is the resource that is first resolved when handling a request. Based on the resource, a first servlet or script is then accessed to actually handle the request.

Coming back to our example, let us just take a walk along the footsteps of SLING on how it is going to resolve our URL and is going to render our page for us.

As you can see this resolves to a cq:Page. So the next thing SLING will look for is a content node of type (cq:PageContent) and name(jcr:content). If that is not found, an error will be thrown. A page will only become a valid resource if has below structure

page
  (type:cq:Page)
      --
        |
          jcr:content (type-> cq:PageContent)
        

So as SLING, I know I should be looking at the cq:PageContent child node( which should be surely of name jcr:content) of a cq:Page node for proceeding further ahead to resolve this request. - I have to correct myself here . A little more on how SLING actually decides to go to jcr:content from cq:Page node. Read this article here :- https://cqdump.wordpress.com/2019/01/07/how-does-sling-resolve-an-aem-page-to-the-correct-resource-type/ (Jorg has explained it very well. They are the experts I look up to ??)

  • Now lets go to the jcr:content node. ( Here I am trying to go on the route where the content is delivered or resource is rendered) So, SLING ( here after referred as I ) will look for a property called sling:resourceType . This is the property which defines what ( or I would say where) is the resource for this node. So for the page /content/wknd/en/restaurants/best-tacos-in-the-city the sling:resourceType is wknd/components/structure/page

So our next stop is this


  • I am going to navigate to this node via CRXDE as from here, we might have to take a look at the scripting files if any and CRXDE would be the best for opening and checking those files. (You can do it in your local IDEs too ) . Now I know our resource in question is residing at wknd/components/structure/page ; but where ? Is it under /apps ? or is it under /libs ?

Okay now a little confession time ???? When I used to take training for AEM , I used to tell the developers that if we have a relative path, then in AEM, SLING will look for the resources first under /apps and then under /libs ?? . I won't say that is wrong. It was and is correct but the point is no one asked me why and how ? And as I was just exploring things at that time , I would not have been able to answer the question if they have asked ???? . But then if you have a similar question now, I would say take a look at https://aemmastery.com/aem-osgi-service-dive-resource-resolver-factory-c2521f75be51

As I have mentioned before there are certain principles or rules by which SLING delivers the content and those are mostly defined in such OSGI configurations as the one above. ( I might not have 100% info on all of them )

  • So now I will go to /apps/wknd/components/structure/page. This is where we look at how the Sling Resolution Principles come into picture. So before heading further lets take a quick look at the URL decomposition mentioned here https://sling.apache.org/documentation/the-sling-engine/url-decomposition.html . All my further explanations will be based on this.
  • So as per the above documentation , our request URI /content/wknd/en/restaurants/best-tacos-in-the-city.html doesn't have a selector. But it has an extension .html . Keeping that in mind, let us look at the files under /apps/wknd/components/structure/page and figure out how the script is rendered to deliver the content.

Now how the script is resolved from this resource !?.

For the same take a look at https://sling.apache.org/documentation/the-sling-engine/url-to-script-resolution.html . I know many things will be little over the head for any fresh developer. But don't worry now. I will try to put that to you in a layman's term as much as I can.

If you finished reading the above URL , let me simplify the same here in simple words

  • For the resource /apps/wknd/components/structure/page ; the resolution principle will look for the best match as below . (Keep in mind few things . Here we don't have selector for our URI . Also since we have moved on with HTL , we will no more refer any JSP at least in this case. But do we have components which use JSPs still ? Hell yes. Will talk about those later sometime for sure )

       Below are the best matches in the order
                1. page.html
                2. html.html
                3. sling:resourceSuperType
                4. GET.html
 
        

Now, when I say best match what does that mean ? If one file is not present , then the next one gets precedence. So in this you might have noticed the 3rd match. Yes , you read it right, I said sling:resourceSuperType . Why ? Before SLING fallback on finding the default script (GET.html / POST.html) , it gives a last try to see if there is any file which it can pull from an inherited component. And how ? that's what sling:resourceSuperType does. Treat it like a parent component to your component. If any script is not present in your component , and it has a sling:resourceSuperType , then SLING will go and take a look at that component in a similar manner to find if any script can be resolved to render content. Read the same here in this JIRA ticket for SLING issues.

As per the above JIRA ticket

Add support to the Servlet Resolver to resolve scripts not just for the resource type but also
for the super type (if defined). This super type resolution takes place before falling back
default scripts !

  • That said, since the page component we are looking at doesn't have a best match neither 1 or 2 , the next option I will look for is , if it has a property called sling:resourceSuperType

Yes it has. So now we have to take a detour to our parent , which is core/wcm/components/page/v2/page

( I know you might be tired walking this long path ?? but guess what , that is the exact route SLING takes each time we send a request to our AEM publish. This is just a starter ??. We are yet in the process of finding the page rendering script.But for SLING, under one page there might be a lot of components and it take the exact same steps for each of those resource. )

Now when I go to /apps/core/wcm/components/page/v2/page and follow the exact same Sling Resolution Principles , I know that the first file/script which is going to execute will be the page.html

  • Now listen to me carefully, there are some simple rules we need to keep in mind from here . Always remember we are right now in a PARENT* component, and we reached here because we were doing sling resolution for a CHILD* component. So whenever you see an include in a script in a PARENT component, then SLING will first go to the CHILD component, check if the file is there.

( disclaimer :- PARENT and CHILD are my way of identifying these components to avoid confusion)

Let me make this little more understandable , let us open the page.html from /apps/core/wcm/components/page/v2/page and try to trace the path which we think SLING will be following. Let us open page.html . I have marked few lines from that file


  1. Include for head.html , SLING will first check /apps/wknd/components/structure/page if it has the file . Since it doesn't will render it from the parent /apps/core/wcm/components/page/v2/page . Same goes for the includes inside each file.

Same goes for all the files marked till 7

Now let us see what will happen when footer.html is rendered in line 28 ( marked 6) . Lets open the footer.html

The highlighted section is where I want to take your attention to. You can see a file include there right ? SLING has to include the contents of customfooterlibs.html at this location. From where will the contents be fetched .

We have one under /apps/core/wcm/page/v2/page ( Our PARENT)




We have a same name file under /apps/wknd/components/structure/page ( Our CHILD)

Which file do you think will be executed ??? Think for a moment .

Did you say CHILD !? ??exactly !!! ... Why ? Because when SLING sees a script include in a file in the PARENT , it first go to the CHILD, look for a same-name file , if it finds, it will be executed, else it will come back and look it under PARENT. Same with PARENT too, if it finds the same-name file/script under PARENT, it will be executed. If it doesn't find it in any of those place , it will throw error ( unless there is another sling:resourceSuperType on PARENT .. Nope.. I am not even gonna take that route now ????)

I will leave the rest of the SLING resolution for this component with you guys . If you have understood what I was trying to explain till now, then rest will be a piece of cake for you ???. Even still you are confused , drop a comment or send me a message , I will try to explain it to the best of my knowledge.

I hope I didn't confuse much but was able to convey the concept properly if not completely.

Uff ??. This was a real long one than I expected. I guess I need some coffee now..

Oh yeah, please let me know of any corrections or suggestions. I am all ears for you ??


Edit 1 :- Added the link to understand how exactly the jcr:content is resolved to render the page . Read it here https://cqdump.wordpress.com/2019/01/07/how-does-sling-resolve-an-aem-page-to-the-correct-resource-type/ .

As I have told prior I am no expert , all the articles are purely my understanding of the topic. So please correct me if any one see anything wrong or missing in these articles. I surely don't want to send wrong information out there.

Awesome, thx a lot for such a detailed explanation!

要查看或添加评论,请登录

社区洞察

其他会员也浏览了