Skip to content

Writing and executing scripts

Content Script scripts are "document" class objects stored on Content Server. The primary usage for a script is its execution. When you "execute" a script, you are basically programmatically invoking a series of APIs that perform actions over Content Server's or other systems' data. In the following paragraphs, we are going to analyze all the Content Script architecture's elements and components that play a role in turning a textual file into an actionable object.

As said, scripts are persisted as "documents" on Content Server. Whenever you execute a script a component named Script Manager retrieves the script's last version and, either compiles it (and caches the compiled version) or loads a pre-compiled version of it for execution. Scripts' execution is managed by another component named Content Script Engine. The Content Script Engine executes the script's code against the provided execution context (the execution context is the "container" through which the script's code can access the Content Script's services, environment variables, support variables, database, etc..). The internals of both the Script Manager and the Script Engine are not relevant for the purpose of this manual and won't be discussed.

API Services

Content Script API Service

Content Script APIs are organized in classes denominated services. Each Content Script API service acts as a container for a set of homogeneous APIs (API releated to the same kind of objects or features). Content Script APIs can be extended creating and registering new services.

Content Script APIs are, in their most essential form, the methods exposed by the service classes. In order to be recognize as a Content Script API a service class method must be decoretad with the @ContentScriptAPIMethod annotation.

Content Script API Services Interfaces

When working with Content Script APIs developers program against interfaces. As a matter of fact all Content Script API services and objects implement one or more interfaces. Implementation classes can be easily distinguished from their interfaces because their name ends with the "Impl" suffix.

Content Script API Objects

Content Script APIs return or accept, as parameters, objects representing OTCS objects or features. In Content Script, these objects are referred to as Content Script API objects. Content Script API objects are active information containers. We define them active because they expose APIs designed to manipulate the information stored in themselves.

In order to be recognize as a Content Script API Object a class must be decoretad with the @ContentScriptAPIObject annotation.

When the script Execution Context is initialized by the Content Script engine, all registered API services are injected into it. These services allow a Content Script to perform operations on Content Server, to use internal utilities (such as PDF manipulation utilities or the templating service), to access external systems and services, etc.

Here after are some of the main services that are currently available as part of Content Script APIs.

