You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@sling.apache.org by GitBox <gi...@apache.org> on 2021/08/13 14:44:40 UTC

[GitHub] [sling-site] kwin commented on a change in pull request #67: SLING-10733 consolidate script documentation

kwin commented on a change in pull request #67:
URL: https://github.com/apache/sling-site/pull/67#discussion_r688569340



##########
File path: src/main/jbake/content/documentation/bundles/scripting.md
##########
@@ -67,9 +67,143 @@ Mapping `html` to Thymeleaf 3.0:
       "html=Thymeleaf:3.0"
     ]
 
+## Scripts are Servlets
+
+The Sling API defines a `SlingScript` interface which is used to represent (executable) scripts inside of Sling. This interface is implemented in the [Scripting Core bundle][8] in the `DefaultSlingScript` class which also implements the `javax.servlet.Servlet`.
+
+To further simplify the access to scripts from the Resource tree, the `scripting/core` bundle registers an `AdapterFactory` to adapt Resources to Scripts and Servlets (the `SlingScriptAdapterFactory`). In fact the adapter factory returns instances of the `DefaultSlingScript` class for both Scripts and Servlets.
+
+From the perspective of the [Servlet resolver][7], scripts and servlets are handled exactly the same. In fact, internally, Sling only deals with Servlets, whereas scripts are packed inside a Servlet wrapping and representing the script.
+
+## Resource Scripts
+
+Scripts are looked up in a series of resource resolver locations defined by the `ResourceResolver.getSearchPath()` and the resource type (and resource super types) of the requested resource: 
+
+    {scriptPathPrefix}/{resourceTypePath} 
+    
+The pseudo code for iterating the locations would be something like: 
+    
+
+    var type = resource.getResourceType(); 
+    while (type != null) { 
+        for (String root: resourceResolver.getSearchPath()) { 
+            String path = root + type.toPath(); 
+            findScriptsIn(path); 
+        } 
+
+        if (type == defaultServlet) { 
+            type = null; 
+        } else { 
+            type = getResourceSuperType(type); 
+            if (type == null) { 
+                type = defaultServlet; 
+            } 
+        } 
+    } 
+
+### Resource script naming conventions
+
+Depending on whether request selectors are considered, a script may have two forms: 
+
+1. Ignoring request selectors (e.g. there are none in the request URI): `{resourceTypeLabel}.{requestExtension}.{requestMethod}.{scriptExtension}` 
+2. Handling request selectors: `{selectorStringPath}.{requestExtension}.{requestMethod}.{scriptExtension}`
+
+The constituents of these script names are as follows: 
+
+* `{resourceTypeLabel}` - The last path segment of the path created from the resource type. This part is optional if the `{requestExtension}` is used in the script name. The resource type might either be set via the `sling:resourceType` property on the accessed node or if that property is not there its primary node type (property `jcr:primaryType`) is taken as fall-back.
+* `{requestExtension}` - The request extension. This part may be omitted if the request extension is `html`, otherwise this part is required. If this part is omitted, the `{resourceTypeLabel}` is required in the case of ignoring the selectors.
+* `{requestMethod}` - The request's HTTP method. This part may be omitted if the script is meant for a `GET` or a `HEAD` request. This part is required for any other HTTP method.
+* `{scriptExtension}` - The extension identifying the scripting language used. This part is mandatory. For more details about the available Script Engines and their registered extensions check the [Sling Scripting](/documentation/bundles/scripting.html) page.
+* `{selectorStringPath}` - The selector string converted to a path, along the lines of `selectorString.replace('.', '/')`. If less selectors are specified in the script name than given in the request, the script will only be taken into consideration if the given selectors are the **first** selectors in the request. This means *sel1/sel2.html.jsp* will be a candidate for the request url */content/test.sel1.sel2.sel3.html* but not for */content/test.sel3.sel1.sel2.html*. So the order of selectors is relevant!
+
+
 ## Bundled Scripts
 
