Return-Path: X-Original-To: apmail-sling-commits-archive@www.apache.org Delivered-To: apmail-sling-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id A719EC1E9 for ; Sun, 3 Jun 2012 17:58:30 +0000 (UTC) Received: (qmail 117 invoked by uid 500); 3 Jun 2012 17:58:30 -0000 Delivered-To: apmail-sling-commits-archive@sling.apache.org Received: (qmail 99981 invoked by uid 500); 3 Jun 2012 17:58:30 -0000 Mailing-List: contact commits-help@sling.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@sling.apache.org Delivered-To: mailing list commits@sling.apache.org Received: (qmail 99974 invoked by uid 99); 3 Jun 2012 17:58:30 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 03 Jun 2012 17:58:30 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 03 Jun 2012 17:58:19 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 8E7EF2388865; Sun, 3 Jun 2012 17:57:56 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1345726 [1/2] - in /sling/site/trunk/content/documentation: ./ bundles/ getting-started/ the-sling-engine/ the-sling-engine/authentication/ tutorials-how-tos/ Date: Sun, 03 Jun 2012 17:57:55 -0000 To: commits@sling.apache.org From: fmeschbe@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120603175756.8E7EF2388865@eris.apache.org> Author: fmeschbe Date: Sun Jun 3 17:57:55 2012 New Revision: 1345726 URL: http://svn.apache.org/viewvc?rev=1345726&view=rev Log: SLING-2002 Fix issues reported by Bertrand (thanks for reporting) Added: sling/site/trunk/content/documentation/bundles/2010-07-01_1036.png (with props) sling/site/trunk/content/documentation/the-sling-engine/url-to-script-resolution.mdtext Modified: sling/site/trunk/content/documentation/bundles/accessing-filesystem-resources-extensions-fsresource.mdtext sling/site/trunk/content/documentation/bundles/content-loading-jcr-contentloader.mdtext sling/site/trunk/content/documentation/bundles/manipulating-content-the-slingpostservlet-servlets-post.mdtext sling/site/trunk/content/documentation/getting-started/discover-sling-in-15-minutes.mdtext sling/site/trunk/content/documentation/the-sling-engine.mdtext sling/site/trunk/content/documentation/the-sling-engine/authentication.mdtext sling/site/trunk/content/documentation/the-sling-engine/authentication/authentication-authenticationhandler.mdtext sling/site/trunk/content/documentation/the-sling-engine/dispatching-requests.mdtext sling/site/trunk/content/documentation/the-sling-engine/request-parameters.mdtext sling/site/trunk/content/documentation/tutorials-how-tos/46-line-blog.mdtext sling/site/trunk/content/documentation/tutorials-how-tos/jackrabbit-persistence.mdtext Added: sling/site/trunk/content/documentation/bundles/2010-07-01_1036.png URL: http://svn.apache.org/viewvc/sling/site/trunk/content/documentation/bundles/2010-07-01_1036.png?rev=1345726&view=auto ============================================================================== Binary file - no diff available. Propchange: sling/site/trunk/content/documentation/bundles/2010-07-01_1036.png ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Modified: sling/site/trunk/content/documentation/bundles/accessing-filesystem-resources-extensions-fsresource.mdtext URL: http://svn.apache.org/viewvc/sling/site/trunk/content/documentation/bundles/accessing-filesystem-resources-extensions-fsresource.mdtext?rev=1345726&r1=1345725&r2=1345726&view=diff ============================================================================== --- sling/site/trunk/content/documentation/bundles/accessing-filesystem-resources-extensions-fsresource.mdtext (original) +++ sling/site/trunk/content/documentation/bundles/accessing-filesystem-resources-extensions-fsresource.mdtext Sun Jun 3 17:57:55 2012 @@ -33,5 +33,6 @@ The Filesystem Resource Provider is conf The following configuration properties must be specified: | Parameter | Name | Description | +|-|-|-| | Provider Root | `provider.roots` | Location in the virtual resource tree where the filesystem resources are mapped in. This property must not be an empty string. | | Filesystem Root | `provider.file` | Filesystem directory mapped to the virtual resource tree. This property must not be an empty string. If the path is relative it is resolved against `sling.home` or the current working directory. The path may be a file or folder. If the path does not address an existing file or folder, an empty folder is created. | \ No newline at end of file Modified: sling/site/trunk/content/documentation/bundles/content-loading-jcr-contentloader.mdtext URL: http://svn.apache.org/viewvc/sling/site/trunk/content/documentation/bundles/content-loading-jcr-contentloader.mdtext?rev=1345726&r1=1345725&r2=1345726&view=diff ============================================================================== --- sling/site/trunk/content/documentation/bundles/content-loading-jcr-contentloader.mdtext (original) +++ sling/site/trunk/content/documentation/bundles/content-loading-jcr-contentloader.mdtext Sun Jun 3 17:57:55 2012 @@ -7,35 +7,43 @@ Apache Sling provides support for initia Bundles can provide initial content, which is loaded into the repository when the bundle has entered the *started* state. Such content is expected to be contained in the bundles accessible through the Bundle entry API methods. Content to be loaded is declared in the `Sling-Initial-Content` bundle manifest header. This header takes a comma-separated list of bundle entry paths. Each entry and all its child entries are accessed and entered into starting with the child entries of the listed entries. Adding this content preserves the paths of the entries as show in this table, which assumes a `Sling-Initial-Content` header entry of `SLING-INF/content`: + | Entry | Repository Path | |--|--| | `SLING-INF/content/home` | `/home` | | `SLING-INF/content/content/playground/en/home` | `/content/playground/en/home` | + Bundle entries are installed as follows: + | Entry Type | Installation method | |--|--| | Directory | Created as a node of type `nt:folder` unless a content definition file of the same name exists in the same directory as the directory to be installed. Example: A directory `SLING-INF/content/dir` is installed as node `/dir` of type `nt:folder` unless a `SLING-INF/content/dir.xml` or `SLING-INF/content/dir.json` file exists which defines the content for the `/dir` node. | | File | Unless the file is a content definition file (see below) an `nt:file` node is created for the file and an `nt:resource` node is created as its `jcr:content` child node to take the contents of the bundle file. The properties of the `nt:resource` node are set from file information as available. If the file is a content definition file, the content is created as defined in the file. See below for the content definition file specification. | + It is possible to modify the intial content loading default behaviour by using certain optional directives. Directives should be specified separated by semicolon. They are defined as follows: + | Directive | Definition | Default value | Description | |--|--|--|--| -| `overwrite` | `overwrite:=(true\|false)` | `false` | The overwrite directive specifies if content nodes should be overwritten or just initially added. If this is true, existing nodes are deleted and a new node is created in the same place. | -| `overwriteProperties` | `overwriteProperties:=(true\|false)` | `false` | The overwriteProperties directive specifying if content properties should be overwritten or just initially added. | -| `uninstall` | `uninstall:=(true\|false)` | `overwrite` | The uninstall directive specifies if content should be uninstalled when bundle is unregistered. This value defaults to the value of the `overwrite` directive. | -| `path` | `path:=*/target/location{*`} | `/` | The path directive specifies the target node where initial content will be loaded. If the path does not exist yet in the repository, it is created by the content loader. The intermediate nodes are of type `nt:folder`. | -| `checkin` | `checkin:=(true\|false)` | `false` | The checkin directive specifies whether versionable nodes should be checked in. | +| `overwrite` | overwrite:=(true|false) | `false` | The overwrite directive specifies if content nodes should be overwritten or just initially added. If this is true, existing nodes are deleted and a new node is created in the same place. | +| `overwriteProperties` | overwriteProperties:=(true|false) | `false` | The overwriteProperties directive specifying if content properties should be overwritten or just initially added. | +| `uninstall` | uninstall:=(true|false) | `overwrite` | The uninstall directive specifies if content should be uninstalled when bundle is unregistered. This value defaults to the value of the `overwrite` directive. | +| `path` | path:=*/target/location* | `/` | The path directive specifies the target node where initial content will be loaded. If the path does not exist yet in the repository, it is created by the content loader. The intermediate nodes are of type `nt:folder`. | +| `checkin` | checkin:=(true|false) | `false` | The checkin directive specifies whether versionable nodes should be checked in. | | `ignoreImportProviders` | `ignoreImportProviders:=list of extensions` | `empty` | This directive can be used to not run one of the configured extractors (see below). | + Examples of these directives uses could be (assumes a Sling-Initial-Content header entry of SLING-INF/content): + | Entry | Behaviour | |--|--| | `SLING-INF/content/home;overwrite:=true;uninstall:=true` | Overwrites already existing content in */home* and uninstalls the content when the bundle is unregistered. | | `SLING-INF/content/home;overwriteProperties:=true` | Overwrites properties of existing content in */home*. | -| `SLING-INF/content/home;path:=/sites/sling*website` | if */sites/sling*website* exists it loads the content into it. Otherwise, it loads the content into root node */*. | +| `SLING-INF/content/home;path:=/sites/sling_website` | if */sites/sling_website* exists it loads the content into it. Otherwise, it loads the content into root node */*. | | `SLING-INF/content/home;checkin:=true` | After content loading, versionable nodes are checked in. | ## Loading initial content from bundles Repository items to be loaded into the repository, when the bundle is first installed, may be defined in four ways: + 1. Directories 1. Files 1. XML descriptor files @@ -59,59 +67,61 @@ The MIME type is derived from the file n Nodes, Properties and in fact complete subtrees may be described in XML files using either the JCR SystemView format, or the format described below. In either case, the file must have the .xml extension. - - xyz - - - nt:file - - - mix:versionable - mix:lockable - - - - - prop - - - property value as string - - - - .... - - + + xyz + + + nt:file + + + mix:versionable + mix:lockable + + + + + prop + + + property value as string + + + String + + + + + .... + + #### Using a custom XML format + By writing an XSLT stylesheet file, you can use whatever XML format you prefer. The XML file references an XSLT stylesheet by using the xml-stylesheet processing instruction: @@ -148,54 +158,54 @@ The my-transform.xsl file is then respon Nodes, Properties and in fact complete subtrees may be described in JSON files using the following skeleton structure (see [http://www.json.org]({{ refs.http://www.json.org.path }}) or information on the syntax of JSON) : { - // optional node name on top level, default is file name without .json ext. - "name": "nodename", - - // optional primary node type, default "nt:unstructured" - "primaryNodeType": "sling:ScriptedComponent", - - // optional mixin node types as array - "mixinNodeTypes": [ ], + // optional node name on top level, default is file name without .json ext. + "name": "nodename", + + // optional primary node type, default "nt:unstructured" + "primaryNodeType": "sling:ScriptedComponent", + + // optional mixin node types as array + "mixinNodeTypes": [ ], - // the "properties" property is an object indexed by property name whose - // value is either the string property value, array for multi-values or - // an object whose value[s] property denotes the property value(s) and - // whose type property denotes the property type - "properties": { - "sling:contentClass": "com.day.sling.jcr.test.Test", - "sampleMulti": [ "v1", "v2" ], - "sampleStruct": { - "value": 1, - "type": "Long" - } - "sampleStructMulti": { - "value": [ 1, 2, 3 ], - "type": "Long" - } - }, - - // the "nodes" property is an array of objects denoting child nodes. Nodes - // may be further nested. - "nodes": [ - { - // the name property is required on (nested) child nodes - "name": "sling:scripts", - - "primaryNodeType": "sling:ScriptList", - - "nodes": [ - { - "primaryNodeType": "sling:Script", - "properties": { - "sling:name": "/test/content/jsp/start.jsp", - "sling:type": "jsp", - "sling:glob": "*" - } - } - ] - } - ] - } + // the "properties" property is an object indexed by property name whose + // value is either the string property value, array for multi-values or + // an object whose value[s] property denotes the property value(s) and + // whose type property denotes the property type + "properties": { + "sling:contentClass": "com.day.sling.jcr.test.Test", + "sampleMulti": [ "v1", "v2" ], + "sampleStruct": { + "value": 1, + "type": "Long" + } + "sampleStructMulti": { + "value": [ 1, 2, 3 ], + "type": "Long" + } + }, + + // the "nodes" property is an array of objects denoting child nodes. Nodes + // may be further nested. + "nodes": [ + { + // the name property is required on (nested) child nodes + "name": "sling:scripts", + + "primaryNodeType": "sling:ScriptList", + + "nodes": [ + { + "primaryNodeType": "sling:Script", + "properties": { + "sling:name": "/test/content/jsp/start.jsp", + "sling:type": "jsp", + "sling:glob": "*" + } + } + ] + } + ] + } ### Extractors @@ -225,6 +235,6 @@ Support for re-registration of node type ### Automated tests -The initial content found in the [sling-test folder of the launchpad initial content]({{ refs.http://svn.apache.org/repos/asf/sling/trunk/launchpad/content/src/main/resources/content/sling-test.path }}) is verified by the [InitialContentTest|http://svn.apache.org/repos/asf/sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/InitialContentTest.java] when running the *launchpad/testing* integration tests. +The initial content found in the [sling-test folder of the launchpad initial content]({{ refs.http://svn.apache.org/repos/asf/sling/trunk/launchpad/content/src/main/resources/content/sling-test.path }}) is verified by the [InitialContentTest](http://svn.apache.org/repos/asf/sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/InitialContentTest.java) when running the *launchpad/testing* integration tests. Those tests can be used as verified examples of initial content loading. Contributions are welcome to improve the coverage of those tests. \ No newline at end of file Modified: sling/site/trunk/content/documentation/bundles/manipulating-content-the-slingpostservlet-servlets-post.mdtext URL: http://svn.apache.org/viewvc/sling/site/trunk/content/documentation/bundles/manipulating-content-the-slingpostservlet-servlets-post.mdtext?rev=1345726&r1=1345725&r2=1345726&view=diff ============================================================================== --- sling/site/trunk/content/documentation/bundles/manipulating-content-the-slingpostservlet-servlets-post.mdtext (original) +++ sling/site/trunk/content/documentation/bundles/manipulating-content-the-slingpostservlet-servlets-post.mdtext Sun Jun 3 17:57:55 2012 @@ -38,13 +38,15 @@ Similarly you can do this using the `cur 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 + $ 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 + $ curl -F"sling:resourceType=sling:sample" -Ftitle="some title text" \ + -Ftext="some body text content" http://host/some/new/content @@ -75,14 +77,16 @@ All these operations always operate on t Please note that operations are mutually exclusive. For a single POST request only one operation may be executed. Operations also only consume the request parameters as described below. Any excess parameters are silently ignored. {note:title=Automated Tests} -Note that the `launchpad/testing` module contains a number of [integration tests]({{ refs.-http-svn-apache-org-repos-asf-sling-trunk-launchpad-testing-src-test-java-org-apache-sling-launchpad-webapp-integrationtest-servlets-post.path }}) for the SlingPostServlet. Most of these tests are fairly readable, and can be used to find out more details about the servlet's behavior. +Note that the `launchpad/testing` module contains a number of [integration tests](http://svn.apache.org/repos/asf/sling/trunk/launchpad/test-services/src/main/java/org/apache/sling/launchpad/testservices/post/) for the SlingPostServlet. Most of these tests are fairly readable, and can be used to find out more details about the servlet's behavior. {note} + {note:title=Trailing star in the :applyTo parameter} This applies to operations that use this parameter, since version 2.1.2 of the *org.apache.sling.servlets.post* bundle: If the last segment of the `:applyTo` value is '*' then the operation applies to all the children of the resolved parent resource. This can be used to act on all the children of a resource without having to specify the path of each individual child resource. {note} + ### Content Creation or Modification @@ -92,12 +96,12 @@ First, the request URL indicates the act 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. +* 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 (and check the `[PostServletCreateTest]({{ refs.https://svn.apache.org/repos/asf/sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletCreateTest.java.path }})` in case of doubt): +To illustrate this algorithm, lets look at some examples (and check the [`PostServletCreateTest`](https://svn.apache.org/repos/asf/sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletCreateTest.java) in case of doubt): | Resource Path | Item path | |--|--| @@ -111,53 +115,50 @@ To illustrate this algorithm, lets look + ##### Setting Property Values Setting property values is as simple as just adding a request parameter whose name is the name of the property to be set and whose value is the value to be assigned to the property. We already saw how to do this in the quick start examples above. Here is another example show a simple HTML form to create a new node with an automatically created name: -{code:html} -
- - - -
+
+ + + +
- If this form is submitted with _title_ and _This is some Text_ as values for the {{title}} and {{text}} fields, resp., a new node is created at the path {{/content/page/first}} and the {{title}} and {{text}} properties set to the respective field values. If a node at {{/content/page/first}} already existed before submitting the form, the {{title}} and {{text}} properties are just updated to the new values from the form fields. +If this form is submitted with *title* and *This is some Text* as values for the `title` and `text` fields, resp., a new node is created at the path `/content/page/first` and the `title` and `text` properties set to the respective field values. If a node at `/content/page/first` already existed before submitting the form, the `title` and `text` properties are just updated to the new values from the form fields. - If a parameter has multiple values, the respective property will be created as a multi-value property. So for example the command line: +If a parameter has multiple values, the respective property will be created as a multi-value property. So for example the command line: - {noformat} $ curl -Fmulti=one -Fmulti=two http://host/content/page - {noformat} - Would assign the {{/content/page/multi}} property the value _[ "one", "two" ]_. +Would assign the `/content/page/multi` property the value *[ "one", "two" ]*. - This is pretty much all there is to know about creating and modifying content. The following sections will now introduce more functionality which help you with more fine-grained control in your content management application. +This is pretty much all there is to know about creating and modifying content. The following sections will now introduce more functionality which help you with more fine-grained control in your content management application. - h5. File Uploads +##### File Uploads - File uploads are typically done using the {{}} element of an HTML form and ensuring the correct form encoding. The SlingPostServlet handles uploaded files specially, in that the file data is not simply written into a property, but a node is actually created with three properties: +File uploads are typically done using the `` element of an HTML form and ensuring the correct form encoding. The SlingPostServlet handles uploaded files specially, in that the file data is not simply written into a property, but a node is actually created with three properties: - * {{jcr:data}} -- The actual file contents - * {{jcr:lastModified}} -- The time stamp of processing the uploaded file - * {{jcr:mimeType}} -- The MIME type from the original file submission (if contained in the file body part) or derived from the original file name +* `jcr:data` -- The actual file contents +* `jcr:lastModified` -- The time stamp of processing the uploaded file +* `jcr:mimeType` -- The MIME type from the original file submission (if contained in the file body part) or derived from the original file name - The name of the node is either taken from the parameter name or if the name is {{*}} from the name of the uploaded file. +The name of the node is either taken from the parameter name or if the name is `*` from the name of the uploaded file. - The primary node type of the uploaded file is selected using the following algorithm: +The primary node type of the uploaded file is selected using the following algorithm: - # If a {{@TypeHint}} suffixed parameter (see below for a description) is present check whether the value is a known non-mixin node type. If so, the node is created with this primary node type. - # If a {{@TypeHint}} suffixed parameter is not present or the value does not denote an existing non-mixin node type, the node will be created as an {{nt:file}} node if the parent node is of type {{nt:folder}}. Otherwise the node will be created with primary node type {{nt:resource}}. +* If a `@TypeHint suffixed parameter (see below for a description) is present check whether the value is a known non-mixin node type. If so, the node is created with this primary node type. +* If a `@TypeHint` suffixed parameter is not present or the value does not denote an existing non-mixin node type, the node will be created as an `nt:file` node if the parent node is of type `nt:folder`. Otherwise the node will be created with primary node type `nt:resource`. - If the node to be created is {{nt:file}}, the actual file data will really be stored in the {{jcr:content}} child node of the new {{nt:file}} node whose primary node type is then set as {{nt:resource}}. +If the node to be created is `nt:file`, the actual file data will really be stored in the `jcr:content` child node of the new `nt:file` node whose primary node type is then set as `nt:resource`. - Example 1: Upload an image to a node named {{image}} below {{/content/page}}: +Example 1: Upload an image to a node named `image` below `/content/page`: - {code:html}
@@ -167,47 +168,46 @@ Here is another example show a simple HT Example 2: Upload a file as a node of type `nt:file` below `/content/folder`: -{code:html} - - - - -
+
+ + + +
- Assuming the user selected a file named {{myImage.jpg}} the uploaded file would be stored in an {{nt:file}} node at {{/content/folder/myImage.jpg}}. - +Assuming the user selected a file named `myImage.jpg` the uploaded file would be stored in an `nt:file` node at `/content/folder/myImage.jpg`. + + - h5. Date properties +##### Date properties - Parameters providing date/time values to be stored in JCR properties of type _Date_ require special handling. The problem is that there are a number of formats to represent such date/time values. To account for this open-ended list of formats, the Sling Post Servlet supports configurability of the process of parsing strings into {{Calendar}} objects. +Parameters providing date/time values to be stored in JCR properties of type *Date* require special handling. The problem is that there are a number of formats to represent such date/time values. To account for this open-ended list of formats, the Sling Post Servlet supports configurability of the process of parsing strings into `Calendar` objects. - The Sling Post Servlet configuration property {{servlet.post.dateFormats}} takes a list of format strings which are used to setup {{java.text.SimpleDateFormat}} instances for parsing date/time string representations. A special format string {{ISO8601}} is supported to indicate the string to be parsed as a JCR standard string representation of a _Date_ property. +The Sling Post Servlet configuration property `servlet.post.dateFormats` takes a list of format strings which are used to setup `java.text.SimpleDateFormat` instances for parsing date/time string representations. A special format string `ISO8601` is supported to indicate the string to be parsed as a JCR standard string representation of a _Date_ property. - The default list of configured date/time parse pattern is : +The default list of configured date/time parse pattern is : - * EEE MMM dd yyyy HH:mm:ss 'GMT'Z - * ISO8601 - * yyyy-MM-dd'T'HH:mm:ss.SSSZ - * yyyy-MM-dd'T'HH:mm:ss - * yyyy-MM-dd - * dd.MM.yyyy HH:mm:ss - * dd.MM.yyyy +* EEE MMM dd yyyy HH:mm:ss 'GMT'Z +* ISO8601 +* yyyy-MM-dd'T'HH:mm:ss.SSSZ +* yyyy-MM-dd'T'HH:mm:ss +* yyyy-MM-dd +* dd.MM.yyyy HH:mm:ss +* dd.MM.yyyy - Any date/time string parameter supplied is subject to the patterns in the configured order. The first pattern accepting the string and parsing it into a {{Date}} -- and thus a {{Calendar}} -- object is used. Therefore this list is best ordered in a most-stringent to least-stringent order. +Any date/time string parameter supplied is subject to the patterns in the configured order. The first pattern accepting the string and parsing it into a `Date` -- and thus a `Calendar` -- object is used. Therefore this list is best ordered in a most-stringent to least-stringent order. - h5. Omitting Some Parameters +##### Omitting Some Parameters - There may be times, that you have forms which contain a lot of fields, which you do not want to actually store in content. Such forms usually are created using some client-side GUI library which uses the fields for its own purposes. To be able to easily differentiate between real content to be actually stored and such control parameters, you may prefix the names of the fields destined for content with a dot-slash ({{./}}). +There may be times, that you have forms which contain a lot of fields, which you do not want to actually store in content. Such forms usually are created using some client-side GUI library which uses the fields for its own purposes. To be able to easily differentiate between real content to be actually stored and such control parameters, you may prefix the names of the fields destined for content with a dot-slash (`./`). - As soon as the SlingPostServlet encounters parameters prefixed with dot-slash, only those parameters are considered for content updates while all other parameters not prefixed are just ignored. In addition to dot-slash prefixed parameters, also parameters prefixed with dot-dot-slash ({{../}}) and slash ({{/}}) are considered in this situation. +As soon as the SlingPostServlet encounters parameters prefixed with dot-slash, only those parameters are considered for content updates while all other parameters not prefixed are just ignored. In addition to dot-slash prefixed parameters, also parameters prefixed with dot-dot-slash (`../`) and slash (`/`) are considered in this situation. - For example, the following form only uses the first two fields for content update and ignores the rest: +For example, the following form only uses the first two fields for content update and ignores the rest: - {code:html}
@@ -224,8 +224,9 @@ Background: The name of the parameters u In addition to the mechanism explained here, the following parameters are also ignored: * Parameters whose name start with a colon (`:`) are always ignored by the SlingPostServlet with respect to content update. The reason is that the prefixing colon is intended as a marker for SlingPostServlet control parameters. -* The `\*charset\*` request parameter is also never written back because this parameter is used to convey the character encoding used to transport the request parameters. -* Request parameters matching a regular expression supplied with the `servlet.post.ignorePattern` configuration parameter are also ignored. By default this pattern is `j*.*` thus ignoring any request parameters with the prefix `j*` such as `j_username`. Those request parameters are generally used for authentication purposes and may hit the Sling POST Servlet in some situations. +* The `charset` request parameter is also never written back because this parameter is used to convey the character encoding used to transport the request parameters. +* Request parameters matching a regular expression supplied with the `servlet.post.ignorePattern` configuration parameter are also ignored. By default this pattern is `j_.*` thus ignoring any request parameters with the prefix `j_` such as `j_username`. Those request parameters are generally used for authentication purposes and may hit the Sling POST Servlet in some situations. + ##### Controlling Content Updates with `@` Suffixes @@ -243,39 +244,37 @@ For example, the parameter `width@TypeHi Parameters with the `@TypeHint` suffix may be used to force storing the named parameter in a property with the given type. The value of the `@TypeHint` parameter, if applied to a parameter for a property, is the JCR property type name. If the `@TypeHint` parameter is applied to a field upload parameter, the value is used to indicate the JCR primary node type for the node into which the uploaded file is stored. -If the `@TypeHint` ends with "[]({{ refs..path }})", it indicates a multi-value property. A multi-value property is usually auto-detected if there are mutliple values for the property (ie. request parameter). But if only a single value is present in the request, the desired property type needs to be explicitly defined as multi-value by stating `@TypeHint=[]`. +If the `@TypeHint` value ends with `[]`, it indicates a multi-value property. A multi-value property is usually auto-detected if there are mutliple values for the property (ie. request parameter). But if only a single value is present in the request, the desired property type needs to be explicitly defined as multi-value by stating `@TypeHint=[]`. Example: The following form sets the numeric `width`, the boolean `checked`, and the multi-valued `hobbys` (with 3 values to enter) properties: -{code:html} - - - - - - - - - - - +
+ + + + + + + + + +
- In real applications you would need some javascript that allows to add/remove values, ie. add/remove inputs with the name "hobbys". Or a pure javascript based form post would be used, that gathers the properties to update programmatically, but the additional parameter {{hobbys@TypeHint=String[]}} would be the same. +In real applications you would need some javascript that allows to add/remove values, ie. add/remove inputs with the name "hobbys". Or a pure javascript based form post would be used, that gathers the properties to update programmatically, but the additional parameter `hobbys@TypeHint=String[]` would be the same. - The {{@TypeHint}} suffixed parameter is assumed to be single-valued. If the parameter has multiple values, only the first is actually used. +The `@TypeHint` suffixed parameter is assumed to be single-valued. If the parameter has multiple values, only the first is actually used. - For more information on applying {{@TypeHint}} to a file upload parameter see the section on File Uploads above. +For more information on applying `@TypeHint` to a file upload parameter see the section on File Uploads above. - h6. {{@DefaultValue}} +###### `@DefaultValue` - The {{@DefaultValue}} suffixed parameter may be provided to set a property to a default value should no value be provided in the actual parameters. Same as for normal parameters, the {{@DefaultValue}} parameter may have multiple values to create multi-valued properties. +The `@DefaultValue` suffixed parameter may be provided to set a property to a default value should no value be provided in the actual parameters. Same as for normal parameters, the `@DefaultValue` parameter may have multiple values to create multi-valued properties. - Example: Set the {{text}} property to a default value if the user does not provide one: +Example: Set the `text` property to a default value if the user does not provide one: - {code:html}
@@ -288,20 +287,18 @@ Example: The following form sets the num As described above, `@DefaultValue` only takes effect if no value is provided for a particular parameter. However, in some cases, such as HTML checkboxes, this isn't sufficient because the parameter isn't submitted at all. To handle this scenario, you can use the `@UseDefaultWhenMissing` suffixed parameter. -{code:html} - - - - -
+
+ + + +
- h6. {{@IgnoreBlanks}} +###### `@IgnoreBlanks` - Sometimes a form client will supply empty parameter values resulting in content being created or modified. For example submitting this form: +Sometimes a form client will supply empty parameter values resulting in content being created or modified. For example submitting this form: - {code:html}
@@ -310,28 +307,25 @@ As described above, `@DefaultValue` only
-will result in multi-value String property being set to [ "foo", "bar", "" ]({{ refs.-foo-bar-.path }}). Notice the blank value. +will result in multi-value String property being set to [ "foo", "bar", "" ]. Notice the blank value. Likewise submitting this form without a value entered: -{code:html} -
- - -
+
+ + +
- will result in the single-value String property being set to an empty string. +will result in the single-value String property being set to an empty string. - To overcome this situation the {{@IgnoreBlanks}} suffix may be used to consider parameters with an empty string value to be ignored during processing. That is such parameter values would be treated as if they would not be supplied. +To overcome this situation the `@IgnoreBlanks` suffix may be used to consider parameters with an empty string value to be ignored during processing. That is such parameter values would be treated as if they would not be supplied. - Adding +Adding - {code:html} - - + -to the above forms will cause the multi-value property be set to the two-element value [ "foo", "bar" ]({{ refs.-foo-bar.path }}) and to not modify the property at all in the second single-value example. +to the above forms will cause the multi-value property be set to the two-element value [ "foo", "bar" ] and to not modify the property at all in the second single-value example. ###### `@ValueFrom` @@ -340,30 +334,28 @@ In some situations, an HTML form with pa Example: To set the property `text` from a form element `supplied_text`, you might use the following form: -{code:html} -
- - - -
+
+ + + +
- To prevent storing the additional paramaters in the repository you might want to use the prefixing mechanism as shown in the example above, where the {{@ValueFrom}} parameter is prefixed and thus the {{supplied_text}} parameter is not used for property setting. +To prevent storing the additional paramaters in the repository you might want to use the prefixing mechanism as shown in the example above, where the `@ValueFrom` parameter is prefixed and thus the `supplied_text` parameter is not used for property setting. - The {{@ValueFrom}} suffixed parameter is assumed to be single-valued. If the parameter has multiple values it is ignored completely. +The `@ValueFrom` suffixed parameter is assumed to be single-valued. If the parameter has multiple values it is ignored completely. - The {{@ValueFrom}} suffixed parameter is also special in that there must not be a correlated parameter without a suffix. Thus have parameters {{text}} and {{text@ValueFrom}} may have unexpected results. +The `@ValueFrom` suffixed parameter is also special in that there must not be a correlated parameter without a suffix. Thus have parameters `text` and `text@ValueFrom` may have unexpected results. - h6. {{@Delete}} +###### `@Delete` - Sometimes it may be required to not set a property to a specific value but to just remove it while processing the content update request. One such situation is a property filled from one or more checkboxes in an HTML form. If none of the checkboxes are checked, no parameter is actually submitted for these checkboxes. Hence the SlingPostServlet will not touch this property and effectively leave it untouched, while the natural reaction would have been to remove the property. +Sometimes it may be required to not set a property to a specific value but to just remove it while processing the content update request. One such situation is a property filled from one or more checkboxes in an HTML form. If none of the checkboxes are checked, no parameter is actually submitted for these checkboxes. Hence the SlingPostServlet will not touch this property and effectively leave it untouched, while the natural reaction would have been to remove the property. - Here comes the {{@Delete}} suffixed parameter. This simply causes the indicated property be removed if it exists. If the property does not exist, nothing more happens. The actual value of the {{@Delete}} suffixed parameter does not care as long as the parameter is submitted. +Here comes the `@Delete` suffixed parameter. This simply causes the indicated property be removed if it exists. If the property does not exist, nothing more happens. The actual value of the `@Delete` suffixed parameter does not care as long as the parameter is submitted. - Example: To ensure the {{color}} property is actually removed if no color has been selected, you might use the following form: +Example: To ensure the `color` property is actually removed if no color has been selected, you might use the following form: - {code:html}
@@ -373,7 +365,6 @@ Example: To set the property `text` from
- The `@Delete` suffixed parameter is also special in that there need not be a correlated parameter without a suffix. If both -- a parameters `text` and `text@Delete` are set, the `text` property is first deleted and then filled with the new content. The `@Delete` suffixed parameter in fact calls for a sub-operation, which is executed after the node addressed by the request URL is created (if needed) but before any other tasks of content creattion and modification are done. Any item -- this may be a property or a node, actually -- addressed by the `@Delete` suffixed parameter is just removed if it exists. If the item does not exist, nothing happens. @@ -388,32 +379,30 @@ To support this kind of functionality, t Example: Your Flash-based file upload stored the file on the server at `/tmp/upload/123`. You now want to store this file along with a title and a text in a newly created node. The following form will be your friend: -{code:html} - -
- - - - -
+ +
+ + + + +
- If there exists no repository item at the indicated path, nothing is done. If the item indicated by the {{@MoveFrom}} suffixed parameter already exists, it is replaced by the item addressed by the parameter value -- unless of course there is no item at the named location. +If there exists no repository item at the indicated path, nothing is done. If the item indicated by the `@MoveFrom` suffixed parameter already exists, it is replaced by the item addressed by the parameter value -- unless of course there is no item at the named location. - The {{@MoveFrom}} suffixed parameter is assumed to be single-valued. If the parameter has multiple values it is ignored completely. +The `@MoveFrom` suffixed parameter is assumed to be single-valued. If the parameter has multiple values it is ignored completely. - The {{@MoveFrom}} suffixed parameter is also special in that there must not be a correlated parameter without a suffix. Thus have parameters {{text}} and {{text@MoveFrom}} may have unexpected results. +The `@MoveFrom` suffixed parameter is also special in that there must not be a correlated parameter without a suffix. Thus have parameters `text` and `text@MoveFrom` may have unexpected results. - The {{@MoveFrom}} suffixed parameter in fact calls for a sub-operation, which is executed after the {{@Delete}} sub operation but before any other tasks of content creattion and modification are done. +The `@MoveFrom` suffixed parameter in fact calls for a sub-operation, which is executed after the `@Delete` sub operation but before any other tasks of content creattion and modification are done. - h6. {{@CopyFrom}} +###### `@CopyFrom` - Similar to the {{@MoveFrom}} suffix exists a {{@CopyFrom}} suffix. The latter works exactly the same as the former except that the item addressed by the parameter value is not moved but just copied. +Similar to the `@MoveFrom` suffix exists a `@CopyFrom` suffix. The latter works exactly the same as the former except that the item addressed by the parameter value is not moved but just copied. - Example: Your Flash-based file upload stored the file on the server at {{/tmp/upload/123}}. You now want to store this file along with a title and a text in a newly created node. The following form may be your friend: +Example: Your Flash-based file upload stored the file on the server at `/tmp/upload/123`. You now want to store this file along with a title and a text in a newly created node. The following form may be your friend: - {code:html}
@@ -440,19 +429,19 @@ If request is posted with an URL ending 1. If a `:name` parameter is supplied, the (first) value of this parameter is used unmodified as the name for the new node. If the name is illegally formed with respect to JCR name requirements, an exception will be thrown when trying to create the node. The assumption with the `:name` parameter is, that the caller knows what he (or she) is supplying and should get the exact result if possible. 1. Otherwise if a `:nameHint` parameter is supplied, the (first) value of this parameter is used to generate the node name. A name filtering is applied to this hint to ensure a valid JCR node name. -1. Otherwise a series of request paramaters supplied to set content is inspected for a possible name. The list of the names of these parameter is configurable with the SlingPostServlet and defaults ot `[ title, jcr:title, name, description, jcr:description, abstract ]({{ refs.-title-jcr-title-name-description-jcr-description-abstract.path }})`. The first request parameter with a non-empty value is used and filtered to get the valid JCR name. +1. Otherwise a series of request paramaters supplied to set content is inspected for a possible name. The list of the names of these parameter is configurable with the SlingPostServlet and defaults ot `[ title, jcr:title, name, description, jcr:description, abstract ](` refs.-title-jcr-title-name-description-jcr-description-abstract.path `)`. The first request parameter with a non-empty value is used and filtered to get the valid JCR name. 1. Otherwise an ever increasing auto generated number is used. Filtering is also applied to this numeric name. The filtering algorithm to create a valid name of the hints from above steps (except the first) works as follows: - * Convert the proposed name to all lower case. - * Replace all characters not in the range \[0..9a..z*\]({{ refs.0-9a-z.path }}) by a single underscore `\*`. - * If the name starts with a digit prepend an underscore. Technically names with leading digits are valid, but they present major issues when using such names in JCR XPath expressions. The algorithm takes care to not create names with two or more consecutive underscore characters. - * Finally the name is cut to a configurable maximum length (default is 20 characters). +* Convert the proposed name to all lower case. +* Replace all characters not in the range [0..9a..z*] by a single underscore `_`. +* If the name starts with a digit prepend an underscore. Technically names with leading digits are valid, but they present major issues when using such names in JCR XPath expressions. The algorithm takes care to not create names with two or more consecutive underscore characters. +* Finally the name is cut to a configurable maximum length (default is 20 characters). -For example the `:nameHint` value *A quick brown Fox ...* is filtered to become *a\*quick\*brown\*fox\** +For example the `:nameHint` value *A quick brown Fox ...* is filtered to become *a_quick_brown_fox_*. After generating and filtering the name it is further guaranteed that the name is unique: If a node of the same name as just generated from the algorithm already exists below the same parent node a numeric index is appended to the new node name to make it unique. @@ -498,7 +487,8 @@ When specifying the item(s) to be remove To remove the `/content/page1` and `/content/page2` nodes, for example, you might use the following command line: - $ curl -F":operation=delete" -F":applyTo=/content/page1" -F":applyTo=/content/page2" http://host/content/sample + $ curl -F":operation=delete" -F":applyTo=/content/page1" \ + -F":applyTo=/content/page2" http://host/content/sample Using a trailing star in the :applyTo parameter (as mentioned before), you can remove all the children of the `/content` node, for example, as follows: @@ -562,7 +552,8 @@ When specifying the item(s) to be copied To copy the `/content/page1` and `/content/page2` nodes to `/content/target`, for example, use: - $ curl -F":operation=copy" -F":applyTo=/content/page1" -F":applyTo=/content/page2" -F":dest=/content/target/" http://host/content/sample + $ curl -F":operation=copy" -F":applyTo=/content/page1" -F":applyTo=/content/page2" \ + -F":dest=/content/target/" http://host/content/sample Please note the trailing slash character (`/`) in the value of the `:dest` parameter. This is required for multi-item copy operations using the `:applyTo` parameter. The copied items are created below the node indicated by the `:dest`. @@ -570,7 +561,8 @@ Please note the trailing slash character Using a trailing star in the :applyTo parameter (as mentioned before), you can copy all the children of the `/content` node, for example, as follows: - $ curl -F":operation=copy" -F":applyTo=/content/*" -F":dest=/content/target/" http://host/content/sample + $ curl -F":operation=copy" -F":applyTo=/content/*" -F":dest=/content/target/" \ + http://host/content/sample If any resource listed in the `:applyTo` parameter does not exist, it is silently ignored. Any item already existing at the copy destination whose name is the same as the name of an item to be copied is silently overwritten with the source item. @@ -631,7 +623,8 @@ When specifying the item(s) to be moved To for example move the `/content/page1` and `/content/page2` nodes to `/content/target`, you might use the following command line: - $ curl -F":operation=move" -F":applyTo=/content/page1" -F":applyTo=/content/page2" -F":dest=/content/target/" http://host/content/sample + $ curl -F":operation=move" -F":applyTo=/content/page1" -F":applyTo=/content/page2" \ + -F":dest=/content/target/" http://host/content/sample Please note the trailing slash character (`/`) in the value of the `:dest` parameter. This is required for multi-item move operations using the `:applyTo` parameter. The moved items are created below the node indicated by the `:dest`. @@ -639,7 +632,8 @@ Please note the trailing slash character Using a trailing star in the :applyTo parameter (as mentioned before), you can move all the children of the `/content` node, for example, as follows: - $ curl -F":operation=move" -F":applyTo=/content/*" -F":dest=/content/target/" http://host/content/sample + $ curl -F":operation=move" -F":applyTo=/content/*" -F":dest=/content/target/" \ + http://host/content/sample If any resource listed in the `:applyTo` parameter does not exist, it is silently ignored. Any item already existing at the move destination whose name is the same as the name of an item to be moved is silently overwritten with the source item. @@ -661,9 +655,10 @@ The move operation applied to multiple r To import content structures just address the parent item to import into and set the `:operation` parameter to `import`. -The optional name of the root node of the imported content may optionally be supplied using the [#Algorithm for Node Name Creation]({{ refs.-algorithm-for-node-name-creation.path }}). +The optional name of the root node of the imported content may optionally be supplied using the [Algorithm for Node Name Creation](#algorithm-for-node-name-creation). Other parameters for the import operation: + | Parameter | Required | Default value | Description | |--|--|--|--| | `:contentType` | `true` | | The `:contentType` value specifies the type of content being imported. Possible values are: xml, jcr.xml, json, jar, zip | @@ -678,31 +673,33 @@ Other parameters for the import operatio For example the following command line imports the `/content/sample` page: - $ curl -F":operation=import" -F":contentType=json" -F":name=sample" - -F":content={ 'jcr:primaryType': 'nt:unstructured', 'propOne' : 'propOneValue', 'childOne' : { 'childPropOne' : true } }" http://host/content + $ curl -F":operation=import" -F":contentType=json" -F":name=sample" \ + -F":content={ 'jcr:primaryType': 'nt:unstructured', 'propOne' : 'propOneValue', 'childOne' : { 'childPropOne' : true } }" \ + http://host/content For example the following command line imports the `/content/sample` page without the optional name parameter: $ curl -F":operation=import" -F":contentType=json" - -F":content={ 'sample' : {'propOne' : 'propOneValue', 'childOne' : { 'childPropOne' : true } } }" http://host/content + -F":content={ 'sample' : {'propOne' : 'propOneValue', 'childOne' : { 'childPropOne' : true } } }" \ + http://host/content For example the following form imports the `/content/sample` page: -{code:html} - - - - - - - -
+ +
+ + + + + + +
- For example the following form imports content from a file upload: - {code:html} +For example the following form imports content from a file upload: +
@@ -713,6 +710,7 @@ For example the following form imports t
+ ###### Response Status The move operation applied to multiple resources has the following status responses: @@ -728,23 +726,11 @@ The move operation applied to multiple r - - - - - - - - - - - - ### Null Operation Sometimes it is useful to explicitly request that nothing is to be done. The SlingPostServlet now provides such an operation under the name `nop`. Apart from doing nothing, the `nop` operations sets the response status to either the default `200/OK` or to any status requested by the `:nopstatus` request parameter. -The `:nopstatus` request parameter must be an integral number in the range \[ 100 .. 999 ]({{ refs.-100-999.path }}). If the parameter value cannot be parsed to an integer or the value is outside of this range, the default status `200/OK` is still set. +The `:nopstatus` request parameter must be an integral number in the range [ 100 .. 999 ]. If the parameter value cannot be parsed to an integer or the value is outside of this range, the default status `200/OK` is still set. ###### Response Status @@ -799,11 +785,12 @@ By default the SlingPostServlet sets res 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. + ## Response format The SlingPostServlet produces a basic HTTP response body, listing the response status, what changes have been made, and other meta-data about the result of the POST request. -The format of this response is either HTML or JSON (JSON support introduced with [SLING-1336]({{ refs.https://issues.apache.org/jira/browse/SLING-1336.path }})). SlingPostServlet determines which format to use by examining the Accept header of the incoming request. If the client has specified a preference for the media type "application/json", the JSON format is used, otherwise HTML is returned. +The format of this response is either HTML or JSON (JSON support introduced with [SLING-1336](https://issues.apache.org/jira/browse/SLING-1336)). SlingPostServlet determines which format to use by examining the Accept header of the incoming request. If the client has specified a preference for the media type "application/json", the JSON format is used, otherwise HTML is returned. The Accept header can be overridden (and simulated) by posting a :http-equiv-accept field, which should have the same format as the Accept header. Examples: @@ -812,26 +799,29 @@ Examples: In example #1, SlingPostServlet will return HTML, since the client has specified a preference for text/html. In example #2, SlingPostServlet will return JSON. -See [RFC 2616, section 14.1]({{ refs.http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1.path }}) for information on the HTTP Accept header. +See [RFC 2616, section 14.1](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1) for information on the HTTP Accept header. ## Versionable Node Support The modify (default), delete, move, and copy operations of the SlingPostServlet support JCR Versionable Nodes. By default, when a node needs to be checked out for a modification to occur, it will be checked out and any nodes the operation checks out will be checked in upon completion of the request. Newly created versionable nodes (or non-versionable nodes made versionable by adding the mix:versionable mixin) will be left in their default, checked out state. This default behavior can be modified either globally (i.e. for all requests) or on a per-request basis. The global behavior is changed through OSGi ConfigAdmin using these three properties of the PID `org.apache.sling.servlets.post.impl.SlingPostServlet`: + * `servlet.post.checkinNewVersionableNodes` * `servlet.post.autoCheckout` * `servlet.post.autoCheckin` -!2010-07-01_1036.png! +![](2010-07-01_1036.png) On a per-request basis, these request parameters can be used: + * `:checkinNewVersionableNodes` * `:autoCheckout` * `:autoCheckin` Checkout and Check In changes will be reflected in the ChangeLog portion of the response. + ## Extending the SlingPostServlet ### Additional POST operations @@ -840,9 +830,12 @@ OSGi services of the `org.apache.sling.s Such services must have a `sling.post.operation` service registration property set to the name of the operation. This name is used as the value of the `:operation` parameter of POST requests to select the extended operation. -Before version 2.1.2 of the *org.apache.sling.servlets.post* bundle, such additional operations were implemented by the `org.apache.sling.servlets.post.SlingPostOperation` interface, which is now deprecated but still supported via a bridge. See [SLING-1725]({{ refs.https://issues.apache.org/jira/browse/SLING-1725.path }}) for details and discussions about this change. +Before version 2.1.2 of the *org.apache.sling.servlets.post* bundle, such additional operations were implemented by the `org.apache.sling.servlets.post.SlingPostOperation` interface, which is now deprecated but still supported via a bridge. See [SLING-1725](refs.https://issues.apache.org/jira/browse/SLING-1725) for details and discussions about this change. + +Two examples (old and new style) of additional POST operations are found in the [test-services](http://svn.apache.org/repos/asf/sling/trunk/launchpad/test-services/src/main/java/org/apache/sling/launchpad/testservices/post/) module, with the corresponding test code in the [integration-tests](http://svn.apache.org/repos/asf/sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/CustomPostOperationTest.java) module. -Two examples (old and new style) of additional POST operations are found in the [test-services]({{ refs.http://svn.apache.org/repos/asf/sling/trunk/launchpad/test-services/src/main/java/org/apache/sling/launchpad/testservices/post/.path }}) module, with the corresponding test code in the [integration-tests|http://svn.apache.org/repos/asf/sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/CustomPostOperationTest.java] module. ### SlingPostProcessor -TODO: document the SlingPostProcessor extension point, and related tests \ No newline at end of file + +TODO: document the SlingPostProcessor extension point, and related tests + Modified: sling/site/trunk/content/documentation/getting-started/discover-sling-in-15-minutes.mdtext URL: http://svn.apache.org/viewvc/sling/site/trunk/content/documentation/getting-started/discover-sling-in-15-minutes.mdtext?rev=1345726&r1=1345725&r2=1345726&view=diff ============================================================================== --- sling/site/trunk/content/documentation/getting-started/discover-sling-in-15-minutes.mdtext (original) +++ sling/site/trunk/content/documentation/getting-started/discover-sling-in-15-minutes.mdtext Sun Jun 3 17:57:55 2012 @@ -6,18 +6,20 @@ This page will help you get started with While simple to run and understand, the Launchpad is a full-featured instance of Sling, an example configuration that we have created with the most common modules and configurations. The full functionality of Sling is available by loading additional Sling (or custom) OSGi bundles as needed, using the Launchpad's web-based OSGi management console. +[TOC] + ## See Also -Example applications and mini-applications for Sling can be found under http://svn.apache.org/repos/asf/sling/trunk/samples/ (each application has a `README.txt` file, see these for more details). +Example applications and mini-applications for Sling can be found under [http://svn.apache.org/repos/asf/sling/trunk/samples/](http://svn.apache.org/repos/asf/sling/trunk/samples/) (each application has a `README.txt` file, see these for more details). Once you grok the basic examples of this page, we recommend studying the *espblog* and *webloader* samples for more complete examples. The *javashell* sample is useful to play with JCR java code (or any java code, for that matter) interactively. ## Prerequisites -We'll start with the self-runnable jar from the Sling distribution, you only need a Java 5 JDK. Download the latest release from the Sling [Downloads]({{ refs.downloads.path }}) page or by clicking this link: [org.apache.sling.launchpad-6-standalone.jar|http://www.apache.org/dyn/closer.cgi/sling/org.apache.sling.launchpad-6-standalone.jar]. Alternatively you can deploy the [Sling Web application|http://www.apache.org/dyn/closer.cgi/sling/org.apache.sling.launchpad-6.war] into any decent Servlet Container such as Jetty or Tomcat or you can [build the current source yourself|Getting and Building Sling]. +We'll start with the self-runnable jar from the Sling distribution, you only need a Java 5 JDK. Download the latest release from the Sling [Downloads]({{ refs.downloads.path }}) page or by clicking this link: [org.apache.sling.launchpad-6-standalone.jar](http://www.apache.org/dyn/closer.cgi/sling/org.apache.sling.launchpad-6-standalone.jar). Alternatively you can deploy the [Sling Web application](http://www.apache.org/dyn/closer.cgi/sling/org.apache.sling.launchpad-6.war) into any decent Servlet Container such as Jetty or Tomcat or you can [build the current source yourself]({{ refs.getting-and-building-sling.path }}). -To show the simplicity of the REST-style approach taken by Sling the examples below will be using [cURL]({{ refs.http://curl.haxx.se/.path }}). Any HTTP client would do, but cURL is the easiest to document in a reproducible way. +To show the simplicity of the REST-style approach taken by Sling the examples below will be using [cURL](http://curl.haxx.se/). Any HTTP client would do, but cURL is the easiest to document in a reproducible way. A WebDAV client makes editing server-side scripts much more convenient, but to make our examples easy to reproduce, we're using cURL below to create and update files in the JCR repository, via the Sling WebDAV server. @@ -32,10 +34,10 @@ After downloading the Sling Launchpad se This starts the Sling embedded Web Server on port 8080 and writes application files into the `sling` folder found in the current working directory. -Once started, look at [http://localhost:8080/system/console/bundles]({{ refs.http://localhost:8080/system/console/bundles.path }}) with your browser. Use *admin* with password *admin* if Sling asks you for a login. Sling then displays the *Felix Web Management Console* page. +Once started, look at [http://localhost:8080/system/console/bundles](http://localhost:8080/system/console/bundles) with your browser. Use *admin* with password *admin* if Sling asks you for a login. Sling then displays the *Felix Web Management Console* page. -On the bundles page, all bundles should be marked *Active*. They're all [OSGi]({{ refs.http://www.osgi.org/.path }}) bundles powered by [Apache Felix|http://felix.apache.org], but that doesn't really matter to us right now. +On the bundles page, all bundles should be marked *Active*. They're all [OSGi](http://www.osgi.org/) bundles powered by [Apache Felix](http://felix.apache.org), but that doesn't really matter to us right now. {tip:title=Log files} If things go wrong, have a look at the `sling/logs/error.log` log file \- that's where Sling writes any error messages. @@ -45,16 +47,16 @@ If things go wrong, have a look at the ` Until we have ready-to-test forms, you can create content with cURL, or you can create an HTML form that posts to the specified URL. -To create a content node (nodes are a [JCR]({{ refs.http://jackrabbit.apache.org/.path }}) concept, a unit of storage) with cURL, use: +To create a content node (nodes are a [JCR](http://jackrabbit.apache.org/) concept, a unit of storage) with cURL, use: curl -u admin:admin -F"sling:resourceType=foo/bar" -F"title=some title" http://localhost:8080/content/mynode -The resulting node can be seen at [http://localhost:8080/content/mynode.html]({{ refs.http://localhost:8080/content/mynode.html.path }}), or as json format under [http://localhost:8080/content/mynode.json|http://localhost:8080/content/mynode.json]. Lets try with cURL: +The resulting node can be seen at [http://localhost:8080/content/mynode.html](http://localhost:8080/content/mynode.html.path), or as json format under [http://localhost:8080/content/mynode.json](http://localhost:8080/content/mynode.json). Lets try with cURL: - $ curl http://localhost:8080/content/mynode.json + $ curl http://localhost:8080/content/mynode.json {"title":"some title","sling:resourceType":"foo/bar","jcr:primaryType":"nt:unstructured"} @@ -74,7 +76,6 @@ To select a script, Sling uses the node' That is the case in our example, so the following script will be used by Sling to render the node in HTML, if the script is found at */apps/foo/bar/html.esp* in the repository. -
html.esp

