ResourceResolver

The entry point for any resource access is the ResourceResolver. How to get one:

  • getResourceResolver() on a SlingHttpServletRequest (Sling automatically creates one per request)
  • getResourceResolver() on any Resource instance
  • Inject via @SlingObject in a Sling Model
  • In an OSGi background service: create via ResourceResolverFactory

Important: A resource resolver is not thread-safe. Never share across threads. Always properly close if you created it yourself. Keep lifetime as short as possible.

Getting Resources

Main method: getResource(path)

  • Absolute path used directly
  • Relative path: configured search paths (/apps, /libs) are prepended
  • Returns a valid Resource or null if not found (no way to distinguish "not found" from "no access")

Alternative: getResource(baseResource, path) — relative to a base resource.

Also: resolve(path) — resolves an external URL to a resource. Normally you should never use this (resolving already happened when Sling accepted the request).

Navigating the Resource Hierarchy

  • getChildren() — returns Iterable<Resource> (usable in for-each)
  • listChildren() — returns Iterator<Resource>
  • hasChildren() — check if children exist
  • getChild(path) — get specific child (direct or via relative path). Returns null if not found.
  • getParent() — returns null for root resource

Inspecting a Resource

  • getValueMap() — get properties (never returns null)
  • getPath() — full path
  • getName() — path part after last "/"
  • getResourceType() / isResourceType() — resource type (stored in sling:resourceType property)

Reading ValueMap Properties

A ValueMap is also a Map<String,Object>. Additionally provides typed access with automatic conversion:

  • get(name, Class<T> type) — returns null if not found or can't convert
  • get(name, T defaultValue) — returns default value if not found. Default also defines the target type.

Always use these typed methods to get properties from a ValueMap.

Querying for Resources

Two methods:

  • findResources(query, lang) — returns Iterator<Resource>
  • queryResources(query, lang) — returns Iterator<Map<String,Object>> (for non-resource results mapped to rows/columns)

This API does not provide a query abstraction — the query language depends on the underlying resource provider(s). The underlying JCR API provides more control (e.g. limiting results, setting query parameters).

CRUD on Resources

// Create a resource
Map<String, Object> props = new HashMap<>();
props.put("prop1", "abc");
props.put("prop2", 25);
Resource matrixNode = resourceResolver.create(parentResource, "resource1", props);
resourceResolver.commit();

// Update a resource
Resource matrixNode = resourceResolver.getResource("/content/resource1");
ModifiableValueMap mvp = matrixNode.adaptTo(ModifiableValueMap.class);
mvp.put("prop1", "def");
mvp.put("prop2", 33);
resourceResolver.commit();

// Delete a resource
Resource matrixNode = resourceResolver.getResource("/content/resource1");
resourceResolver.delete(matrixNode);
resourceResolver.commit();

Transaction Handling

ResourceResolver uses implicit transaction handling (started automatically):

  • commit() — permanently save pending changes
  • revert() — revert all changes
  • hasChanges() — check if unsaved changes exist

Decorating and Providing Resources

Sling supports advanced resource features:

  • ResourceDecorator OSGi service — decorate (e.g. manipulate metadata/properties) all resources before serving them
  • ResourceWrapper — overlay methods with other behavior
  • ResourceProvider OSGi service — provide additional resources in a virtual resource tree from another data source (e.g. Sling NoSQL resource providers). Can be combined with JCR resource provider.
  • ResourceUtil — useful utility methods
  • SyntheticResource — create virtual resources on-the-fly

The adaptTo() Concept

adaptTo() allows to "get a view of the same object in terms of another class". Content is kept encapsulated, functionality is abstracted from content, classes are not constrained by inheritance hierarchy.

This is used everywhere in Sling — it's the backbone of Sling Models where adaptTo() creates model instances from a context object.

Adapter Examples

Resource adapts to:

  • JCR Node — if JCR-node-based
  • ValueMap — to get properties
  • ModifiableValueMap — to write properties
  • InputStream — binary content of file resource (nt:file/nt:resource)
  • Any Sling Model adapting from Resource

ResourceResolver adapts to:

  • JCR Session — if JCR-based
  • Any Sling Model adapting from ResourceResolver

New adaptions can be added dynamically at runtime through OSGi bundles. Usually you use Sling Models for this (generates AdapterFactory internally).

Sling Request API

SlingHttpServletRequest:

  • getResourceResolver() — resource resolver for this request
  • getResource() — current resource addressed in the URL
  • getRequestPathInfo() — URL decomposition information
  • getRequestDispatcher(…) — include/forward another resource
  • getRequestProgressTracker() — write to request progress log
  • adaptTo(…) — adapt to another class

RequestPathInfo

  • getResourcePath() — "resource path" part of URL (before selectors, extension, suffix)
  • getExtension() — extension or null
  • getSelectorString() — selectors as string (dot-separated) or null
  • getSelectors() — selectors as array (split on dots) or empty array
  • getSuffix() — suffix part or null

SlingRequestDispatcher

Sling-specific RequestDispatcher that accepts RequestDispatcherOptions:

  • forward() — server-side redirect, control handed to another resource
  • include() — server-side include, output included in response

Options allow: forcing a different resource type, adding/replacing selectors, replacing suffix. Most times you won't use this directly — use HTL/JSP resource include mechanisms instead.

Namespace Mangling

Paths in Sling often contain colons (used for JCR namespacing). Some systems don't handle colons in URL paths properly. Sling applies Namespace Mangling:

  • Encloses namespace prefix in underscores and removes the colon
  • Only registered JCR namespaces are processed
  • Mangling in map() methods (outgoing), unmangling in resolve() (incoming)

Example: /content/_a_sample/jcr:content/jcr:data.png/content/_a_sample/_jcr_content/_jcr_data.png