The official documentation is at: http://docs.alfresco.com
This document details the JavaScript API for Alfresco 5.0. See also the JavaScript Services API.
If you are looking for details on Alfresco 4.0, 4.1, 4.2: 4.0_JavaScript_API.
The Alfresco JavaScript API allows script writers to develop JavaScript (ECMA Script) 1.7 compatible files that access, modify, and create Alfresco repository objects. It provides a clean and simple object-oriented API to well known Alfresco concepts such as Nodes, Properties, Associations, and Aspects. The API is similar to the Alfresco Template API - with a significant difference in that it allows modification and creation of nodes, aspects, and properties.
Using the API script writers can:
In addition, scripts can create new files, folders, or nodes of any type, copy/move/delete nodes and create/modify/remove child and target associations between nodes. All the usual Alfresco security and ACL permissions apply.
Scripts can also include (or 'import') other scripts. The developer can build libraries of scripts that are included at runtime to reduce copy/paste between script files.
As JavaScript is a standards based language (also known as ECMA Script) there are many web resources, online tutorials and books to help developers in writing JavaScript files. It is suggested that potential script writers read up on JavaScript resources before attempting to script the Alfresco repository.
A good general JavaScript reference can be found on the Mozilla site.
The integrated JavaScript engine in Alfresco utilises the Mozilla Rhino JavaScript Engine for Java. This allows JavaScript 1.7 (ECMA Script) files to access Alfresco Java objects using a simple bean-style notation and interpreted mode execution without compiling to external class files.
A mechanism for adding and configuring additional scripting engines exists. It is possible to completely replace or augment the existing script engines with others such as PHP or Ruby. The correct scripting implementation will be automatically selected by the ScriptService when executing a script file based on the file extension of the script being executed. If it cannot resolve the engine to use, then the developer can specify it explicitly when calling the ScriptService. By default only JavaScript is available and this is the API documented here. However a Java-based PHP scripting engine is also provided as an additional AMP download.
Note: There are many example scripts illustrating the API in the JavaScript_API_Cookbook.
Rhino 1.7 is now being used as the JavaScript engine - it is generally faster than Rhino 1.6 but has some subtle differences in the way it handles Strings internally. This can in certain rare circumstances break existing WebScript code. This can happen where JavaScript-based scripts pass a string to the model, prior to it being passed to the FreeMarker template. The string must be fully converted, using the toString() method. If you notice that previously working web scripts no longer work, then this possible reason should be investigated. See ConsString issue: https://issues.alfresco.com/jira/browse/ALF-20856
'session' object was renamed to 'sessionticket' as it was only supplying user ticket and was incorrectly shadowing the true HttpSession 'session' API in the model.
'session' is now working correctly in WebScript JS API - providing access to the actual servlet web-session for the current user.
Since Alfresco 2.1 JavaScript has been the default scripting language for the Web Scripts REST API. The API detailed in this document is relevant for both plain JavaScript files executed in the original Alfresco Web Client (i.e. via folder Rules) and for Web Scripts that execute JavaScript within the repository.
Web applications built on the Alfresco SURF platform make extensive use of Web Scripts but they do not execute directly within the context of an Alfresco repository, instead they execute within a remote 'presentation tier' i.e. a new web application on a separate web-tier. The API available in the new presentation tier is completely different and more orientated towards managing remote invocations of data Web Scripts that live in the repository tier. Therefore it does not provide direct access to nodes and properties, but instead provides a mechanism to execute data Web Scripts remotely and retrieve and manipulate the data response.
The API available to JavaScript based WebScripts on the presentation tier is detailed in the SURF Platform - FreeMarker and JavaScript API page. A large number of presentation tier WebScript examples can be found in the Slingshot project at the path projects\slingshot\config\alfresco\site-webscripts. The Slingshot project can be found in the Alfresco public SVN server or SourceForge project page.
When creating Alfresco repository tier data Web Scripts, service based JavaScript APIs are available to the developer. They are detailed in the 5.0 JavaScript Services API page. A large number of repository tier data WebScripts examples can be found in the Remote API project in the path projects\remote-api\config\alfresco\templates\webscripts. The Remote API project can be downloaded from SVN or SourceForge.
JavaScript can also be used to build business logic for Workflow.
Script files can be stored either on the ClassPath (for example, in alfresco/extension/myscripts) or in a repository store. Scripts are also stored in the default repository in the Company Home/Data Dictionary/Scripts location. Scripts in this location can be accessed directly by users via the Execute a script action. Scripts in any repository location can be accessed by any user via REST URL if they have the appropriate read permissions on the script document. Scripts on the ClassPath can be imported into other scripts but not executed directly in the web client.
This feature allows libraries of scripts to be built and used by other scripts at runtime. The syntax to import the scripts is specific to Alfresco and not a feature of standard JavaScript. For example, the <script src='...'>
syntax you may be familiar with, as supported by most web browsers, is not part of standard ECMA JavaScript and will not work!
The syntax to import other scripts is very strict and must be followed exactly or the import may fail. Import directives must be the first lines in the JavaScript file - no code or comments are allowed above those lines. Only the following syntax variants are supported:
Import a script from the repository via name based path:
<import resource='/Company Home/Data Dictionary/Scripts/library.js'>
Import a script from the repository via a NodeRef reference:
<import resource='workspace://SpacesStore/6f73de1b-d3b4-11db-80cb-112e6c2ea048'>
Import a script from a Java ClassPath location:
<import resource='classpath:alfresco/extension/myutils.js'>
Multiple script import of the same script content and circular dependencies are dealt with. A script can import several other scripts from multiple different locations, that is, a script from the repository and another from the classpath.
After the import lines, usual JavaScript code and comments may begin - the imports must be first lines in the file.
The Alfresco JavaScript API provides a rich set of scriptable Java objects that are available to the script writer. Many 'root' scope objects (see below) are provided by default, such as access to the user home folder, company home folder, search, People API and logging functionality. It is possible to configure in additional root scope objects for use by your own scripts, see the section on adding custom Script APIs.
Most root objects are known as Script Node objects that wrap the common Alfresco repository concepts such as nodes, aspects, associations, and properties. They also provide access to common services through an object-oriented API.
If you are accessing the script engine either through a rule/action (Execute a Script) in the Web Client or through the Script Command Processor then the following objects are available by default in the root scripting scope:
companyhome | The Company Home Script Node. |
---|---|
userhome | Current user Home Space Script Node. |
person | Script Node representing the current user Person object. |
space | The current space Script Node (if any). Note that for a script executing from a rule, the space object will be the space that the rule resides in, this may not be the space you are expecting if the rule is inherited. |
document | The current document Script Node (if any). |
script | The Script Node representing the script object itself. Not present if the script is loaded from the Java ClassPath. Other useful root scope objects provided by default. |
args | An associative array of any URL parameters passed via the Script Processor Servlet (only available if the script was executed via the script servlet). |
search | A host object providing access to Lucene and Saved Search results. See the Search API section. |
people | A host object providing access to Alfresco people and groups. See the People API section. |
actions | A host object providing invocation of registered Alfresco Actions. See the Actions API section. |
logger | A host object providing access to console logging facilities for debugging of scripts. See the Logging API section. |
session | Session related information such as the current authentication ticket. See the Session API section. |
classification | Access to the root elements of the classification API. See the Classification API section. |
utils | Access to a library of useful helper functions not provided as part of generic JavaScript. See the Utility Functions section. |
invitations | The root of invitations api. Providing access to invitations for web sites (and in future other resources) Invitations |
groups | The root of group authorities. Providing access to groups Groups |
transfer | The root of transfer service. Providing access to the transfer service Transfer |
sites | The root of sites service. Providing access to the sites service Sites |
The default model objects can be accessed directly from the root of a script scope and follow the standard JavaScript pattern of property dot notation style syntax, for example:
var name = userhome.properties.name
Here the variable name is populated by accessing the properties property and the name value within it.
The node children/association/aspect model is built dynamically as required. For example, you can write statements that walk multiple node collections such as:
userhome.children[1].children[0].children[2].name
The companyhome, userhome, document, space, and person objects represent Alfresco Node objects and provide access to the common Alfresco concepts such as properties, aspects, and associations. The following Node API is available to use within scripts:
var name1 = userhome.properties.name
var name2 = userhome.properties['name'];
var name3 = userhome.properties['cm:name'];
var name4 = userhome.properties['{http://www.alfresco.org/model/content/1.0}name'];
A useful feature is that properties of type d:noderef are automatically converted into another ScriptNode object. This means the script writer can dynamically walk the object hierarchy for a node. For example, if a document node has a NodeRef property called 'locale' you could execute the following to retrieve the name of the node the property references:
var locale = document.properties.locale.properties.name;
If you wish to retrieve the NodeRef value for a d:noderef property, then the following code will work:
var localeNoderef = document.properties.locale.nodeRef;
In addition, any properties of type d:content are converted to special ScriptContent objects that themselves feature an API to get or modify the content, mimetype, size and url for the content property. For example:
var mimetype = document.properties.content.mimetype;
var content = document.properties.content.content;
As most documents are derived from the default Content Model type cm:content, shortcut APIs are provided for content, mimetype, size and url for the cm:content property, for example:
document.content = 'some new text content';
var mimetype = document.mimetype;
var url = document.url;
Properties can be modified and new properties added, see the Modifying and Creating API section below.
children | A readonly JavaScript Array of the child nodes. For example mynode.children[0]. Note that since Alfresco 2.1, all methods that returns lists of data now return true JavaScript Array objects rather than simple Java lists. This means standard JavaScript 1.6 syntax for each and for each in can be used to iterate the results. |
---|---|
assocs | A readonly associative array (map) of the target associations of the node. Each named entry in the array contains an Array of the ScriptNode objects on the end of the association. For example: mynode.assocs['cm:translations'][0]. |
sourceAssocs | A readonly associative array (map) of the source associations to this node. Each named entry in the array contains an Array of the ScriptNode objects on the start of the association. For example: mynode.sourceAssocs['cm:translations'][0]. |
childAssocs | A readonly associative array (map) of the child associations of the node. Each named entry in the array contains an Array of the ScriptNode objects on the end of the association. For example:myforumnode.childAssocs['fm:discussion'][0]. |
parentAssocs | A readonly associative array (map) of the parent associations of the node. Each named entry in the array contains an Array of the ScriptNode objects on the end of the association. For example:mynode.parentAssocs['cm:contains'][0]. |
aspects | A readonly array of the aspects (as fully qualified QName strings) applied to the node. (This is returned as a Java HashSet) |
isContainer | returns true if the node is a folder node, false otherwise. |
isDocument | Returns true if the node is a content node, false otherwise. |
content | The content of the node on the default cm:content property as a string value. This value can be modified to update the content of the node, see the Modifying and Creating API section below. |
url | The readonly url to the content stream for this node. |
downloadUrl | The readonly url to the content stream for this node as an HTTP1.1 attachment object. |
webdavUrl | The WebDav cm:name based path to the content. |
mimetype | The mimetype encoding for content on the default cm:content property attached to this node. |
size | the readonly size in bytes of content on the default cm:content property attached to this node. |
displayPath | The readonly display path to this node. NOTE: care must be taken when accessing the display path if the current user does not have permissions to view all of it. A fix has been made in Alfresco 2.1.1E so that the display path can always be obtained safely for any user. |
qnamePath | The readonly (qname) path to this node. (sorry, available 2.1 Enterprise onwards) |
icon16 | The readonly small icon image for this node. |
icon32 | The readonly large icon image for this node. |
isLocked | Return true if the node is locked. Otherwise, it is false. |
id | GUID for the node. |
nodeRef | NodeRef as a string for the node. |
name | Shortcut access to the cm:name property. |
type | Fully qualified QName type of the node. |
typeShort | Prefix string, or 'short' QName type of the node. |
parent | The primary parent node, can be null if this is the root node. NOTE: care must be taken when accessing the parent node if the current user does not have permissions to view it. Note that the parent node can always be obtained to allow a hasPermission() check to be applied before accessing properties etc. of it in a script. |
parents | An array of the parent nodes. Note that the parent node can always be obtained to allow a hasPermission() check to be applied before accessing properties etc. of it in a script. |
isCategory | true if this is a category node and false otherwise. See the Classification API section. The following Node API functions are provided to help locate child nodes using an XPath or Name based path: |
Node childByNamePath (string path) | Performs an xpath based on the name property of the nodes and returns a Node found at the specified path. The path is relative to the current node. If the named node is found then it is returned, else null is returned. For example: var testingFolder = userhome.childByNamePath('QA/Performance/Testing');. |
Array childrenByXPath (string xpath) | Performs an xpath based query search and returns an array of the nodes found. The XPath search is relative to the current node. An empty array will be returned if no results are matched. For example: var nodes = userhome.childrenByXPath('*[@cm:name='Finance Documents']/*');. |
Array activeWorkflows | Returns an array of all active workflows this node is involved in. If the node is not part of an active workflow, null is returned. Items in the returned array are of type JscriptWorkflowInstance. |
boolean isScriptContent(object obj) | Returns true if the supplied node property value is a ScriptContentData object. |
string getSiteShortName() | Returns the short name of the site this node is located within. If the node is not located within a site null is returned. |
The following values are available but are only required for special use cases. You can safely ignore these if you do not know what they mean.
Most of the available ScriptNode API returns read-only values, however the real power of the scripting API can be found in the support for writable objects and access to Alfresco Repository services through this API. The ScriptNode object allows modification of properties, adding new properties, adding aspects, creating new files, folder, and custom type nodes, and of course, updating and setting the text content stream for a node. In addition, it is possible to perform powerful features such as deleting nodes, transforming content, executing templates, and modifying the associations for a node.
// change the name of this document
document.properties.name = 'Backup of ' + document.properties.name;
// add a new property string
document.properties['cm:locale'] = mylocalenode;
// save the property modifications
document.save();
Important: The node.save()
API call is needed to persist the property modifications - all other modifications made using the API (such as content or adding aspects) take immediate effect.
It is important to note that JavaScript objects are different to native repository Java objects. Property values in the repository must be of the correct object type as defined in the Data Dictionary and exposed by the content model. So a String property value expects a Java String and a multi-valued property expects a List. The Alfresco JavaScript API will perform the conversion of most object types between JavaScript and Java and visa-versa for you, for example Array (for a multi-value property), numbers, dates, boolean, and strings. The conversion code handles all common type conversions and recursive lists of those types.
var props = {};
props['cm:template'] = myTemplateNode.nodeRef;
document.addAspect('cm:templatable', props);
The ScriptContent API provides several functions and properties related to node properties of type d:content, for example, document.properties.content.
content | A read/write value that represents the content as a string. |
---|---|
write(ScriptContent content) | Copy the content from the specified ScriptContent. |
mimetype | A read/write string value that represents the mimetype of the content. |
guessMimetype(string filename) | Guess and apply the mimetype to the content based on the given filename. |
guessEncoding() | Guess and apply the encoding to the content based on the current content. Uses the ContentCharsetFinder service. |
encoding | A read/write string value that represents the encoding of the content. |
size | A readonly long value that represents the size in bytes of the content. |
url | A readonly string representing the download url for the content. |
downloadUrl | A readonly string representing the download (as attachment) url for the content. |
The ScriptNode API features several functions and properties related to permissions in the repository. It is a common use case to check for the appropriate user permissions on a node before attempting to access or modify it.
org.alfresco.service.cmr.security.PermissionService
. Most commonly used permission checks are 'Read', 'Write', 'Delete' and 'CreateChildren'.The checkin/checkout ScriptNode API features methods for checkout, checkin and cancelling checkout of working copies. Note that you may wish to first add the cm:versionable aspect to a node if you wish version history to be recorded when using these methods.
The ScriptNode versions API provides functions and properties for managing and retrieving the versions of a document.
The ScriptVersion API represents a specific version snapshot of a document.
The following ScriptNode functions make use of the document transformation services available in Alfresco. The OpenOffice server is required for some document transformations.
The following functions make use of the image transformation services available in Alfresco. The ImageMagick components will need to be installed correctly and working. Note that detailed information on the ImageMagick options mentioned in the methods below can be found on the ImageMagick website.
The following functions make use of the FreeMarker template processing services available in Alfresco. The result of the template execution is returned as a string from each function. Note that the node is used as the context to the template. If this node is a document, it will be setup as the 'document' context object for the template, with the parent space setup as the 'space' context object for the template, if it is a folder then it will be setup only as the 'space' context object for the template. An argument list can also be passed to the template - and will be available as the 'args' object, see Template Default Model page for more information on template models and the 'args' object.
Repository and REST service for automatic thumbnailing of content The ScriptNode object allows JavaScript access to CRUD operations for thumbnailing. See the Thumbnail Services API page for full details.
Repository and REST service for Web 2.0 style tagging of content is available. The ScriptNode allows JavaScript access to CRUD operations for tagging. See the Tagging Services API page for full details.
The Search API provides direct access to repository level Lucene search results and Saved Search results. It is accessable via the 'search' root scope object. Note that local searches can be performed using the ScriptNode APIs childByNamePath and childByXPath as detailed above.
Like the various node objects, the search object is part of the root scope available to script writers. The API provides the following functions:
search
{
query: string, mandatory, in appropriate format and encoded for the given language
store: string, optional, defaults to 'workspace://SpacesStore'
language: string, optional, one of: lucene, xpath, jcr-xpath, fts-alfresco, cmis-alfresco, cmis-strict - defaults to 'lucene'
templates: [], optional, Array of query language template objects (see below) - if supported by the language
sort: [], optional, Array of sort column options (see below)
page: object optional, paging information object (see below) - if supported by the language
namespace: string, optional, the default namespace for properties (default is 'cm')
defaultField: string, optional, the default field for query elements when not explicit in the query
onerror: string optional, result on error - one of: exception, no-results - defaults to 'exception'
}
sort
{
column: string, mandatory, sort column in appropriate format for the language
ascending: boolean optional, defaults to false
}
page
{
maxItems: int, optional, max number of items to return in result set
skipCount: int optional, number of items to skip over before returning results
}
template
{
field: string, mandatory, custom field name for the template
template: string mandatory, query template replacement for the template
}
Note that only some query languages support the query template feature, such as 'fts-alfresco'.
See the following documentation for more details http://wiki.alfresco.com/wiki/Full_Text_Search_Query_Syntax#Templates
The search definition object an be as simple to use as:
var results = search.query({query: 'TEXT:alfresco'});
Or as richly defined as:
var sort1 =
{
column: '@{http://www.alfresco.org/model/content/1.0}modified',
ascending: false
};
var sort2 =
{
column: '@{http://www.alfresco.org/model/content/1.0}created',
ascending: false
};
var paging =
{
maxItems: 100,
skipCount: 0
};
var def =
{
query: 'cm:name:test*',
store: 'workspace://SpacesStore',
language: 'fts-alfresco',
sort: [sort1, sort2],
page: paging
};
var results = search.query(def);
Multi-column sorting and any of the Alfresco search languages are supported through this interface. The search definition objects may be extended with additional properties in future versions of the API but backward compatibility will be maintained.
The People API provides access to Alfresco people and groups. The API provides the following functions:
Details of the API to workflow can be found in the Workflow documentation.
A root level object 'actions' is provided that allows invocation of Alfresco Actions registered with the Repository.
A ScriptAction represents an Alfresco Action registered within the Repository.
// create mail action
var mail = actions.create('mail');
mail.parameters.to = 'davidc@alfresco.com';
mail.parameters.subject = 'Hello from JavaScript';
mail.parameters.from = 'davidc@alfresco.com';
mail.parameters.template = root.childByNamePath('Company Home/Data Dictionary/Email Templates/notify_user_email.ftl');
mail.parameters.text = 'some text, in case template is not found';
// execute action against a document
mail.execute(doc);
A root level object 'logger' is provided that provides functions to aid debugging of scripts.
log4j.logger.org.alfresco.repo.jscript.ScriptLogger
should be set to DEBUG
. This can be applied in the log4j.properties file (TomCat) or log4j.xml file (JBoss) on the Alfresco server.A root level object 'sessionticket' is provided to access to the current logged in user session ticket as a string value.
A root level object 'session' is provided to access the servlet web session access.
There are two parts to the API: manipulating classifications and manipulating the categories that they contain. A root level object 'classification' is provided to return category nodes. The CategoryNode objects returned from the functions are extended from the standard JavaScript ScriptNode model to include category manipulation.
The CategoryNode object API.
A root level object 'utils' is provided as a library of helper functions that are missing from generic JavaScript.
Example Scripts Page.
The Alfresco Server provides a built-in server-side JavaScript debugger which allows line by line step through, variable inspection and arbitrary script execution.
Note:
To enable and disable the JavaScript debugger use the following URL (you must be logged in as an administrator):
http://<host>:<port>/alfresco/service/api/javascript/debugger
This URL displays the current status of the debugger and allows you toggle between enabled and disabled.
When enabled, the JavaScript Debugger window is displayed. Upon execution of any server-side JavaScript, the debugger will intercept and stop execution at the first JavaScript statement. You can then step through, view variables etc or resume execution. When disabled, server-side JavaScript is executed without interruption.
The Script Service is a typical Alfresco repository service accessed via a Spring managed bean with the name of ScriptService.
Only developers will be interested in accessing the ScriptService directly, those more interested in simply writing scripts themselves should skip this section and jump to Scripting API.
The available scripting engines can be configured in the Alfresco Spring config file script-services-context.xml. You should download the Alfresco SDK to examine the structure of this file.
It is possible to completely replace or augment the existing JavaScript implemenation with others such as PHP or Ruby. The correct script engine implementation will be automatically selected by the ScriptService when executing a script based on the file extension of the script being executed. If it cannot resolve the engine to use, then the developer can specify it explicitly when calling the ScriptService.
Further engines can be added by developers. Examining the script-services-context.xml for configuration examples. The engine must implement org.alfresco.service.cmr.repository.ScriptProcessor
interface and it is recommend to extend the org.alfresco.repo.processor.BaseProcessor
abstract class and override the various execute() methods.
A Java based PHP engine has been integrated and is an example of this, it is available as an AMP download for addition into an existing Alfresco installation.
It is possible to create and add custom script API's implemented in Java and accessible as root objects in JavaScript. This provides an integration point for Alfresco extensions to provide custom API's where appropriate.
In order to implement a custom JavaScript API it is recommended that you develop a POJO (Plain Old Java Object) that extends the base class org.alfresco.repo.processor.BaseProcessorExtension
. The public methods of your class will be those that will be accessable from JavaScript. (For example see org.alfresco.repo.jscript.ScriptLogger
).
Once complete, you must then configure your bean in Spring. Make use of the baseJavaScriptExtension parent bean definition in order to ensure your object is automatically registered with the ScriptService framework. The name of the object as it will appear to script writers must also be specified in the bean definition.
The following example shows the bean definition for the ScriptLogger custom API.
<bean id='loggerScript' parent='baseJavaScriptExtension' class='org.alfresco.repo.jscript.ScriptLogger'>
<property name='extensionName'>
<value>logger</value>
</property>
</bean>
Since this is a standard Spring bean definition any additional services that are required can be injected as properties into the bean definition in the usual way.
Once this bean have been loaded the custom API object will be accessible directly in JavaScript by calling the public methods on the named object. For example the following shows how the log method can be called on the logger API we have defined above.
...
logger.log('This is a log message.');
...
In some cases you may find that you're unable to satisfy a requirement using the Javascript API, but that a Java API (perhaps the Alfresco Foundation Services API contains facilities that would allow you to do so.
Using the method described in Adding Custom Script APIs, it is possible to add additional root scope objects to Javascript. In the case of the Alfresco Foundation Services API the only object that needs to be injected is the ServiceRegistry (or a proxy of it) - an example implementation of this may be found at Configuring the ServiceRegistry as a Javascript Root Object.
JavaScript stored in the classpath (e.g. in the file system at the extension directory) can also leverage the Rhino Javascript interpreter's native Java integration facilities (see the Rhino documentation for more details).
However, for security reasons these mechanisms are completely disabled for Javascript scripts that are stored in the repository. This means that the Javascript file has to be stored in the filesystem to be able to access the Native Java API.
Note that there are some important things to keep in mind when calling native Java APIs from Javascript:
var value1 = javaMap['key1']
var value2 = javaMap.key2
You must call the underlying Java methods instead:
var value1 = javaMap.get('key1')
var value2 = javaMap.get('key2')
Please note that these techniques are solely intended for developers who wish to take advantage of the productivity benefits of a scripted language while still having access to the full power of native Java APIs. They should not be used for end user scripting scenarios (eg. end user developed custom actions uploaded to the repository, workflow scripts, etc.).
Return to Developer Guide