Resource API in AEM
Okay, so now that we’ve got a good understanding of ResourceResolver, how we get it in services, servlets, and Sling Models, let’s talk about what we do once we have that resolver. The next logical step?
1. The Resource API
When you think about it, a ResourceResolver
is kind of useless by itself.
It’s like having the key to a house… but you still need to open the doors inside. That’s where Resource objects come in.
2. What is a Resource?
In AEM (thanks to Sling) a Resource
It’s just a wrapper around a JCR node.
But you don’t work directly with JCR nodes—you work with Resource
objects, which give you
- the path
- the type (what kind of component/content it is)
- the properties
- the children
Super useful because you don’t have to mess with low-level JCR APIs or Session
objects.
For example, let’s say I want to grab the /content/my-site/home
page
3. getResource(path)
Resource resource = resourceResolver.getResource("/content/my-site/home");
getResource(path) — resolves a request path (which might include selectors, extensions) to a resource
Useful when handling incoming requests instead of direct repository paths
Now resource
points to that page. Cool, right?
getResource(path) — resolves a request path (which might include selectors, extensions) to a resource
Useful when handling incoming requests instead of direct repository paths
Now resource
points to that page. Cool, right?
Okay, so what can we do with a Resource?
Once you’ve got a Resource
Here’s what you’ll probably do 99% of the time
4. Get properties
ValueMap properties = resource.getValueMap();
String title = properties.get("jcr:title", "Default Title");
Think of ValueMap
like a handy properties getter.
You ask for "jcr:title"
, and it returns whatever value is stored, or the default you provide.
5. Check what type of resource it is
if (resource.isResourceType("cq:Page")) {
log.info("Yes, this is a page!");
}
Very useful when looping through a page’s child nodes to filter out what you want.
6. Iterate over child resources
Iterator<Resource> children = resource.listChildren();
while (children.hasNext()) {
Resource child = children.next();
log.info("Found child at {}", child.getPath());
}
This is how you’d go through the child components or content under a page.
7. Adapt a resource to other types (Sling Models, JCR Node, etc.)
MyModel model = resource.adaptTo(MyModel.class);
Node node = resource.adaptTo(Node.class);
Super powerful because it lets you switch context depending on what you need.
Remember: adaptTo()
returns null
If adaptation isn’t possible, always check for null before using the result.
8. Resource Metadata
ResourceMetadata metadata = resource.getResourceMetadata();
gives info like resolution path, internal data
This is optional → mostly used in low-level resource resolution/debugging
9. Getting the parent resource
Let’s say you’re on /content/my-site/home
and wants its parent
Resource page = resourceResolver.getResource("/content/my-site/home");
Resource parent = page.getParent();
if (parent != null) {
log.info("Parent path: {}", parent.getPath());
}
Super useful if you’re navigating a page structure or need to go one level up.
10. Getting a specific child by name
If you know the name of the child you want (instead of looping):
Resource content = page.getChild("jcr:content");
if (content != null) {
log.info("Found child jcr:content at {}", content.getPath());
}
getChild()
is great for directly accessing a known child node.
11. Checking the resource super type
Sometimes a component inherits from another via sling:resourceSuperType
. You can check what it inherits from:
String superType = page.getResourceSuperType();
or
String parentType = resourceResolver.getParentResourceType(resource);
log.info("Super type: {}", superType);
If the resource doesn’t declare a sling:resourceSuperType
This will return null.
Tip: This is helpful if you’re working with component inheritance!
12. Extending Resource API
If you ever need to create a custom Resource implementation, Sling recommends extending AbstractResource
or ResourceWrapper
Instead of directly implementing the Resource
interface.
Why? Because these base classes already handle some of the default methods for you.
In practice, you’ll rarely need this unless you’re writing low-level Sling code or integrations.
13. Why use the Resource API instead of directly using JCR Session/Node?
Honestly, I used to think “why not just adapt to a JCR Node and work directly?” but
- Resource API takes care of a lot of boilerplate
- No need to manually close sessions
- Cleaner integration with Sling & AEM
In most Sling Models and Servlets, the Resource API is the way to go.
14. Real Example: Finding image components on a page
Let’s say you’ve got a page/content/my-site/home
, and you want to log all the image component file references on it.
Here’s how you’d do it
Resource page = resourceResolver.getResource("/content/my-site/home");
for (Resource child : page.getChildren()) {
if (child.isResourceType("myproject/components/image")) {
ValueMap props = child.getValueMap();
log.info("Image file reference: {}", props.get("fileReference", ""));
}
}
Simple, right?
We’re combining type-checking and property access.
15. Where you’ll use the Resource API (as a developer)
- In a Sling Servlet → getting the resource from a path param
- In a Sling Model → using the injected
@SlingObject Resource resource
- In a Workflow Process Step → traversing resources under a payload
- In backend services → querying resources
Anywhere you have a ResourceResolver
You’ll probably use the Resource API next.
16. Best Practices:
- Always check
resource != null
→getResource()
returnsnull
If the path doesn’t exist - Prefer
ValueMap
overadaptTo(Node.class)
for properties - Be careful when looping over children (not all nodes may be content nodes)
- Don’t use
resourceResolver.findResources()
querying unless you really need a query.
The upcoming blog will explore more with the Real Time Example in details.
Every great discussion starts with a simple thought! If you enjoyed this article, found it useful, or have any questions, let’s talk! I’d love to hear from you.
For more updates, tips, and engaging conversations, connect with me on Medium, LinkedIn, and RealCodeWorks. Let’s keep learning together! 🚀✨
Thank you 🙏 !