API Service Name Description
Base API Base API is constituted by methods and properties that are exposed directly by each script. Some of the most important API are: logging, redirection (used to redirect users navigation through a server side redirection i.e. http code 302, outputting HTML, XML, JSON and Files)
Core Services
admin The admin service allows to programmatically perform administrative tasks. With the admin service is it possible, among other things, to: perform XML import/export operations, programmatically schedule/unscheduled Content Script executions
collab The collab service is the main access point to the Content Server collaborative functionalities. With collab service is it possible, among other things, to: create and manage projects, tasks and milestones, create and manage discussions, list and manage users’ assignments
distagent The distagent service provides functionality for: scheduling and unscheduling of scripts, comprehensive configuration management. distagent supports the definition of MapReduce type of Jobs (referred to as "Chain Jobs"), which allows users to configure behaviors for each phase of the job:Split: Define how to partition the data. Map: Specify the processing for each partition. Reduce: Aggregate the results from the map phase. Finalize: Conclude the job with any post-processing steps required.
docman The docman service is the main access point to the Content Server Document Management functionalities. With docman service it is possible, among other things, to: create and manipulate documents and containers, access and modify meta-data, access and modify object permissions, access volumes, perform database queries, manipulate renditions and custom views, run reports, consume OScript request handlers, programmatically import/export content through Content Server native XML import/export feature
mail The mail service allows to programmatically create/send and receive emails from scripts. With the mail service is it possible, among other things, to: create and send email message through multiple mailboxes, scan mailboxes and retrieve incoming messages and attachments, create email messages (both html and text messages are supported) with custom templates, send email to internal users and groups, attach files and Content Server documents to emails, configure multiple email service profiles to use different IMAP/SMTP configuration at the same time
search The search service allows to programmatically search over Content Server's repository. With the search service is it possible, among other things, to: easily build/execute complex search queries programmatically, easily build/execute query based on categories attributes, retrieve search result with or without pagination
users The users service is the main collector for all APIs related to Content Server users and groups. With users service is it possible, among other things, to: create/modify/delete users and groups, impersonate different users, access and modify user privileges, perform member searches
template The template service can come in handy anytime you have to dynamically create documents. With the template service is it possible, among other things, to: evaluate documents and plain text strings as templates, replace place holders and interpret template-expressions
workflow The workflow service allows to programmatically manipulate workflows. With the workflow service is it possible, among other things, to: start, stop, suspend, resume, delete workflows, access and manipulate workflow and task data, accept, complete, reassign workflow tasks, perform searches within workflows and tasks, change workflows' and steps' title
adlib The adlib service allows to programmatically drive the AdLib rendition engine. With adlib service it is possible, among other things, to: create jobs for AdLib PDF Express Engine and fetch renditions results
amgui The amgui service is designed to control the visibility of elements within the Classic UI upon the execution of a content script, and it facilitates the retrieval of format specifications for certain data types, such as dates. It also handles the data structures inherent to the Classic UI, enabling the creation of custom pages and reports. Furthermore, amgui is instrumental in generating SmartView session tickets and provides programmatic access to the form builder for server-side creation of Beautiful Webforms views.
amsui The amsui service is primarily utilized by the Smart Pages module to ascertain which enhancements, such as commands, actions, panels, and columns, should be activated in the SmartView and their respective locations. Additionally, amsui is responsible for the server-side rendering of Smart Pages as well as generating Smart View session tickets, which are essential for the integration of Smart View-related widgets within Beautiful WebForms and Smart Pages.
aws The aws service provides an interface for accessing and managing Amazon EC2 instances and S3 storage services. It enables the management of S3 buckets and the orchestration of EC2 resources, streamlining cloud operations within Amazon's extensive infrastructure.
blazon The blazon service is designed to facilitate programmatic access to the OpenText Blazon rendition engine, enabling developers to create and manage rendition jobs. This service allows for the programmatic initiation of jobs and their management in both synchronous (waiting for job completion) and asynchronous modes. It grants full access to the Blazon API suite, encompassing a comprehensive range of rendition and transformation capabilities.
cache The cache service provides interaction capabilities with the distributed Memcache service, offering APIs to store and retrieve data applicable to individual users or the entire Content Server population. This service simplifies the integration within Content Script objects, such as CSNode nodes, through a well-designed API set that streamlines cache usage in the context of content management operations.
classification The classification service is the main access point to the Content Server classification features. With classification service is it possible, among other things, to: access, apply, remove classifications from objects
core The core service is tailored to offer simplified access to integrated core services, including 'share' and other essential components. This service streamlines the process of interfacing with the fundamental functionalities of our system, enhancing developer efficiency and system integration.
docbuilder The docbuilder service acts as a wrapper around an enhanced version of the (Groovy Document Builder library). This service facilitates the creation of both PDF and Word documents, with the capabilities for generating Word documents being significantly extended beyond those offered by the underlying library.
docx,xlsx The docx/xlsx services allow to programmatically manipulate Microsoft Office documents. With docx/xlsx services is it possible, among other things, to: create and manipulate Word, PowerPoint and Excel documents, read and write documents' properties
eng The eng service offers access to a comprehensive set of APIs specific to Extended ECM for engineering. This includes specialized functionalities for managing CAD documents, handling transmittals, state flows, distribution matrices, and other engineering-specific processes and data structures.
forms The forms service is the main access to the Content Server web-forms features. With forms service it is possible, among other things, to: create and modify form and form template objects, read/modify/delete submitted form records, submit new form records, export/import form records
ftp The ftp service allows to interact with FTP services. With ftp service it is possible, among other things, to: access, read, write files and folders on multiple FTP servers
html The html service provides a convenient set of server-side APIs for processing HTML code. Key features include HTML to XHTML conversion, HTML sanitization, XSS (Cross-Site Scripting) prevention, and HTML to PDF conversion, all achievable without the need for additional software.
jdbc The jdbc service is designed to offer a convenient method for integrating JDBC-enabled data sources. It manages connections to multiple data sources and connection pools to optimize performance. Additionally, this service includes a layer of abstraction related to the specific pooling technology used, enhancing its adaptability and ease of use in various database environments.
ldap The ldap service is dedicated to managing LDAP (Lightweight Directory Access Protocol) connections and operations, streamlining interactions with LDAP servers and simplifying directory management tasks.
llm The llm service is designed to integrate LLM (Large Language Model) based services, specifically tailored for the context of the Module Suite application. It offers a convenient set of APIs for use in scripts and widgets, facilitating seamless integration. Currently, the service supports OpenAI-like APIs but is architecturally agnostic, allowing compatibility with various underlying LLM technologies.
notifications The notifications service is designed to provide programmatic access to the functionalities of the Notification Center. This enables developers to utilize it for notifying users about events related to Module Suite applications, enhancing user engagement and awareness.
oauth The oauth service is specifically designed to simplify the access and usage of resources and services protected by OAuth, streamlining authentication and authorization processes for secure and efficient integration.
odata The odata service is crafted to offer a convenient approach for both consuming and producing REST APIs that are compliant with OData (Open Data Protocol) standards, facilitating seamless interaction with OData-based services. For more information on OData, you can visit the OData official website.
pdf The pdf service allows to programmatically manipulate PDF documents. With pdf service is it possible, among other things, to: create and manipulate PDF documents, write in overlay on PDFs, extract PDF pages as images, merge PDFs, add watermarks to PDF documents, add barcodes (mono and bi-dimensional) on PDF pages, remove print/modify permissions from PDF, add PDFs in overlay to existing PDFs, extract images from pages or portion of pages, read bar-codes form PDF’s pages, remove/insert pages
physobj The physobj service is designed to facilitate the management of Physical Objects nodes, providing tools and functionalities necessary for handling these specific types of nodes effectively.
recman The recman service is intended to provide access to Records Management APIs and services, enabling the integration and utilization of records management functionalities within the application framework.
rend The rend service allows to programmatically invoke external rendition engines. With rend service it is possible, among other things, to: transform on the fly HTML pages to PDF documents, rend WebForms as PDFs, invoke external services through an "all-purpose" generic rendition api
rmsec The rmsec service is intended to provide access to APIs and services related to Records Management Security and Security Clearance modules, enabling streamlined integration and management of these critical security features.
rtl The rtl (Right-to-Left) service features a set of APIs specifically designed to simplify the creation of user interfaces that support Right-to-Left languages, ensuring ease of use and inclusivity in global applications.
sap The sap service allows to integrate Content Script with the well known SAP ERP through RFCs. With sap service it is possible, among other things, to: connect to multiple SAP systems through JCO APIs, invoke standard and custom SAP functions to retrieve/update ERP information
sftp The sftp service encompasses a suite of APIs tailored to simplify, optimize, and enhance the efficiency of using SFTP (Secure File Transfer Protocol) services in various applications.
sql The sql service is designed to facilitate access to the platform's underlying database. This service enables querying the database, managing the creation of cursors, wrapping queries in transactions, and more. Additionally, it features methods specifically aimed at simplifying the creation of SQL queries for paginated data access, streamlining interactions with large datasets.
sync The sync service is designed to support the configuration of server-side services and APIs necessary for Syncfusion-based widgets. This includes both Beautiful WebForms and Smart Pages widgets, ensuring seamless integration and functionality within these frameworks.
xecm The xecm service is tailored to support the management and creation of new Extended ECM connectors, as well as Extended ECM-related objects such as Business Workspaces. Additionally, this service facilitates integration with the Event Bots center, enhancing the capabilities of Extended ECM environments.
zip The zip service is designed to provide robust functionalities for handling ZIP file operations. This includes creating, extracting, and managing ZIP archives, enabling efficient file compression and decompression within various applications. The service is optimized for ease of use and seamless integration, making it ideal for managing large datasets or grouped files in a compressed format.

