OSGi console plugin

Version 2.0.46 of the org.apache.sling.scripting.core bundle provides an OSGi console plugin that dynamically retrieves the actual scripting variable names and types, at /system/console/scriptingvariables

Sling's scripting variables and script languages

Common scripting variables

The basic objects, such as the request and response, are available for most scripting languages (Note the differences for eg. JSP below).

Name

Description

request

SlingHttpServletRequest object, providing access to the HTTP request header information - extends the standard HttpServletRequest - and provides access to Sling-specific things like resource, path info, selector, etc.

response

SlingHttpServletResponse object, providing access for the HTTP response that is created by the server. This is currently the same as the HttpServletResponse from which it extends.

sling

SlingScriptHelper, containing convenience methods for scripts, mainly sling.include('/some/other/resource') for including the responses of other resources inside this response (eg. embedding header html snippets) and sling.getService(foo.bar.Service.class) to retrieve OSGi services available in Sling (Class notation depending on scripting language).

resource

Current Resource to handle, depending on the URL of the request. Same as request.getResource().

reader

Direct access to the Reader of the request - same as request.getReader(). Use it for reading the data of an HTTP request body.

out

Direct access to the PrintWriter of the response - same as response.getWriter(). Use it for writing to the HTTP response body.

flush

Indicates whether the output used by the script shall be flushed after the script evaluation ended. It is a Boolean, so use TRUE for flushing or FALSE for not flushing, which is the default value. The boolean value notation depends on the scripting language.

log

Provides an SLF4J Logger for logging to the Sling log system from within scripts, eg. log.info("Executing my script").

See also the api documentation of the org.apache.sling.api.scripting.SlingBindings.java which defines the common scripting variables.

This list can be expanded by bundles. See Adding New Scripting Variables for information.

In addition currently the currentNode binding is supported by most scripting languages. If the current resource points to a JCR node (which is typically the case in Sling), this gives you direct access to the Node object. Otherwise this object is not defined. However, we discourage using this variable as this directly binds you to the jcr api and makes your script unusable with other data sources supported by Sling. The better approach is to rely on the resource and the value map. Have a look at the ResourceUtil class for more information.

JSP

Since JSPs already have a few Java-objects pre-defined, things have to be named differently here. And you will have to explicitly require the variables to be defined with a custom tag <sling:defineObjects />. Your jsp should start with:

<%@ page session="false" %>
<%@ page import="javax.jcr.*,
        org.apache.sling.api.resource.Resource"
%>
<%@ taglib prefix="sling" uri="http://sling.apache.org/taglibs/sling/1.0" %>

<sling:defineObjects />

slingRequest

SlingHttpServletRequest object, providing access to the HTTP request header information - extends the standard HttpServletRequest - and provides access to Sling-specific things like resource, path info, selector, etc.

slingResponse

SlingHttpServletResponse object, providing access for the HTTP response that is created by the server. This is currently the same as the HttpServletResponse from which it extends.

request

The standard JSP request object which is a pure HttpServletRequest.

response

The standard JSP response object which is a pure HttpServletResponse.

resourceResolver

Current ResourceResolver. Same as slingRequest.getResourceResolver().

sling

SlingScriptHelper, containing convenience methods for scripts, mainly sling.include('/some/other/resource') for including the responses of other resources inside this response (eg. embedding header html snippets) and sling.getService(foo.bar.Service.class) to retrieve OSGi services available in Sling (Class notation depending on scripting language).

resource

Current Resource to handle, depending on the URL of the request. Same as slingRequest.getResource().

log

Provides an SLF4J Logger for logging to the Sling log system from within scripts, eg. log.info("Executing my script").

bindings

Provides access to the SlingBindings object for access to non-standard scripting variables.

In addition currently the currentNode binding is supported. If the current resource points to a JCR node (which is typically the case in Sling), this gives you direct access to the Node object. Otherwise this object is not defined. However, we discourage using this variable as this directly binds you to the jcr api and makes your script unusable with other data sources supported by Sling. The better approach is to rely on the resource and the value map. Have a look at the ResourceUtil class for more information.

The names of the JSP scripting variables can be altered by passing attributes to the sling:defineObjects tag using these attributes:

Variable Name

Attribute Name

slingRequest

requestName

slingResponse

responseName

resource

resourceName

currentNode

nodeName

sling

slingName

resourceResolver

resourceResolverName

log

logName

bindings

bindingsName

For example, to specify that the Logger object should be available as a scripting variable named logger (instead of log):

<sling:defineObject logName="logger"/>

