Core path ยท 3 of 34
Learn how Sling identifies and resolves components. Understand sling:resourceType, sling:resourceSuperType, component resolution, and script resolution. Discover why Core Component proxies reduce maintenance and improve project sustainability.
In this chapter, you'll master:
Imagine a request reaches Sling.
ResourceResolver successfully locates:
/content/company/us/en/home/jcr:content/root/title
Sling now has a Resource.
However, another important question still remains:
Key question:
The Resource contains content.
But content alone is not enough.
Sling still needs to determine:
The answer comes from one property: sling:resourceType
This property drives almost every rendering decision in AEM.

Let's look at a real example.
Repository:
/content/company/us/en/home/jcr:content/root/title
Properties:
jcr:title = "Welcome"
sling:resourceType = "company/components/title"
At this point, Sling has two different pieces of information.
The first is the content itself:
jcr:title = "Welcome"
The second is the instruction that tells Sling how that content should be rendered:
sling:resourceType = "company/components/title"
Think of it this way:
Without a resourceType, Sling would know what content exists, but it would not know which component should render that content.
This property tells Sling:
Resource = Data
resourceType = Renderer
Or:
Book = Content
resourceType = Reader
The content doesn't know how to display itself. The component does.
Here's how Sling maps resourceType to an actual component:
Content Resource
/content/company/us/en/home/jcr:content/root/title
โ
โโ sling:resourceType
โ company/components/title
โ
โโ Maps to
โ /apps/company/components/title
โ
โโ Contains script
โ title.html
โ
โโ Result
HTML Output
Breaking it down:
This is where people start understanding component resolution.
Suppose:
sling:resourceType = company/components/title
Sling searches:
/apps/company/components/title/title.html
When Sling reads:
sling:resourceType = company/components/title
it converts that value into a component path:
company/components/title
becomes:
/apps/company/components/title
Sling then searches that component folder for scripts that can handle the current request.
For a standard page request, Sling typically looks for:
title.html
If the script is found, rendering continues. If no matching script can be located, the component cannot render.
Situation:
Why?
Because:
resourceType points here: company/components/title
but /apps/company/components/title does not exist
This happens frequently after deployments.
The component code wasn't deployed to the server, or the deployment path is incorrect.
Imagine Sling resolves:
company/components/title
and locates:
/apps/company/components/title
However, the component folder may contain:
title.html
title.json
GET.java
POST.java
Which one should Sling execute?
Script Resolution takes over at this point.
Many developers assume Component Resolution and Script Resolution are the same thing.
They are actually two different stages in the Sling rendering process:
Understanding the difference makes it much easier to troubleshoot rendering issues and servlet execution problems.

Sling uses several factors to determine which script should handle the request:
Resource Type
+
HTTP Method
+
Selectors
+
Extension
Think of Script Resolution as a matching process.
Component Resolution already identified the component that should render the content.
Now Sling must decide which script inside that component should handle the request.
A component may contain:
title.html (for GET requests with .html extension)
title.model.json (for model.json exports)
TitleServlet.java (for custom servlet handling)
All of these belong to the same component, but they serve different request types.
Script Resolution is responsible for selecting the best match based on the incoming request.
Request:
/content/site/en/home.html
Sling sees:
Method = GET
Extension = html
Result: title.html gets executed
Request:
/content/site/en/home.model.json
Sling sees:
Selector = model
Extension = json
Result: JSON Exporter gets executed
This is exactly what AEM SPA Editor and Headless AEM use for content delivery.
Request:
/content/site/en/home.delete.html
Sling sees:
Selector = delete
Method = POST
Result: Delete Servlet may be executed
The complete decision process:
Request
โ
Resource Located
โ
sling:resourceType determined
โ
HTTP Method identified
โ
Selectors parsed
โ
Extension evaluated
โ
Best Matching Script Found
โ
Script Executed
A common production issue appears like this:
Developer creates a servlet:
@SlingServletResourceTypes(
resourceTypes="company/components/page",
selectors="export",
extensions="json"
)
public class PageExportServlet extends SlingSafeMethodsServlet {
// implementation
}
They test with request:
/home.json
Servlet never executes. Developer starts debugging code.
Why?
Because of a selector mismatch:
Expected: /home.export.json
Actual: /home.json
The servlet is configured to listen for the export selector, but the test request doesn't include it.
Many developers spend hours debugging code when the issue is actually script resolution.
When a servlet or script isn't being called:
@SlingServlet annotations for correct resourceTypes.export.json)Core Components solve this with inheritance.
Say you need a custom Title component:
company/components/customtitle
Instead of creating everything from scratch, you specify:
sling:resourceSuperType = core/wcm/components/title/v3/title
Now Sling says:
Use custom component first.
If something is missing, inherit from Core Component
This inheritance model is one of the reasons Core Components became so successful.
Bad approach:
1. Copy Core Component entirely
2. Modify code as needed
3. Deploy custom component
The Problem:
Adobe releases update to Core Component
โ
Your copied component never gets it
โ
You must manually discover changes
โ
You must compare, merge, test
โ
Maintenance burden increases
Good approach: Proxy Component
1. Create minimal proxy component
2. Set sling:resourceSuperType = Core Component
3. Override only what you need
4. Deploy proxy
The Benefit:
Adobe releases update to Core Component
โ
Your proxy automatically inherits the update
โ
You only maintain your customizations
โ
Maintenance burden decreases significantly