APIs evolution

New service APIs are constantly added or updated with every subsequent release of Content Script. Optional APIs are usually available through Content Script Extension Packages, and can be installed separately using the master installer or the extension packages’ own installers.

Execution context

Upon execution, every Content Script is associated to a Groovy binding. The binding can be seen as a container for Objects that are part of the context in which the script is executed. We make reference to this context as Content Script Execution Context or as Script Binding.

The Script Manager creates the most appropriate execution context on the basis of:

  • the script's code;

  • the system's current configuration;

  • the user context (user's permission, user's roles, etc..)

  • the cause that triggered the script's execution (direct invocation, scheduler, callback, etc..)

graph LR
  A[Script Source Code] --> B([Script Manager]);
  B --> |Compiles| C{{Script Compiled}};
  B --> | Assemble| D[Execution Context];
  C --> E([Script Engine]);
  D --> E;
  E --> |Executes the Script against the Context and generates| F[Result] 

The Script Manager initializes the Script Binding before execution, injecting a set of objects, which include:

  • API Services

  • Request variables

  • Support Objects

  • Support Variables

Additionally, a set of script utility methods are available in the Content Script (Base API). The methods grant access to short-cuts for commonly used features or can pilot the execution result.

Request variables

Request variables are variables injected into the execution context by the Script Manager whenever a script is directly invoked as a result of a user's browser request.

