Sling offers an Adapter pattern to conveniently translate objects that implement the Adaptable interface. This interface provides a generic adaptTo() method that translates the object to the class type being passed as the argument.
For example, to translate a Resource object to the corresponding Node object, you can simply do:
Node node = resource.adaptTo(Node.class);
There are the following use cases:
Get implementation-specific objects.
Shortcut creation of objects that require internal context objects to be passed.
For example, the JCR-based
ResourceResolver holds a reference to the request’s
JCR Session, which in turn is needed for many objects that will work based on that request session, such as the
Shortcut to services.
A rare case -
sling.getService() is simple as well.
adaptTo() returns null.
There are various reasons for this, including:
It is important that you handle the null case gracefully. For jsp renderings it might be acceptable to have the jsp fail if that will result in an empty piece of content.
To improve performance, implementations are free to cache the object returned from a
obj.adaptTo() call. If the
obj is the same, the returned object is the same.
This caching is performed for all
AdapterFactory based cases.
However, there is no general rule - the object could be either a new instance or an existing one. This means that you cannot rely on either behavior. Hence it is important, especially inside
AdapterFactory, that objects are reusable in this scenario.
There are various ways that
Adaptable.adaptTo() can be implemented:
By the object itself; implementing the method itself and mapping to certain objects.
AdapterFactory, which can map arbitrary objects.
The objects must still implement the
Adaptable interface and must extend
SlingAdaptable (which passes the
adaptTo call to a central adapter manager).
This allows hooks into the
adaptTo mechanism for existing classes, such as
A combination of both.
For the first case, the Java™ docs can state what
adaptTo-targets are possible. However, for specific subclasses such as the JCR-based Resource, often this is not possible. In the latter case, implementations of
AdapterFactory are typically part of the private classes of a bundle and thus not exposed in a client API, nor listed in Java™ docs. Theoretically, it would be possible to access all
AdapterFactory implementations from the OSGi service runtime and look at their “adaptables” (sources and targets) configurations, but not to map them to each other. In the end, this depends on the internal logic, which must be documented. Hence this reference.
Resource adapts to:
|Node||If this is a JCR-node-based resource or a JCR property referencing a node.|
|Property||If this is a JCR-property-based resource|
|Item||If this is a JCR-based resource (node or property)|
|Map||Returns a map of the properties, if this is a JCR-node-based resource (or other resource supporting value maps)|
|ValueMap||Returns a convenient-to-use map of the properties, if this is a JCR-node-based resource (or other resource supporting value maps). Can also be achieved (more simply) by using
|InheritanceValueMap||Extension of ValueMap which allows the hierarchy of resources to be taken into account when looking for properties|
|ModifiableValueMap||An extension of the ValueMap, which lets you modify properties on that node|
|InputStream||Returns the binary content of a file resource (if this is a JCR-node-based resource and the node type is
|URL||Returns a URL to the resource (repository URL of this node if this is a JCR-node-based resource; jar bundle URL if this is a bundle resource; file URL if this is a file system resource)|
|File||If this is a file system resource|
|SlingScript||If this resource is a script (for example, jsp file) for which a script engine is registered with sling|
|Servlet||If this resource is a script (for example, jsp file) for which a script engine is registered with sling or if this is a servlet resource.|
|Returns the values if this is a JCR-property-based resource (and the value fits).|
|LabeledResource||If this is a JCR-node-based resource|
|Page||If this is a JCR-node-based resource and the node is a
|Component||If this is a
|Design||If this is a design node (
|Template||If this is a
|Blueprint||If this is a
|Asset||If this is a dam:Asset node resource|
|Rendition||If this is a dam:Asset rendition (nt:file under the rendition folder of a dam:Assert)|
|Tag||If this is a
|UserManager||Based on the JCR session if this is a JCR-based resource and the user has permissions to access the UserManager|
|Authorizable||The Authorizable is the common base interface for User and Group|
|User||User is a special Authorizable that can be authenticated and impersonated|
|SimpleSearch||Searches below the resource (or use setSearchIn()) if this is a JCR-based resource|
|WorkflowStatus||Workflow status for the given page/workflow payload node|
|ReplicationStatus||Replication status for the given resource or its jcr:content subnode (checked first)|
|ConnectorResource||Returns an adapted connector resource for certain types, if this is a JCR-node-based resource|
|Config||If this is a
|ConfigEntry||If this is below a
ResourceResolver adapts to:
|Session||The request's JCR session, if this is a JCR-based resource resolver (default)|
|AssetManager||Based on the JCR session, if this is a JCR-based resource resolver|
|TagManager||Based on the JCR session, if this is a JCR-based resource resolver|
|UserManager||The UserManager provides access to and means to maintain authorizable objects that is, users and groups. The UserManager is bound to a particular Session|
|Authorizable||The current user|
||The current user|
|Externalizer||For externalizing absolute URLs, even without the request object
SlingHttpServletRequest adapts to:
No targets yet, but implements Adaptable and could be used as source in a custom AdapterFactory.
SlingHttpServletResponse adapts to:
|If this is a sling rewriter response|
Page adapts to:
||Resource of the page|
|LabeledResource||Labeled resource (== this)|
|Node||Node of the page|
|...||Everything that the page's resource can be adapted to|
Component adapts to:
|Resource||Resource of the component.|
|LabeledResource||Labeled resource (== this).|
|Node||Node of the component.|
|…||Everything that the component’s resource can be adapted to.|
Template adapts to:
||Resource of the template|
|LabeledResource||Labeled resource (== this)|
|Node||Node of this template|
|...||Everything that the template's resource can be adapted to.|
Authorizable, **User, and Group adapt to:
|Node||Returns the user/group home node.|
|ReplicationStatus||Returns the replication status for the user/group home node.|
Asset adapts to:
|Resource||Resource of the asset.|
|Node||Node of the asset.|
|…||Everything that the asset’s resource can be adapted to.|
Tag adapts to:
|Resource||Resource of the tag.|
|Node||Node of the tag.|
|…||Everything that the tag’s resource can be adapted to.|
Furthermore Sling / JCR / OCM also provides an
[AdapterFactory](https://sling.apache.org/site/adapters.html#Adapters-AdapterFactory) for custom OCM (Object Content Mapping) objects.