Resource Inclusion

Instead of sling.include("/path/to/resource") you can use the sling taglib for that:

<sling:include path="/path/to/resource" /> 

For more options of the sling taglib see the tag lib definition file.

ESP

Sling's ESP (ECMAScriptPages) language is based on Mozilla's Rhino javascript interpreter.

Scripts are transformed by a simple FilterReader, in the org.apache.sling.scripting.javascript bundle.

There's a number of .esp script examples in Sling's integration tests and samples.

Here's a few of the objects and methods available in an ESP file:

html.esp
<html>
<head><title>Sling ESP reference documentation</title>
</head>
<body>
	
<h2>Sling ESP documentation (work in progress)</h2>
<p>Have a look at this file's source or at Sling's ScriptableNodeTest.java</p><br/>
	
<%= 'tags: use \<%=  %\> to evaluate, \<%  %\> otherwise.' %>
<%  'e.g. this will not be printed'; %><br/>
<%

// create a new node under currentNode
var n = currentNode.addNode('n');
prt('path of n: ' + n.getPath());

// create new node and specify node type
var n2 = n.addNode('n2', 'nt:folder');

// set and get property
n.setProperty('thename', 'thevalue');
prt('get prop thename: ' + n['thename']               ); // thevalue
prt('another way: '      + n.thename                  ); // thevalue
prt('get type of n2:  '  + n2['jcr:primaryType']      ); // nt:folder
prt('test type of n2: '  + n2.isNodeType('nt:folder') ); // true

// iterate over properties
var props = n.getProperties();
for(i in props) { 
  prt('getProperties(): ' + props[i].name + ': ' + props[i].value.string); 
}

// getNodes()
n.addNode('abcd');
n.addNode('abcdef')
n.addNode('abcdefgh');
prt('get all nodes: ' +n.getNodes().length         ); // 4, incl n2	
prt('get abcd: '      +n.getNodes('abcd').length   ); // 1, abcd
prt('get abcde*: '    +n.getNodes('abcde*').length ); // 2, abcdef and abdefgh

// remove()
n.getNode('abcd').remove();
prt('removed abcd node ' + n.hasNode('abcd'));				// false

// get the root node (3 ways)
prt( currentNode.getAncestor(0));
prt( currentNode.session.getRootNode());
prt( currentNode.getSession().getRootNode());

// include the rendered result of another node (see Sling in 15 minutes)
// sling.include("/content/header", "forceResourceType=wiki.page,replaceSelectors=edit,replaceSuffix=validation");

function prt(s) { out.print(s+'<br/><br/>'); }
%>
</body>
</html>

Groovy

An enhanced version of the GET.groovy script from http://sling.apache.org/site/groovy-support.html that shows all the variables and a little of what's groovy about Groovy.

response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");

log.info "Groovin' on ${resource}"

def mb = new groovy.xml.MarkupBuilder(out)

mb.html {

   // Shouldn't javax.jcr.Property.getString() take care of this for us?
   def formatMultipleValues = { prop ->
      if (prop.definition.isMultiple()) {
         prop.values.string.join('; ')
      } else {
         prop.string
      }
   }
   
   def tableForMap = { cap, map ->
      table {
         caption { h2 cap }
         tr { th 'property' ; th 'value' }
         map.each { key, value -> tr { td key ; td value } }
      }
   }

   meta {
      title 'Groovy Scripting Sample for Sling'
   }
   body {
      h1 "Hello World !" 
      p "This is Groovy Speaking" 
      p "You requested the Resource ${resource} (yes, this is a GString)"

      // If we get called on a system file, then there won't be a currentNode binding.
      if (this.binding.variables.containsKey('currentNode')) {
         table {
            caption { h2 'Current Node Properties' }
            tr { th 'property' ; th 'value' }
            currentNode.properties.each { prop -> tr { td prop.name ; td formatMultipleValues(prop) } }
         }
      }
      tableForMap 'Resource Properties', resource.properties
      tableForMap 'Script Bindings', this.binding.variables
      tableForMap 'Request Properties', request.properties
   }
}

And what's up with the Java Content Repository API not using the Java Collections API? A repository is a collection after all. Not very groovy...

Here's another example of using Groovy's MarkupBuilder with Sling http://n1ceone.blogspot.com/2008/09/using-groovy-builders-in-sling.html.

  • No labels

2 Comments

  1. Anonymous

    It would be great if someone integrate freemarker here. As I remember there was some activity on that ...

  2. Anonymous

    Link class names to their Javadoc instead of sources.