Variable Description
params A container for the Script’s request parameters. It’s a non-case sensitive map that provide access to all the parameters passed to the script when executed.
In the params map are injected by default also the following variables (where available):
  • myurl:The URL string used to execute the Content Script
  • node: the id of the Content Script object
  • useragent: the user's browser useragent
  • cookies: the user's browser cookies (as strings)
  • method: the HTTP verb used to request the script
  • lang: the user's locale
  • port: the HTTP port used to request the script
  • server: the HTTP host used to request the script
  • pathinfo: the request's URL path information
request A synonym for the previous variable (for backward compatibility)

Support variables

The number and the nature of the variables that are injected by the Content Script Engine depends primarily from the mode through which the script has been executed. Content Script scripts used for example to implement Node Callbacks or columns' Data Sources will have injected in their Execution Context, respectively: the information regarding the Node that triggers the event or the Node for which the column’s value is requested. Please refer to the Content Script module online documentation for the name and type of the variables made available in the Execution Context in the different scenarios. The following variables are always injected.

Variable Description
img Content Server static resource context path (es. /img/).
webdav WebDav path
supportpath Content server support path
url Content Server CGI Context
SCRIPT_NAME A synonym for the previous variable (for backward compatibility)
csvars A map containing the script's static variables
originalUserId The ID of the user that triggered the execution of the Script (not considering impersonation)
originalUsername The username of the user that triggered the execution of the Script (not considering impersonation)


Please note that most of the time the img context variable ends with a trailing slash. To correctly use it as a replacement variable in Content Script strings or velocity templates we suggest you to use the ${img} notation. E.g.:

"""<img src="${img}anscontentscript/img/am_logo.png" />"""

Support objects

Support objects are instances of Content Script classes that the Script Manager creates, configures and injects into every execution context in order to provide a simple mean for accessing very basic or commonly required functionalities.

Variable Description
self An object representing the Content Script node being currently executed.
response An instance of the ScriptResponse class that can be used to pilot the Content Script output.
gui A map of standard Content Server UI Components that can be enabled/disabled at the time of rendering the page.
  • = false
  • gui.sideBar = false

Disable standard UI

To completely disable the standard Content Server UI use:

gui.gui = false 

log Each Content Script is associated with an instance logger that can be used to keep track of the script execution. From within a script you can access the logger either using the Script’s method getLog() or the shortcut log. The Content Script logging system is based on a framework similar to the one used internally by OTCS. The logger supports five different levels: trace, debug, info, warn, error. The default log level for any script is: error this means that log messages at level for example debug won’t be outputted in the ModuleSuite’s master log file (cs.log).

Logging level can be overridden per script basis through a dedicated administrative console.

out A container for the script textual output

Base API

The Content Script "Base API" or "Script API" is constituted by methods and properties that are exposed directly by each Content Script script.

