Apache Sling is a content-centric web application framework:
- Built around RESTful principles, embraces the web
- Uses JCR for content storage — or other data sources via Resource Providers
- Supports Scripts (JSR 223) or Servlets for processing
- Highly modular and based on OSGi
- Healthy community: >30 Committers (mostly from Adobe and other companies)
- >300 modules on GitHub
Started as internal project at Day Software, Apache Incubator project since 2007, top-level project since 2009.
REST stands for "REpresentational State Transfer" — an architectural style for distributed systems defined in 2000 by Roy Fielding.
- A Resource can be anything (but has to be addressable)
- Resources are independent from their representation — a web page is not a resource, it's a representation of one
- An URL identifies a resource — URLs have an implicit hierarchy
- Methods perform operations on resources (GET, POST, PUT, DELETE…) — operation is not part of the URL
- HTTP status codes indicate result success
Benefits: Performance, Scalability, Simplicity, Modifiability, Cacheability.
Un-RESTful URL in "traditional" apps:
/schedule.jsp?event=1&year=2015&id=1&format=JSON
RESTful URLs in Sling:
/conference/2015/day1/rookie-session.json /conference/2015/day1/rookie-session.xml
URL addresses a Resource, not a script. Representation selection via extension.
# Create a node at /content/mynode with two properties
curl -u admin:admin
-F"sling:resourceType=matrix/sentinel"
-F"title=Sentinel Outpost"
http://localhost:8080/content/mynode
# This HTTP POST is intercepted by the default Sling POST Servlet.
# Authentication required to get write access.
// HTTP GET with JSON extension:
// http://localhost:8080/content/mynode.json
{
"jcr:primaryType": "sling:Folder",
"jcr:createdBy": "admin",
"jcr:created": "Thu Nov 26 2015 11:22:39 GMT+0100",
"title": "Sentinel Outpost",
"sling:resourceType": "matrix/sentinel"
}
// Node type automatically chosen by Sling
// Alternative in XML: http://localhost:8080/content/mynode.xml
# HTTP POST: Create two folders
curl -u admin:admin -F"jcr:primaryType=sling:Folder" http://localhost:8080/apps/matrix
curl -u admin:admin -F"jcr:primaryType=sling:Folder" http://localhost:8080/apps/matrix/sentinel
# HTTP PUT: Upload the script
curl -u admin:admin -T sentinel.html http://localhost:8080/apps/matrix/sentinel/sentinel.html
# Content of sentinel.html (HTL):
# <h1>Hello World!</h1>
# <p>${properties.title}</p>
# Now GET http://localhost:8080/content/mynode.html
# Sling detects the script via script resolution and renders it
Resources are typed. A "content" resource has a sling:resourceType property pointing to the Sling component containing script(s) to render the resource.
- Resource type is a repository path (can be relative to script search paths)
- Resource type is optional if the resource is just used for storage
- Sling components are resources as well — containing scripts rather than content
- With
sling:resourceSuperTypeyou can build hierarchies of resource types for generalization in script resolution
A resource provider maps the resource hierarchy to a storage system. Default: JCR resource provider.
Multiple resource providers are mapped to the same resource tree. There is no concept for multiple workspaces or repositories in Sling.
Example: Main resource provider is JCR with Jackrabbit Oak. On path /content/usergenerated a different resource provider is mounted — all read/writes there go to a different store, everything else goes to JCR.
If no custom script or servlet is in place, all GET requests are handled by the standard GET servlet:
.html/.xml/.txt— dump resource data as HTML, XML or plain text.json— dump resource data as JSON.<level>.json— include child resources (e.g..5.json= 5 levels,.infinity.json= all levels).tidy.<level>.json— formatted JSON output
Important: Configure in Felix console to switch off some/all of these features on production instances!
Supports writing data back to repository without custom code:
- Creating or updating resources — maps POST parameters to property names
- Control data types (Number, Boolean, Date)
- Delete, Move, Copy, Import, Checkin, Checkout content
All access to the repository is subject to access restrictions:
- Sling Launchpad: Read access to all resources, write access to none
- If more access is needed, the user must authenticate with credentials authorized with proper access rights
- JCR allows very fine-grained control of access rights on path level
- All default servlets, custom scripts/servlets, and every access via the Sling API respects the ACLs
Sling provides support for initial content to be deployed with bundles, installed when the bundle is started. Declared with the Sling-Initial-Content bundle header.
- Files & Folders: directly mapped to nt:folder and nt:file nodes in JCR
- XML: XML file containing JCR data structures
- JSON: JSON file containing JCR data structures (best option — XML has problems with multi-valued properties)
<plugin>
<groupId>biz.aQute.bnd</groupId>
<artifactId>bnd-maven-plugin</artifactId>
<configuration>
<bnd>
<!-- include application path as initial content -->
Sling-Initial-Content:
SLING-INF/app-root;overwrite:=true;ignoreImportProviders:=xml;path:=/apps/myapp
</bnd>
</configuration>
</plugin>
<!-- Imports content from SLING-INF/app-root in the JAR to /apps/myapp -->
Additionally to the REST interfaces, Sling provides a Java API used by OSGi components and scripts on the server-side:
- The Sling API extends the Servlet API to provide Sling-specific and resource-related features (e.g. URL decomposition)
- The Sling Resource API provides read/write operations to manage the resource hierarchy, transparent from the underlying resource providers
- Entry points for customizing resource handling, authentication, security and helper functions
Sling takes a unique approach: a request URL is first resolved to a resource, then based on the resource it selects the servlet or script to handle the request.
The request handling can be further customized by:
- Applying servlet filters
- Applying Sling Mapping for "SEO-friendly short URLs"
- Using the "Recent Requests" Felix Web Console plugin to debug request processing
Sling uses a very thin launcher to run Sling and OSGi: the Launchpad. May be launched as a standalone application or as a Web Application (WAR).
Created using the Sling Feature Model — a collection of OSGi Bundle references and configurations. Makes it easy to build own application starters with all required bundles and configuration flexibility.