Modifying Content: The SlingPostServlet
Work In Progress This page is work in progress to explain how the SlingPostServlet works after the refactoring as per SLING-422. Please also note, that the contents of this page reflects the status of the SlingPostServlet after implementing SLING-422 and does not yet reflect the updates implicated by SLING-394 and SLING-458 |
Multiple Ways to Modify Content
As always in life there is more than one way to do it. So to modify content in a JCR repository underlying Sling, you have multiple options, two of which are WebDAV and the Sling default POST Servlet also called the SlingPostServlet. This page is about how you can modify - create, modify, copy, move, delete - content through the SlingPostServlet. In addition it also explains how to extend the SlingPostServlet with new operations.
What is Content anyway ? In the following discussion, I use the terms Content and Item interchangeably. With Content I just mean some data to be stored in the JCR repository to be later used as the basis for some presentation. In this sense Content is a rather conceptual term. Item is the name of the parent interface of the JCR Node and Property interfaces. When speaking of Items we mean some actual data stored in the repository ignoring whether the data is actually stored as a Node with child nodes and properties or just a single Property.
Quickstart: Creating Content
To create content you simply send an HTTP request using the path of the node to store the content in and include the actual content as request parameters. So one possibility to do just that is by having an HTML Form like the following:
<form method="POST" action="http://host/some/new/content" > <input type="text" name="title" value="" /> <input type="text" name="text" value="" /> </form>
This simple form will set the title and text properties on a node at /some/new/content. If this node does not exist it is just created otherwise the existing content would be modified.
Similarly you can do this using the curl command line tool:
$ curl -Ftitle="some title text" -Ftext="some body text content" http://host/some/new/content
You might want to use a specific JCR node type for a newly created node. This is possibly by simply setting a jcr:primaryType property on the request, e.g.
$ curl -F"jcr:primaryType=nt:unstructured" -Ftitle="some title text" -Ftext="some body text content" http://host/some/new/content
Similary you may assing JCR mixin node types using the jcr:mixinTypes property and a Sling resource type using the sling:resourceType property. For example:
$ curl -F"sling:resourceType=sling:sample" -Ftitle="some title text" -Ftext="some body text content" http://host/some/new/content
SlingPostServlet Operations
The SlingPostServlet is actually just a frontend to the actual operations. To select the actual operation to execute, the :operation request parameter is used. Out of the box, the SlingPostServlet supports the following operations:
- property not set or empty – Create new content or modify existing content
- delete – Remove existing content
- move – Move existing content to a new location
- copy – Copy existing content to a new location
All these operations always operate on the resource of the request as returned by SlingHttpServletRequest.getResource(). Some operations require additional parameters to be set to operate completely.
Content Creation or Modification
The simplest and most common use case, probably, is content creation and modification. We already saw an example above in the quickstart section. In this section we elaborate more on the concrete stuff.
First, the request URL indicates the actual repository node to be handled. If the URL addresses an existing node, the request parameters just provide values for the properties to be set on the existing node.
If the resource of the request is a synthetic resource, e.g. NonExistingResource or StarResource, a new item is created. The path (including name) of the item to be created is derived from the resource path:
- If the resource path ends with a /* or / the name of the item is automatically created using a name creation algorithm taking into account various request parameters.
- Otherwise the resource path is used as the path and name of the new item.
In both cases the path may still include selectors and extensions, which are cut off the path before finding out, what to do.
To illustrate this algorithm, lets look at some examples:
Resource Path | Item path |
---|---|
/content/new | /content/new |
/content/new.html | /content/new |
/content/new.print.a4.html | /content/new |
/content/ | /content/xxx where xxx is a generated name |
/content/* | /content/xxx where xxx is a generated name |
/content/*.html | /content/xxx where xxx is a generated name |
/content/*.print.a4.html | /content/xxx where xxx is a generated name |
TDB: How parameters are used to define content to be stored.
Response Status
The delete operation has the following status responses:
Status | Explanation |
---|---|
200/OK | An existing node has been updated with content |
201/CREATED | A new node has been created and filled with content |
500/INTERNAL SERVER ERROR | Some exception, for example a RepositoryException, occurred while processing the request |
Content Removal
To remove existing content just address the item to be removed and set the :operation parameter to delete. For example the following command line removes the /content/sample page:
$ curl -F":operation=delete" http://host/content/sample
Response Status
The delete operation has the following status responses:
Status | Explanation |
---|---|
200/OK | The resource (and all its descendents) has been removed |
404/NOT FOUND | The request URL does not address an existing repository item |
500/INTERNAL SERVER ERROR | Some exception, for example a RepositoryException, occurred while processing the request |
Copying Content
To copy existing content to a new location, the copy operation is specified. This operation copies the item addressed by the request URL to a new location indicated by the :dest parameter. The :dest parameter is the absolute or relative path to which the resource is copied. If the path is relative it is assumed to be below the same parent as the request resource. If it is terminated with a / character the request resource is copied to an item of the same name under the destination path.
To illustrate the :dest parameter handling, lets look at a few examples. All examples are based on addressing the /content/sample item:
:dest Parameter | Destination Absolute Path |
---|---|
/content/newSample | /content/newSample |
different/newSample | /content/different/newSample |
/content/different/ | /content/different/sample |
different/ | /content/different/sample |
If an item already exists at the location derived from the :dest parameter, the copy operation fails unless the :replace parameter is set to true (case is ignored when checking the parameter value).
Status | Explanation |
---|---|
200/OK | The node has been copied to the new location replacing an existing item at the destination |
201/CREATED | The node has been copied to the new location creating a new item at the destination |
412/PRECONDITION FAILED | An item already exists at the destination and the :replace parameter is not set to true |
500/INTERNAL SERVER ERROR | Some exception, for example a RepositoryException, occurred while processing the request |
Moving Content
To move existing content to a new location, the move operation is specified. This operation moves the item addressed by the request URL to a new location indicated by the :dest parameter. The :dest parameter is the absolute or relative path to which the resource is moved. If the path is relative it is assumed to be below the same parent as the request resource. If it is terminated with a / character the request resource is moved to an item of the same name under the destination path.
To illustrate the :dest parameter handling, lets look at a few examples. All examples are based on addressing the /content/sample item:
:dest Parameter | Destination Absolute Path |
---|---|
/content/newSample | /content/newSample |
different/newSample | /content/different/newSample |
/content/different/ | /content/different/sample |
different/ | /content/different/sample |
If an item already exists at the location derived from the :dest parameter, the move operation fails unless the :replace parameter is set to true (case is ignored when checking the parameter value).
Status | Explanation |
---|---|
200/OK | The node has been moved to the new location replacing an existing item at the destination |
201/CREATED | The node has been moved to the new location creating a new item at the destination |
412/PRECONDITION FAILED | An item already exists at the destination and the :replace parameter is not set to true |
500/INTERNAL SERVER ERROR | Some exception, for example a RepositoryException, occurred while processing the request |
Special Parameters
Some parameters have special significance for the complete processing of the SlingPostServlet or are used by multiple operations. This section summarizes these parameters:
:order
Child nodes may be ordered if the primary node type of their common parent node is defined as having orderable child nodes. To employ such ordering, the content creation/modification, move and copy operations support the :order parameter which apply child node ordering amongst its sibblings of the target node.
The :order parameter may have the following values:
Value | Description |
---|---|
first | Place the target node as the first amongst its sibblings |
last | Place the target node as the last amongst its sibblings |
before xyz | Place the target node immediately before the sibbling whose name is xyz |
after xyz | Place the target node immediately after the sibbling whose name is xyz |
numeric | Place the target node at the indicated numeric place amongst its sibblings where 0 is equivalent to first and 1 means the second place |
:redirect
Instructs the SlingPostServlet to redirect the client to the indicated location if the operation succeeds. That is the reponse status is set to 302/FOUND and the Location header is set to the value of the :redirect parameter.
:status
By default the SlingPostServlet sets response status according to the status of the operation executed. In some cases, it may be desirable to not have the real status codes (e.g. 404 or 505) but a normal 200/OK to trick the client browser into displaying the response content generated by the SlingPostServlet.
To not send the actual response status back to the client, the :status request parameter should be set to browser. If this parameter is not set, is empty, is set to standard or to any other value, the actual status code is sent back to the client.