API Description
asCSNode(Map) An alternative to loading a node explicitly using one method out of: docman.getNode, docman.getNodeByPath, docman.getNodeByNickname
asCSNode(Long) An alternative to loading a node explicitly using the docman.getNode method
redirect(String) A shortcut for sending a redirect using the response object
json(String) A shortcut for sending json using the response object
json(Map) A shortcut for sending json using the response object
json(List) A shortcut for sending json using the response object
sendFile(File[,String]) A shortcut for sending a file using the response object
success(String) A shortcut for setting the result of the script execution to "success"
runCS(Long) A utility method to run a second Content Script (identified by ID) within the same context
runCS(String) A utility method to run a second Content Script (identified by nickname) within the same context
runCS(String, Object[]) A utility method to run a second Content Script (identified by nickname) using a cleaned execution context (the new execution context shares with the caller’s context only the Content Script services and the following variables: out, gui, response). In the sub-script code the parameters that have been used to call the sub-script can be accessed through the context variable “args”. Using this variant it’s possible to intercept the result of the sub-script execution.
printError(Ex) A utility method to print out any exception raised by script’s execution


Usage example for runCS(String, Object[]) API

//Parent Script
node = asCSNode(123456)
map  = runCS(mySubScript, node, users.current)
out << map.user

//SubScript “mySubScript”
def retVal = [:] = args[0].name
retVal.user = args[1].with{
return retVal
Usage example for asCSNode(...)API

// Load a CSNode

// A node can be loaded also by path or nickname
asCSNode(id:2000) //=== asCSNode(2000)

Usage example for printError(...)API

    out << asCSNode(12345).name
    log.error("Error ",e) //Prints the full stack trace in the log file
    printError(e) //Outputs the error


Script's execution

As shown in previous sections, the execution of Content Scripts can be triggered in different ways. Here after are a few examples:

  • Direct execution by a user. This can happen, for example:

    • Using the Execute action in the object function menu or promoted object functions

    • While using the Content Script Editor, using the Execute or Execute in Modal buttons (useful for debug and testing purposes, shown in the figure below)

    • A URL associated to the execution of a Content Script is invoked

    • A Content Script backed SmartUI widget is displayed

  • Direct execution by an external system

    • A URL associated to a Content Script REST API is invoked
  • Automatic execution by the system. This happens when:

    • The script is scheduled, at the configured execution time

    • A callback is configured, and the associated event is triggered

    • A Content Script Workflow step is configured as part of a workflow, and the step is activated

    • A Content Script is configured as a Data Source for a WebReport, and the WebReport is executed

    • A Content Script serves as a Data Source for a custom column

Script's output

As you can easily imagine by analysing the examples in the previous paragraph, the expected result from the execution of a Content Script varies significantly from case to case.

When a user executes a Content Script directly from the Content Server user interface, he/she would probably expect, in most of the cases, the result to be either a web page, a file to download, or a browser redirection to a different Content Server resource.

When a remote system invokes a REST service API backed by a Content Script, it will most probably expect structured data in return (probably XML or JSON data).

When a Content Script is executed as part of a workflow and the next step is to be chosen depending on the execution outcome, the script will probably be expected to return a single variable of some kind (a number or a string) or an indication that the execution was either successful or encountered errors.

Content Script is flexible enough to cover all of these scenarios. The next section will include examples of how to provide the different output necessary in each situation.

HTML (default)

The default behaviour in case of a successful script execution is to return the content of the "out" container

def contentToPrint = "This content will be printed in output"
out << contentToPrint
def contentToPrint = "This content will be printed in output"

//If the object returned by the script is a String, it will be printed in output
return contentToPrint


JSON content can be easily returned

def builder = new JsonBuilder()
builder.companies {
    company "AnswerModules"
    country "Switzerland"

// Stream JSON content, useful for restful services
String jsonString = '{"key":"value"}'

// A string containing JSON data can be used 
// or with the shorthand method
// or
json([[key:value1], [key:value2]])


XML content can be easily returned

gui.gui = false
gui.contentType = "application/xml"

def builder = new StreamingMarkupBuilder()
def parent  = asCSNode(2000)
def nodes   = parent.childrenFast //nodes are lazy loaded 

def xml = builder.bind {
    node(id:parent.ID,,  isContainer:parent.isContainer){
        children {
            nodes.collect {
                node(id:it.ID,, isContainer:it.isContainer)
out << XmlUtil.serialize(xml)
Output of the above script:

<node id="2000" name="Enterprise" isContainer="true">
            <node id="90064"    name="Import"   isContainer="true"/>
            <node id="3270165"  name="Training" isContainer="true"/>

Using gui support object for tuning script's output

Note the usage of gui.contentType in order to change the response’s “Content-Type” header.


It is also possible to stream a file directly:

// Stream a file as result of the execution
def res  = docman.getTempResource("tempRes", "txt")
res.content.text = "Just a test"
def file = res.content 
// Stream a file as result of the execution
def res  = docman.getTempResource("tempRes", "txt")
res.content.text = "Just a test"
def file = res.content 
// Stream a file, specifying if it is a temporary file (will prevent deletion) 
response.file(file, true)
// Stream a file as result of the execution
def res  = docman.getTempResource("tempRes", "txt")
res.content.text = "Just a test"
def file = res.content 
// or with the shortcut method
// Stream a file as result of the execution
def res  = docman.getTempResource("tempRes", "txt")
res.content.text = "Just a test"

// or returing the CSResource directly = "My textFile.txt"
return res
Managed resources

In the context of developing against OTCS you will end up dealing with many different kind of contents most of which are (or are strictly related with) files. In order to reduce the amount of code needed to properly manage the disposition of temporary files, Content Script introduces the concept of "managed resource" or CSResource. A CSResource is basically a wrapper around the File class. CSResources are managed by the Content Script engine (no disposition required) and are returned any time you want to access the content of a CSDocument or you fetch a version from it (in these cases the CSResource will keep a reference, towards the source CSDocument, through its "owner" property.

CSResources are first class citizens in Content Script. A CSResrouce can be for example returned directly by a Content Script, triggering the download of the same.

Returning CSResource to trigger document download

Returning a CSResource from a script is the simplest way to stream out a file in this case is important to keep in mind that the name of the downloaded file will be determined using the following rule:

if the property onwer of the CSResource is != null                                                                                                                                                         
    use the name of the CSNode referenced by the CSResources owner property                                                                                                                                   
    use the CSResource's name property.


In alternative, the response could contain a redirection to an arbitrary URL:

String url = ""

// Send a redirect using the response

// or with the shortcut method
// or
redirect ${url}/open/2000
// or
redirect asCSNode(2000)


In certain cases (e.g. when Content Script is used to extend OTCS’ REST APIs), it could be necessary to explicitly control the "error" or "success" status of the script execution:

// Force the script execution result to be "success" using the response
response.success("This is a success message")
response.success("This is a success message",200)

// or with the shortcut method
success("This is a success message")
success("This is a success message",200)

// Force the script execution result to be "success"
response.error("This is an error message", 403)

// or with the shortcut method
error("This is an error message", 403)

Advanced programming


Content Script features a flexible yet powerful templating engine based on Apache Velocity. Evaluating a template is just a matter of invoking one of the evaluate methods available through the template service.

Content Script velocity macros

Content Scripts defines a collection of macros that simplify the creation of OTCS UI embeddable interfaces. A developer can create his own macros simply defining them in a z_custom.vm file to be stored under the Content Script "Temp" folder (as defined in the Base Configuration page: amcs.core.tempFilePath).

Name and description Param Type and description Usage example
Creates the standard OTCS context menu for the given node (identified by its dataid)
dataid Integer
node's dataid
nextUrl String
Loads static libraries from the module support directory
resList List
A list of resources to load. To be chosen from: query, jquery-ui, jquery-ui-css, bootstrap, bootstrap-css
Creates the HTML form needed to submit a request against the executed Content Script
script Integer
The objId of the Content Script you’d like to execute
//Custom form inputs go here
submit String
The value for the label of the submit button. If null the submit button will not be created

Creates an HTML table that fits nicely with the standard OTCS UI
columns List
The list of column labels
#@cstable([‘First Name’], {},{}, true)
//Your rows here
sortColumns Map
A map of “Column Label”, “Property” couples. The Property is used to build sort links for columns
columnsClasses Map
A map of “Column Label”, “CSS Classes” couples. The “CSS Classes” are assigned to the THs tags.
checkBoxes Boolean
If TRUE the first column of the table will have width 1%. To be used to insert a checkboxes column

Creates a pagination widget to be used
skip Integer
The index of the element to skip before to start rendering rows
#cspager(0 25 3 $parent.childCount)
pageSize Integer
The page size (e.g. 25)
pagerSize Integer
The number of pages to show in the pager widget
elementsCount Integer
The total number of elements

OScript serialized data structures

Content Script Java layer is tightly bound with Content Script Oscript layer, thus quite frequently you will face the need of managing Oscript's serialized data structures obtained for example querying the OTCS' database or from nodes' properties.

Oscript serializes its data in the form of Strings, for this reason Content Script enhances the String class in order to provide a quick method for retrieving the corresponding Content Script’s objects out of the OScript serialized representation.

Methods available on the String class are:

  • getDateFromOscript

  • getListFromOscript

  • getMapFromOscript

In the exact same way Content Script enhances its most common types (List, Map, Date, Long, CSReportResult) in order to simplify the creation of the corresponding OScript serialized representation.

The below table shows an usage example of the mentioned features:

Optimizing your scripts


You can use behaviors to decorate your scripts and let them implement a specific set of new functionalities. Behaviors are to be considered similar to inheritance. A behavior is defined as a collection (MAP) of closures and usually implemented in the form of a static class featuring a getBehaviors method.

When you add a behavior to your script, all the closures that have been defined in the behavior become part of your script thus becoming part of your script context.

Behaviors are resolved at compilation time, this means that they should be considered as a static import.

Said otherwise, any changes applied directly on the script that implements your behaviors, won't effect the scripts that have imported such behaviors. In order to update the imported behaviors you have to trigger the re-compilation of the script that is importing them (target script).


In order to add behaviors to a script you shall use the BehaviourHelper utility class.

The BehaviourHelper utility class, features three methods:

@ContentScriptAPIMethod (params = [ "script" , "behaviours" ], description = "Add behaviours to a Content Script" )
public static void addBeahaviours(ContentScript script, Map<String, Closure> closures)

@ContentScriptAPIMethod (params = [ "script" ,  "behaviours" ], description= "Remove behaviours from a Content Script " )
public static void  removeBehaviours(ContentScript script, String... closures=null)

@ContentScriptAPIMethod (params = [ "script" ,  " behaviour " ], description= " Determine if the script already has the specified behaviour " )
public static void  hasBehaviour(ContentScript script, String name)

Through BehaviourHelper you can add, remove or check for the presence of an associated behavior.

Behaviors are of great help when it comes to structure your code base, optimize executions and reduce boilerplate code.

Module Suite comes with few predefined behaviors, you can easily implement yours by defining a map of closures to be passed to the above BehaviourHelper utility class.

Default Behaviours

The AMController behavior has been designed to simplify the creation of form-based application on Content Server.

It features the following closures:

  1. start: this closure takes no parameters, and it is used to dispatch incoming requests. It creates (if not already provided) an app object to be made available in the execution context. It analyzes the request's pathinfo, to extract the information required to route towards a registered closure. Rebuilds any Beautiful WebForm object found in the request.

    This closure should be the last instruction of your script.

    app =  [:]
    app.product ="Module Suite"
    if(!BehaviourHelper.hasBehaviour(this, "start") ) {
        BehaviourHelper.addBeahaviours(this, AMController.getBehaviours())
    home = {
        out << "Hello world from ${app.product}"
    details = { String id = null->
        out << "This script ID ${id?asCSNode(id as int).ID:self.ID}"
    When directly executed (http://my.server/otcs/cs.exe?func=ll&objId=12345&objAction=Execute&nexturl=.. or http://my.server/otcs/cs.exe/open/12345) the script above will output:

    Hello world from Module Suite

    when executed using: http://my.server/otcs/cs.exe/open/12345/details it will output

    The script ID 12345

    when executed as: http://my.server/otcs/cs.exe/open/12345/details/2000 it wll output:

    The script ID 2000

    In other words the requested path will always been interpreted using the follow schema: http://my.server/otcs/cs.exe/open/12345/closurename/param1/param2/param3 where closurename will be defaulted to "home" if not found in the path.

  2. loadForm(def formID, def amSeq=0): loads a Form data object, setting form.viewParams.contentScript = params.node (so that if the form data object will be used with a BeautifulWebForm view the form will submit on this very same content script) and form.viewParams.amapp_Action = params.pathinfo.

  3. submitForm(def form): validates the form data object and performs the submit (executing pre-submit and on-submit scripts if defined)

  4. renderForm(def form, def context=null): renders the form either in the script context or in the specified context