<%= currentNode.title %>

@@ -83,11 +84,12 @@ That is the case in our example, so the To select the script, Sling: + * looks under */apps* * and appends the *sling:resourceType* value of our node ( which is *foo/bar* ) * and appends *html.esp*, as the extension of our URL is *html* and the language of our script is *esp*. -Store this script under */apps/foo/bar/html.esp*, either using a WebDAV client (connected to [http://admin:admin@localhost:8080/]({{ refs.http://admin:admin@localhost:8080/.path }})), or using cURL as shown here, after creating the *html.esp* script in the current directory on your system: +Store this script under */apps/foo/bar/html.esp*, either using a WebDAV client (connected to [http://admin:admin@localhost:8080/](http://admin:admin@localhost:8080/)), or using cURL as shown here, after creating the *html.esp* script in the current directory on your system: curl -X MKCOL -u admin:admin http://localhost:8080/apps/foo @@ -100,9 +102,9 @@ create a local file *html.esp* and copy curl -u admin:admin -T html.esp http://localhost:8080/apps/foo/bar/html.esp -The HTML rendering of your node, at [http://localhost:8080/content/mynode.html]({{ refs.http://localhost:8080/content/mynode.html.path }}), is now created by this ESP script. You should see the node's title alone as an

element in that page. +The HTML rendering of your node, at [http://localhost:8080/content/mynode.html](http://localhost:8080/content/mynode.html), is now created by this ESP script. You should see the node's title alone as an <h1> element in that page. -A script named *POST.esp* instead of *html.esp* would be called for a POST request, *DELETE.esp* for DELETE, *xml.esp* for a GET request with a *.xml* extension, etc. See [URL to Script Resolution]({{ refs.http://cwiki.apache.org/SLING/url-to-script-resolution.html.path }}) on the Sling wiki for more info. +A script named *POST.esp* instead of *html.esp* would be called for a POST request, *DELETE.esp* for DELETE, *xml.esp* for a GET request with a *.xml* extension, etc. See [URL to Script Resolution]({{ refs.url-to-script-resolution.path }}) on the Sling wiki for more info. Servlets can also be easily "wired" to handle specific resource types, extensions, etc., in the simplest case by using SCR annotations in the servlet source code. Servlets and scripts are interchangeable when it comes to processing Sling requests. @@ -113,12 +115,12 @@ These simple examples show how Sling use There's much more to Sling of course - you'll find some additional simple examples below, and above in the *see also* section. -We are working on debugging features to help trace the way Sling processes requests. Have a look at [SLING-3]({{ refs.https://issues.apache.org/jira/browse/SLING-3.path }}) to see what's possible already. +We are working on debugging features to help trace the way Sling processes requests. Have a look at [SLING-3](https://issues.apache.org/jira/browse/SLING-3) to see what's possible already. -# Additional examples +## Additional examples -## Let Sling generate the path of a newly created node. +### Let Sling generate the path of a newly created node. To create a node with a unique path at a given location, end the URL of the POST request with */*. @@ -136,30 +138,29 @@ And create a node with a Sling-generated curl -D - -u admin:admin -F"title=Adventures with Sling" "http://localhost:8080/content/blog/" -Using cURL's *\-D* option shows the full HTTP response, which includes a *Location* header to indicate where the new node was created: +Using cURL's *-D* option shows the full HTTP response, which includes a *Location* header to indicate where the new node was created: Location: /blog/adventures_with_slin -The actual node name might not be *adventures*with*slin* \- depending on existing content in your repository, Sling will find a unique name for this new node, based on several well-know property values like title, description, etc. which are used for this if provided. +The actual node name might not be *adventures_with_slin* - depending on existing content in your repository, Sling will find a unique name for this new node, based on several well-know property values like title, description, etc. which are used for this if provided. -So, in our case, our new node can be displayed in HTML via the [http://localhost:8080/blog/adventures*with*slin.html]({{ refs.http://localhost:8080/blog/adventures*with*slin.html.path }}) URL. +So, in our case, our new node can be displayed in HTML via the [http://localhost:8080/blog/adventures_with_slin.html](http://localhost:8080/blog/adventures*with*slin.html) URL. Note that we didn't set a *sling:resourceType* property on our node, so if you want to render that node with a script, you'll have to store the script under */apps/nt/unstructured/html.esp*. -## Add a page header with sling.include +### Add a page header with sling.include The *sling.include* function can be called from scripts to include the rendered result of another node. In this example, we create a node at */content/header*, rendered with a logo using an *html.esp* script, then use that header at the top of the *html.esp* script that we created previously for the *foo/bar* resource type. -Start by checking that [http://localhost:8080/content/mynode.html]({{ refs.http://localhost:8080/content/mynode.html.path }}) is rendered using the *html.esp* script created above. +Start by checking that [http://localhost:8080/content/mynode.html](http://localhost:8080/content/mynode.html) is rendered using the *html.esp* script created above. Create this script and name it *header.esp*: -
header.esp

@@ -178,7 +179,8 @@ Upload it so that it is used to render r Create the header node: - curl -u admin:admin -F"sling:resourceType=foo/header" -F"headline=Hello, Sling world" http://localhost:8080/content/header + curl -u admin:admin -F"sling:resourceType=foo/header" \ + -F"headline=Hello, Sling world" http://localhost:8080/content/header Upload the logo that the script uses (using sling.jpg or another logo in the current directory): @@ -188,11 +190,10 @@ Upload the logo that the script uses (us curl -u admin:admin -T sling.jpg http://localhost:8080/images/sling.jpg -And check that the header is rendered with the logo at [http://localhost:8080/content/header.html]({{ refs.http://localhost:8080/content/header.html.path }}). +And check that the header is rendered with the logo at [http://localhost:8080/content/header.html](http://localhost:8080/content/header.html). Now, update the html.esp script that we created for our first example above, to include the header: -

html.esp