JCR is a hierarchy, tree-structured content repository. JCR has nodes and properties. Nodes are like folders. They have a name, type, and contain
JCR & Sling
What is the JCR
JCR is a hierarchy, tree-structured content repository.
Nodes and properties
JCR has nodes and properties.
- Nodes are like folders. They have a name, type, and contain child nodes and properties.
- Properties are key-value pairs attached to a node. Values can be strings, numbers, dates, booleans, or binary data.
- Pages:
cq:Pagenodes with ajcr:contentchild. - Page content lives under
jcr:content- this is where properties likejcr:titleare stored. - Components on a page are child nodes under the
jcr:contenttree. sling:resourceTypetells Sling which component will render this node.
Node types
Nodes can also have mixin types to add extra capabilities.
CRXDE basics
Edit content and explore items:
/content/mysite/en- your site's English root page/apps/mysite/components- your project's component definitions/libs/core/wcm/components- AEM Core Components source/conf/mysite/settings/wcm/templates- your editable templates
Apache Sling - the web framework
Sling is a web framework that sits between HTTP and JCR. Its main job: resolve URLs to JCR structures, then render them.
Sling request processing pipeline
When a request like GET /content/mysite/en/about.html arrives:
- Resource resolution - Sling parses the URL and finds the JCR node at
/content/mysite/en/about. - Script selection - Sling reads the
sling:resourceTypeproperty (e.g.,mysite/components/page) and finds the corresponding rendering script. - Rendering - The HTL template (or servlet) renders the content.
- Response - The rendered HTML is returned.
URL decomposition
Sling splits URLs into parts:
[Image unavailable: image-2.png]
Selectors are powerful - they let you render the same content in multiple ways without creating new endpoints:
/about.html- default rendering/about.article.html- article rendering/about.json- JSON output/about.xml- XML output
Resource Resolution in detail
Resource resolution is how Sling finds the correct JCR node for a URL.
The sling:resourceType property on a node points to a component definition. Sling searches for rendering scripts in the following order:
/apps/<resourceType>/<scriptName>.html- your project's override/libs/<resourceType>/<scriptName>.html- AEM's default
This is the overlay mechanism - you can override any AEM component by placing your version in /apps.
A component can also declare a sling:resourceSuperType property pointing to a parent component. When Sling cannot find a script in the current component, it walks up the super-type chain and uses the parent component's script.
This is how proxy components work - a component in your project inherits all rendering from a Core Component and only overrides what is needed:
Script selection rules
For a resource with sling:resourceType = "mysite/components/text", Sling looks for scripts in /apps/mysite/components/text/:
Script naming conventions: <component>.<selector>.<extension>.html or the shorthand <extension>.html.
For a resource with sling:resourceType = "mysite/components/text", Sling's Script Resolution / Script Selection mechanism is actually more complex and depends on multiple request factors, not just the extension.
1. Factors Sling uses to select a script
Sling determines the script based on:
- Resource Type (
mysite/components/text) - HTTP Method (GET, POST, PUT, DELETE…)
- Selectors (e.g.,
.article,.print) - Extension (
.html,.json,.xml…) - Suffix (does not directly affect script selection)
- Resource Super Type chain
- Search Path (
/apps→/libs)
2. Script lookup order (highest → lowest priority)
Sling searches for scripts in a specific → more general order:
Example request:
Lookup order:
If not found, fall through to:
If still not found, continue following sling:resourceSuperType.
3. Full naming rules
Full format:
Common formats:
4. Specific request mappings
4.1 GET.html
Lookup:
4.2 GET with selectors
Lookup:
4.3 Multiple selectors
Lookup:
4.4 GET.json
Lookup:
If not found, fallback to:
- Sling Default GET Servlet (renders JSON from JCR)
4.5 POST
Lookup:
If not found, fallback to:
- Sling POST Servlet
5. Super Type chain
If not found in the current component:
Sling continues looking up using the same rules in the parent component.
6. Search Path (overlay)
Order:
→ /apps overrides /libs
7. Key principles summary
-
Sling always prioritizes:
- More specific (more selectors)
- Correct HTTP method
- Correct extension
- Current component first
- Then super type
- Finally
/libs
-
Scripts can be written as:
- Component-specific (
text.html) - Generic (
html.html)
- Component-specific (
-
Selector resolution is a progressive fallback.
8. Practical example
Request:
Sling tries:
/apps/mysite/components/text/text.article.html/apps/mysite/components/text/article.html/apps/mysite/components/text/text.html/libs/…resourceSuperType- Default servlet
Resources and the Resource API
In Sling, everything is a Resource. A Resource is a Java abstraction of a JCR node.
Key interfaces:
Adaptable pattern
Sling extensively uses the Adaptable design pattern - you convert (adapt) one object to another:
This pattern is central to AEM development. Sling Models (chapter 7) are the primary way to adapt resources into custom Java objects.
Content paths and conventions
AEM has strong conventions for where content is stored:
Code paths (immutable in AEMaaCS)
Content paths (mutable)
System paths
Rule: Never modify /libs. Always overlay or extend in /apps. In AEMaaCS, /libs is read-only.
Querying the JCR
Beyond traversing the tree, you can query it. AEM supports two query languages:
QueryBuilder
AEM's query API - used in Java code and HTTP:
In Java (e.g., inside a Sling Model), use the QueryBuilder service:
JCR-SQL2
SQL-like syntax for JCR queries:
Note: The syntax page.[jcr:content/jcr:title] is not valid in JCR-SQL2. To query properties on child nodes, you must use INNER JOIN with ISCHILDNODE() as shown above.
You can run queries using the query tool in CRXDE Lite (bottom panel) or the QueryBuilder Debugger at http://localhost:4502/libs/cq/search/content/querydebug.html.
Queries without proper indexes will be slow and can block the repository. Always test query performance and create Oak indexes for production queries. See the JCR references for details.