-Scripts may also be provided in OSGi bundles (precompiled or embedded) since [Sling Servlet Resolver 2.7.0](https://github.com/apache/sling-org-apache-sling-servlets-resolver#bundled-scripts).
+Scripts may also be provided in OSGi bundles (precompiled or embedded) since [Sling Servlet Resolver 2.7.0](https://github.com/apache/sling-org-apache-sling-servlets-resolver#bundled-scripts) through the org.apache.sling.servlets.resolver.bundle.tracker API in addition to classical Resource based scripts.
+
+Although traditionally scripts are deployed as content stored in the search paths of a Sling instance, this leaves very little
+room for script evolution in a backwards compatible way. Furthermore, versioning scripts is a difficult process if the only
+mechanism to do this is the `sling:resourceType` property, since consumers (content nodes or other resource types) have then to
+explicitly mention the version expected to be executed.
+
+Scripts should not be considered content, since their only purpose is to actually generate the rendering for a certain content
+structure. They are not consumed by users, but rather by the Sling Engine itself and have very little meaning outside this
+context. As such, scripts should be handled like code:
+
+  1. they _provide an HTTP API_;
+  2. they can evolve in a [_semantical_  way][1];
+  3. they have a _developer audience_.
+
+  
+### Technical Background
+
+Being built around a [`BundleTrackerCustomizer`][2], the `org.apache.sling.servlets.resolver.internal.bundle.BundledScriptTracker`
+monitors the instance's bundles wired to the `org.apache.sling.servlets.resolver` bundle and scans the ones providing a `sling.servlet`
+[capability][3]. The wiring is created by placing a `Require-Capability` header in the bundles that provide the `sling.servlet` capability:
+
+```
+osgi.extender;filter:="(&(osgi.extender=sling.scripting)(version>=1.0.0)(!(version>=2.0.0)))"
+```
+
+A `sling.servlet` capability has almost the same attributes as the properties required to [register a servlet on the Sling platform][4]:
+
+  1. `sling.servlet.resourceTypes:List` - mandatory; defines the provided resource type; its value is a list of resource types
+  2. `sling.servlet.selectors:List` - optional; defines the list of selectors that this resource type can handle;
+  3. `sling.servlet.extensions:List` - optional; defines the list of extensions that this resource type can handle;
+  4. `sling.servlet.methods:List` - optional; defines the list of HTTP methods that this resource type can handle;
+  5. `version:Version` - optional; defines the version of the provided `resourceType`;
+  6. `extends:String` - optional; defines which resource type it extends; the version range of the extended resource type is defined in a
+    `Require-Capability`.
+
+The `BundledScriptTracker` will register a Sling Servlet with the appropriate properties for each `sling.servlet` capability. The
+servlets will be registered using the bundle context of the bundle providing the `sling.servlet` capability, making
+sure to expose the different versions of a resource type as part of the registered servlet's properties. On top of this, a plain resource
+type bound servlet will also be registered, which will be automatically wired to the highest version of the `resourceType`. All the
+mentioned service registrations are managed automatically by the `BundledScriptTracker`.
+
+### So how do I deploy my scripts?
+Short answer: exactly like you deploy your code, preferably right next to it. Pack your scripts using the following conventions:
+
+  1. create a `src/main/resources/javax.script` folder in your bundle (if you want to embed the scripts as they are) or just put the
+   scripts in `src/main/scripts` if you want to precompiled them (e.g. JSP and HTL);
+  2. each folder under the above folders will identify a `resourceType`;
+  3. inside each `resourceType` folder you can optionally create a `Version` folder; this has to follow the Semantic Versioning
+   constraints described at [1];
+  4. add your scripts, using the same [naming conventions that you were used to from before][5];
+  5. manually define your provide and require capabilities; just kidding; add the
+  [`scriptingbundle-maven-plugin`](https://github.com/apache/sling-scriptingbundle-maven-plugin) to your build section and add its required
+  properties in the `maven-bundle-plugin`'s instructions (check [these examples](https://github.com/apache/sling-org-apache-sling-scripting-bundle-tracker-it/tree/master/examples/));
+  6. `mvn clean sling:install`.
+
+### Integration Tests
+
+The integration tests for bundled scripts are provided by the [`org.apache.sling.scripting.bundle.tracker.it`](https://github.com/apache/sling-org-apache-sling-scripting-bundle-tracker-it) project.
+
+## Script resolution order
+
+The [same rules as for servlets][6] are being followed but in addition keep in mind that bundled scripts (as well as servlets) are prefered over resource scripts.

Review comment:
       @karlpauls Is this observation correct? I couldn't find according tests for that....




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@sling.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org