Contents
CQ5 is built using Sling, a Web application framework based on REST principles that provides easy development of content-oriented applications. Sling uses a JCR repository, such as Apache Jackrabbit, or Day's CRX, as its data store.
Sling started as an internal project of Day Management AG and is included in the installation of CQ5. Sling has since been contributed to the Apache Software Foundation - further information can be found at Apache.
Using Sling, the type of content to be rendered is not the first processing consideration. Instead the main consideration is whether the URL resolves to a content object for which a script can then be found to perform the rendering. This provides excellent support for web content authors to build pages which are easily customized to their requirements.
The advantages of this flexibility are apparent in applications with a wide range of different content elements, or when you need pages that can be easily customized. In particular, when implementing a Web Content Management system such as CQ WCM.
Sling is content-centric. This means that processing is focused on the content as each (HTTP) request is mapped onto content in the form of a JCR resource (a repository node):
the first target is the resource (JCR node) holding the content
secondly, the representation, or script, is located from the resource properties in combination with certain parts of the request (e.g. selectors and/or the extension)
Due to the content-centric philosophy, Sling implements a REST-oriented server and thus features a new concept in web application frameworks. The advantages are:
very RESTful; resources and representations are correctly modelled inside the server
removes one or more data models
previously the following were needed: URL structure, business objects, DB schema;
this is now reduced to: URL = resource = JCR structure
In Sling, and therefore also CQ5, processing is driven by the URL of the user request. This defines the content to be displayed by the appropriate scripts. To do this, information is extracted from the URL.
If we analyze the following URL:
http://myhost/tools/spy.printable.a4.html/a/b?x=12
We can break it down into its composite parts:
Table 1. URL Decomposition
| protocol | host | content path | selector(s) | extension | suffix | param(s) | ||
|---|---|---|---|---|---|---|---|---|
http:// | myhost | tools/spy | .printable.a4. | html | / | a/b | ? | x=12 |
- protocol
HTTP.
- host
Name of the website.
- content path
Path specifying the content to be rendered. Is used in combination with the extension; in this example they translate to
tools/spy.html.- selector(s)
Used for alternative methods of rendering the content; in this example a printer-friendly version in A4 format.
- extension
Content format; also specifies the script to be used for rendering.
- suffix
Can be used to specify additional information.
- param(s)
Any parameters required for dynamic content.
Using these principles:
the mapping uses the content path extracted from the request to locate the resource
when the appropriate resource is located, the sling resource type is extracted, and used to locate the script to be used for rendering the content
The figure below illustrates the mechanism used, which will be discussed in more detail in the following sections.
Therefore:
DO NOT specify which data entities to access in your scripts (as an SQL statement in a PHP script would do)
DO specify which script renders a certain entity (by setting the
sling:resourceTypeproperty in the JCR node)
The request is broken down and the necessary information extracted. The repository is searched for the requested resource (content node):
first Sling checks whether a node exists at the location specified in the request; e.g.
../content/corporate/jobs/developer.htmlif no node is found, the extension is dropped and the search repeated; e.g.
../content/corporate/jobs/developerif no node is found then Sling will return the http code 404 (Not Found).
![]() | Note |
|---|---|
Sling also allows things other than JCR nodes to be resources, but this is an advanced feature. |
When the appropriate resource (content node) is located, the sling resource type is extracted. This is a path, which locates the script to be used for rendering the content.
The path specified by the
sling:resourceType can be either:
absolute
relative, to a configuration parameter
![[Note]](../resources/note.png)
Note Relative paths are recommended by Day as they increase portability.
All Sling scripts are stored in subfolders of either
/apps or /libs, which will be searched in this
order.
A few other points to note are:
when the Method (GET, POST) is required, it will be specified in uppercase as according to the HTTP specification e.g. jobs.POST.esp (see below)
various script engines are supported:
.esp, .ecma: ECMAScript (JavaScript) Pages (server-side execution).jsp: Java Server Pages (server-side execution).java: Java Servlet Compiler (server-side execution).jst: JavaScript templates (client-side execution).js: ECMAScript / JavaScript (client-side execution)
The list of script engines supported by the given instance of
CQ are listed on the Felix Management Console
(http://localhost:4502/system/console/scriptengines
).
Additionally, Apache Sling supports integration with other popular scripting engines (e.g., Groovy, JRuby, Freemarker), and provides a way of integrating new scripting engines.
Using the above example, if the
sling:resourceType is hr/jobs then
for:
GET/HEAD requests, and URLs ending in .html (default request types, default format)
The script will be
/apps/hr/jobs/jobs.esp; the last section of thesling:resourceTypeforms the file name.POST requests (all request types excluding GET/HEAD, the method name must be uppercase)
POST will be used in the script name.
The script will be
/apps/hr/jobs/POST.esp.URLs in other formats, not ending with .html
For example
../content/corporate/jobs/developer.pdfThe script will be
/apps/hr/jobs/jobs.pdf.esp; the suffix is added to the script name.URLs with selectors
Selectors can be used to display the same content in an alternative format. For example a printer friendly version, an rss feed or a summary.
If we look at a printer friendly version where the selector could be print; as in
../content/corporate/jobs/developer.print.htmlThe script will be
/apps/hr/jobs/jobs.print.esp; the selector is added to the script name.If no
sling:resourceTypehas been defined then:the content path will be used to search for an appropriate script (if the path based ResourceTypeProvider is active).
For example, the script for
../content/corporate/jobs/developer.htmlwould generate a search in/apps/content/corporate/jobs/.the primary node type will be used.
If no script is found at all then the default script will be used.
The default rendition is currently supported as plain text (.txt), HTML (.html) and JSON (.json), all of which will list the node's properties (suitably formatted). The default rendition for the extension
.res, or requests without a request extension, is to spool the resource (where possible).For http error handling (codes 404 or 500) Sling will look for a script at
/libs/sling/servlet/errorhandler/404.esp, or500.esp, respectively.
If multiple scripts apply for a given request, the script with the best match is selected. The more specific a match is, the better it is; in other words, the more selector matches the better, regardless of any request extension or method name match.
For example, consider a request to access the resource
/content/corporate/jobs/developer.print.a4.html of type
sling:resourceType="hr/jobs". Assuming we
have the following list of scripts in the correct location:
jobs.esp
jobs.GET.esp
jobs.GET.html.esp
jobs.html.esp
jobs.print.esp
jobs.print.a4.esp
jobs.print.html.esp
jobs.print.GET.html.esp
jobs.print.a4.html.esp
jobs.print.a4.GET.html.esp
Then the order of preference would be (10) - (9) - (6) - (8) - (7) - (5) - (3) - (4) - (2) - (1).
![]() | Note |
|---|---|
(6) is a better match than (8), because it matches more selectors even though (8) has a method name and extension match where (6) does not. |
In addition to the resource types (primarily defined by the
sling:resourceType property) there is also
the resource super type. This is generally indicated by the
sling:resourceSuperType property. These super
types are also considered when trying to find a script. The
advantage of resource super types is that they may form a hierarchy
of resources where the default resource type
sling/servlet/default (used by the default
servlets) is effectively the root.
The resource super type of a resource may be defined in two ways:
by the
sling:resourceSuperTypeproperty of the resource.by the
sling:resourceSuperTypeproperty of the node to which thesling:resourceTypepoints.For example:
/
a
b
sling:resourceSuperType = a
c
sling:resourceSuperType = b
x
sling:resourceType = c
y
sling:resourceType = c
sling:resourceSuperType = a
The type hierarchy of
/xis[ c, b, a, <default> ]while for/ythe hierarchy is[ c, a, <default> ]because/yhas theslingresourceSuperTypeproperty whereas/xdoes not and therefore its supertype is taken from its resource type.
Within Sling, scripts cannot be called directly as this would break the strict concept of a REST server; you would mix resources and representations.
If you call the representation (the script) directly you hide the resource inside your script, so the framework (Sling) no longer knows about it. Thus you lose certain features:
automatic handling of http methods other than GET, including:
POST, PUT, DELETE which are handled with a sling default implementation
the POST.js script in your sling:resourceType location
your code architecture is no longer as clean nor as clearly structured as it should be; of prime importance for large-scale development
A final consideration is the need to reference existing elements within the scripts.
More complex scripts (aggregating scripts) might need to access multiple resources (for example navigation, sidebar, footer, elements of a list) and do so by including the resource.
To do this you can use the
sling:include("/<
command. This will effectively include the definition of the
referenced resource, as in the following statement which references an
existing definition for rendering images:path>/<resource>")
%><sling:include resourceType="geometrixx/components/image/img"/><%
An introduction the first steps of developing with Sling (and
CRX) can be seen on http://dev.day.com/.