Many enterprise projects contain:
/apps/company/components/title
but almost no HTL code.
Why?
Because:
sling:resourceSuperType
does most of the work.
This surprises many developers the first time they see it.
The proxy component is just a pointer to the Core Component, with minimal overrides for project-specific customizations.

Your Component
โโ HTL (copied from Core)
โโ Sling Models (copied from Core)
โโ CSS (copied from Core)
โโ Custom Modifications
โโ New HTL logic
โโ New Models
โโ New Styles
Problem: All Core updates must be manually applied
Your Component (Minimal)
โโ Proxy configuration
โโ Custom Modifications
โ โโ New HTL override
โ โโ New Model
โ โโ New Styles
โโ sling:resourceSuperType
โ
Core Component
โโ HTL (inherited)
โโ Sling Models (inherited)
โโ CSS (inherited)
Benefit: Core updates automatically inherited
At this point we can finally understand the complete rendering journey:

What initially appears to be a simple page request is actually a series of resolution steps working together.
Understanding this chain makes it significantly easier to troubleshoot rendering problems because you can identify exactly where the process breaks down.
When a component doesn't render, follow this checklist:
| Check | What to Verify |
|---|---|
| Resource exists | Did ResourceResolver find the content? |
| resourceType set | Does the resource have sling:resourceType? |
| Component path | Does /apps/{resourceType} exist? |
| Script exists | Does title.html (or equivalent) exist? |
| Script resolution | Do method/selector/extension match? |
| Super type chain | If using resourceSuperType, is chain valid? |
| Permissions | Does current user have access? |
| OSGi status | Are required bundles active? |
| Logs | Are there resolution errors in error.log? |
Most developers think:
resourceType = property
Architects think:
resourceType = rendering engine
Without resourceType:
โ No HTL rendering
โ No Sling Model adaptation
โ No Component loading
โ No Component rendering
โ Page breaks or shows error
Understanding resource types is often the moment when developers truly understand how Sling rendering works.
Architects rarely troubleshoot rendering problems by starting with HTL.
Instead, they follow the rendering chain:
Resource
โ
resourceType
โ
Component Resolution
โ
Script Resolution
โ
Sling Model
โ
HTL
โ
Response
The earlier a failure occurs in this chain, the less useful it becomes to investigate rendering code.
If Component Resolution fails, there's no point investigating HTL. If Script Resolution fails, there's no point investigating Sling Models.
In this chapter, we learned how Sling identifies and resolves components through resourceType, and how component inheritance reduces maintenance burden.
However, we haven't yet explored an important aspect of request handling:
Key question:
To answer that, we need to understand:
These concepts are critical for building flexible AEM components and APIs.
In the next chapter, we will explore how Sling dissects request paths and uses selectors, extensions, and suffixes to control rendering behavior.
Get an email when I publish the next chapter. No spam โ just new technical deep-dives.
Comments
Share feedback or questions about this blog post.
No comments yet. Be the first to share your thoughts.