Web Scripts Examples

cancel
Showing results for 
Search instead for 
Did you mean: 

Web Scripts Examples

resplin
Intermediate
0 0 15.3K

Introduction

This page presents some sample Web Scripts that reside in your Alfresco Server at the folder:

/Company Home/Data Dictionary/Web Scripts/org/alfresco/sample

Quick start

You can run some of these scripts right now on a clean install of Alfresco 2.1 or later.

If you installed by following Installing on Microsoft Windows or Linux Quick Install then you can access the folder webscript here:

http://localhost:8080/alfresco/service/sample/folder/Company%20Home 

Log in with the username admin and password admin.

What Is All This Information?

For each Sample described below, you see the following information:

URL
Defines the format of the URL used to access the script
Examples
Gives concrete examples of valid URLs to call the script. You can call the web script by copying the URL into your browser and substituting your host name and port.

Description Document

Execute Script

Response Template

These are source of the content items in Alfresco, found by browsing to the following space:

Company Home > Data Dictionary > Web Scripts > org > alfresco > sample

The file names and extensions are important as they tell Alfresco what the item is for.

If you want to experiment with your first web script see this page: Web Scripts Hello World Quick Start

Hello World

This sample very simply demonstrates how to create a polite Alfresco Repository.

URL
GET /alfresco/service/sample/hello

Examples:

http://<host>:<port>/alfresco/service/sample/hello
Description Document
File: hello.get.desc.xml
<webscript>   <shortname>Hello</shortname>   <description>Polite greeting</description>   <url>/sample/hello</url>   <authentication>user</authentication> </webscript>
Response Templates
File: hello.get.html.ftl
Hello ${person.properties.userName}.

Folder Browse/RSS Feed

This sample demonstrates how to implement a URL service that renders the contents of a folder in either HTML or ATOM. The HTML rendition allows for the browsing of a folder hierarchy.

URL
GET /alfresco/service/sample/folder/{path}

Examples:

http://<host>:<port>/alfresco/service/sample/folder/Company%20Home http://<host>:<port>/alfresco/service/sample/folder/Company%20Home?format=atom
Description Document
File: folder.get.desc.xml
<webscript>   <shortname>Folder Listing Sample</shortname>   <description>Sample demonstrating the listing of folder contents</description>   <url>/sample/folder/{path}</url>   <format default="html">argument</format>   <authentication>guest</authentication>   <transaction>required</transaction> </webscript>
Execute Script
File: folder.get.js
// locate folder by path var folder = roothome.childByNamePath(url.extension); if (folder == undefined || !folder.isContainer) {    status.code = 404;    status.message = "Folder " + url.extension + " not found.";    status.redirect = true;  }  model.folder = folder;
Response Templates
File: folder.get.html.ftl
<html>   <head>     <title>${folder.displayPath}/${folder.name}</title>   </head>   <body>     Folder: ${folder.displayPath}/${folder.name}     <br>     <table>      <#if folder.parent.parent?exists>      <tr>        <td><td><a href="${url.serviceContext}/sample/folder<@encodepath node=folder.parent/>">..</a>      </tr>      </#if> <#list folder.children as child>      <tr>        <#if child.isContainer>          <td>><td><a href="${url.serviceContext}/sample/folder<@encodepath node=child/>">${child.name}</a>        <#else>          <td><td><a href="${url.serviceContext}/api/node/content/${child.nodeRef.storeRef.protocol}/${child.nodeRef.storeRef.identifier}/${child.nodeRef.id}/${child.name?url}">${child.name}</a>        </#if>      </tr> </#list>     </table>   </body> </html> <#macro encodepath node><#if node.parent?exists><@encodepath node=node.parent/>/${node.name?url}</#if></#macro>
File: folder.get.atom.ftl
<?xml version="1.0" encoding="UTF-8"?> <feed xmlns="http://www.w3.org/2005/Atom">   <generator version="${server.version}">Alfresco (${server.edition})</generator>   <title>Folder: ${folder.displayPath}/${folder.name}</title>    <updated>${xmldate(date)}</updated>   <icon>${absurl(url.context)}/images/logo/AlfrescoLogo16.ico</icon> <#list folder.children as child>   <entry>     <title>${child.name}</title>     <#if child.isContainer>       <link rel="alternate" href="${absurl(url.serviceContext)}/sample/folder<@encodepath node=child/>"/>     <#else>       <link rel="alternate" href="${absurl(url.serviceContext)}/api/node/content/${child.nodeRef.storeRef.protocol}/${child.nodeRef.storeRef.identifier}/${child.nodeRef.id}/${child.name?url}"/>     </#if>     <icon>${absurl(url.context)}${child.icon16}</icon>     <id>urn:uuid:${child.id}</id>     <updated>${xmldate(child.properties.modified)}</updated>     <summary>${child.properties.description!""}</summary>     <author>        <name>${child.properties.creator}</name>     </author>    </entry> </#list> </feed> <#macro encodepath node><#if node.parent?exists><@encodepath node=node.parent/>/${node.name?url}</#if></#macro>

WCM/AVM Browse

Warning: AVM Deprecation
The AVM is no longer being actively developed by Alfresco Engineering and Enterprise support subscriptions for the AVM are no longer being offered to new customers. New projects requiring Web Content Management features may want to consider leveraging a CMIS-based solution such as Web Quick Start or the File System Transfer Receiver. The topic AVM Decommissioning collects useful information for migrating off of the AVM. The AVM was removed from the product in version 5.0.

This sample (split into two web scripts) demonstrates how to browse WCM/AVM stores.

AVM Stores List

This sample demonstrates how to implement a URL service that renders a list of all AVM stores.

URL
GET /alfresco/service/sample/avm/stores

Examples:

http://<host>:<port>/alfresco/service/sample/avm/stores
Description Document
File: avmstores.get.desc.xml
<webscript>   <shortname>AVM Stores Sample</shortname>   <description>Sample demonstrating the listing of AVM stores</description>   <url>/sample/avm/stores</url>   <format default="html"/>   <authentication>admin</authentication>   <transaction>required</transaction> </webscript>
Response Templates
File: avmstores.get.html.ftl
<html>   <head>     <title>AVM Stores</title>   </head>   <body>     AVM Stores     <br>     <br>     <table>      <tr> <#list avm.stores as store>      <tr>         <td>${store.creator}<td> <td>${store.createdDate?datetime}<td> <td><a href="${url.serviceContext}/sample/avm/path/${store.id}/">${store.id}      </tr> </#list>     </table>   </body> </html>

AVM Folder Browse

This sample demonstrates how to implement a URL service that renders the contents of an AVM folder in HTML. The rendition allows for the browsing of a folder hierarchy.

URL
GET /alfresco/service/sample/avm/path/{storeid}/{path}

Examples:

http://<host>:<port>/alfresco/service/sample/avm/path/main--admin/www
Description Document
File: avmbrowse.get.desc.xml
<webscript>   <shortname>AVM Browse Sample</shortname>   <description>Sample demonstrating the listing of AVM folder contents</description>   <url>/sample/avm/path/{storeid}/{path}</url>   <format default="html">argument</format>   <authentication>admin</authentication>   <transaction>required</transaction> </webscript>
Execute Script
File: avmbrowse.get.js
script: {    // extract avm store id and path    var fullpath = url.extension.split("/");    if (fullpath.length == 0)    {      status.code = 400;      status.message = "Store id has not been provided.";      status.redirect = true;      break script;    }    var storeid = fullpath[0];    var path = (fullpath.length == 1 ? "/" : "/" + fullpath.slice(1).join("/"));         // locate avm node from path    var store = avm.lookupStore(storeid);    if (store == undefined)    {      status.code = 404;      status.message = "Store " + storeid + " not found.";      status.redirect = true;      break script;    }    var node = avm.lookupNode(storeid + ":" + path);    if (node == undefined)    {      status.code = 404;      status.message = "Path " + path + " within store " + storeid + " not found.";      status.redirect = true;      break script;    }         // setup model for templates    model.store = store;    model.folder = node;     }
Response Templates
File: avmbrowse.get.html.ftl
<html>   <head>     <title>AVM Folder: ${folder.displayPath}/${folder.name}</title>   </head>   <body>     <a href="${url.serviceContext}/sample/avm/stores">AVM Store</a>: ${store.id}     <br>     <br>     AVM Folder: ${folder.displayPath}/${folder.name}     <br>     <br>     <table>      <#if folder.parent?exists>      <tr>       <td>${folder.parent.properties.creator}<td> <td>${folder.parent.size}<td> <td>${folder.parent.properties.modified?datetime}<td> <td><td><a href="${url.serviceContext}/sample/avm/path/${store.id}<@encodepath node=folder.parent/>">..</a>      </tr>      </#if> <#list folder.children as child>      <tr>        <#if child.isContainer>         <td>${child.properties.creator}<td> <td>${child.size}<td> <td>${child.properties.modified?datetime}<td> <td>><td><a href="${url.serviceContext}/sample/avm/path/${store.id}<@encodepath node=child/>">${child.name}</a>        <#else>          <td>${child.properties.creator}<td> <td>${child.size}<td> <td>${child.properties.modified?datetime}<td> <td><td><a href="${url.serviceContext}/api/node/content/${child.nodeRef.storeRef.protocol}/${child.nodeRef.storeRef.identifier}/${child.nodeRef.id}/${child.name?url}">${child.name}</a>        </#if>      </tr> </#list>     </table>   </body> </html>

Blog Search

This sample demonstrates how to implement a URL service that performs a full-text search whose results are rendered in either HTML or ATOM.

URL
GET /alfresco/service/sample/blog/search?q={searchTerm}

Examples:

http://<host>:<port>/alfresco/service/sample/blog/search?q=alfresco http://<host>:<port>/alfresco/service/sample/blog/search.atom?q=alfresco
Description Document
File: blogsearch.get.desc.xml
<webscript>   <shortname>Blog Search Sample</shortname>   <description>Sample that finds all blog entries whose content contains the specified search term</description>   <url>/sample/blog/search?q={searchTerm}</url>   <url>/sample/blog/search.atom?q={searchTerm}</url>   <url>/sample/b/s?q={searchTerm}</url>   <url>/sample/b/s.atom?q={searchTerm}</url>   <format default="html">extension</format>   <authentication>guest</authentication>   <transaction>required</transaction> </webscript>
Execute Script
File: blogsearch.get.js
// check that search term has been provided if (args.q == undefined || args.q.length == 0) {    status.code = 400;    status.message = "Search term has not been provided.";    status.redirect = true; } else {    // perform search    var nodes = search.luceneSearch("TEXT:" + args.q);    model.resultset = nodes; }

NOTE: The above script executes a simple full-text search across the whole repository. It could be extended to search within a specific folder or a specific type of content.

Response Templates
File: blogsearch.get.html.ftl
<html>   <body>     <img src="${url.context}/images/logo/AlfrescoLogo32.png" alt="Alfresco" />     Blog query: ${args.q}     <br>     <table> <#list resultset as node>      <tr>        <td><img src="${url.context}${node.icon16}"/>        <td><a href="${url.serviceContext}/api/node/content/${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}/${node.name?url}">${node.name}</a>      </tr> </#list>     </table>   </body> </html>
File: blogsearch.get.atom.ftl
<?xml version="1.0" encoding="UTF-8"?> <feed xmlns="http://www.w3.org/2005/Atom">   <generator version="${server.version}">Alfresco (${server.edition})</generator>   <title>Blog query: ${args.q}</title>    <updated>${xmldate(date)}</updated>   <icon>${absurl(url.context)}/images/logo/AlfrescoLogo16.ico</icon> <#list resultset as node>   <entry>     <title>${node.name}</title>     <link rel="alternate" href="${absurl(url.serviceContext)}/api/node/content/${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}/${node.name?url}"/>     <icon>${absurl(url.context)}${node.icon16}</icon>     <id>urn:uuid:${node.id}</id>     <updated>${xmldate(node.properties.modified)}</updated>     <summary>${node.properties.description!""}</summary>     <author>        <name>${node.properties.creator}</name>     </author>    </entry> </#list> </feed>
Status Template
File: blogsearch.get.html.404.ftl
<html>   <body>     ${status.message}   </body> </html>
File: blogsearch.get.atom.404.ftl
<?xml version="1.0" encoding="UTF-8"?> <response>   ${status.code}  <codeName>${status.codeName}</codeName>   <codeDescription>${status.codeDescription}</codeDescription>   <message>${status.message}</message> </response>

Blog Category Search

This sample demonstrates how to implement a URL service that performs a category search whose results are rendered in either HTML or ATOM.

Content may be categorized via the Alfresco Web Client (Content Properties page).

URL
GET /alfresco/service/sample/blog/category/{category}

Examples:

http://<host>:<port>/alfresco/service/sample/blog/category/EUROPE
Description Document
File: categorysearch.get.desc.xml
<webscript>   <shortname>Category Search</shortname>   <description>Find all blog entries tagged with specified categories</description>   <url>/sample/blog/category/{category}</url>   <format default="html">extension</format>   <authentication>guest</authentication>   <transaction>required</transaction> </webscript>
Execute Script
File: categorysearch.get.js
// check category exists? var category = search.luceneSearch("PATH:\"/cm:generalclassifiable//cm:" + url.extension + "\""); if (category == undefined) {    status.code = 404;    status.message = "Category " + url.extension + " not found.";    status.redirect = true; } else {    // perform category search    var nodes = search.luceneSearch("PATH:\"/cm:generalclassifiable//cm:" + url.extension + "//member\"");    model.resultset = nodes; }

NOTE: The above script executes a simple category search across the whole repository. It could be extended to search within a specific folder or a specific type of content.

Response Templates
File: categorysearch.get.html.ftl
<html>   <body>     <img src="${url.context}/images/logo/AlfrescoLogo32.png" alt="Alfresco" />     Category search: ${url.extension}     <br>     <table> <#list resultset as node>      <tr>        <td><img src="${url.context}${node.icon16}"/>        <td><a href="${url.serviceContext}/api/node/content/${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}/${node.name?url}">${node.name}</a>      </tr> </#list>     </table>   </body> </html>
File: categorysearch.get.atom.ftl
<?xml version="1.0" encoding="UTF-8"?> <feed xmlns="http://www.w3.org/2005/Atom">   <generator version="${server.version}">Alfresco (${server.edition})</generator>   <title>Category search: ${url.extension}</title>    <updated>${xmldate(date)}</updated>   <icon>${absurl(url.context)}/images/logo/AlfrescoLogo16.ico</icon> <#list resultset as node>   <entry>     <title>${node.name}</title>     <link rel="alternate" href="${absurl(url.serviceContext)}/api/node/content/${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}/${node.name?url}"/>     <icon>${absurl(url.context)}${node.icon16}</icon>     <id>urn:uuid:${node.id}</id>     <updated>${xmldate(node.properties.modified)}</updated>     <summary>${node.properties.description!""}</summary>     <author>        <name>${node.properties.creator}</name>     </author>    </entry> </#list> </feed>
Status Templates
File: categorysearch.get.html.404.ftl
<html>   <body>     ${status.message}   </body> </html>
File: categorysearch.get.atom.404.ftl
<?xml version="1.0" encoding="UTF-8"?> <response>   <code>${status.code}</code>   <codeName>${status.codeName}</codeName>   <codeDescription>${status.codeDescription}</codeDescription>   <message>${status.message}</message> </response>

File Upload

This sample (split into two web scripts) demonstrates how to implement a file upload URL service.

The first web script presents a simple HTML form with three form fields, one of which is of type file. The form POSTs to a second web script which parses the posted multipart/form-data request and creates a new file in the repository using the values entered into the form.

Upload Form

URL
GET /sample/upload
Description Document
File: upload.get.desc.xml
<webscript>   <shortname>File Upload Form Sample</shortname>   <description>Form for uploading file content and meta-data into Repository</description>   <url>/sample/upload</url>   <authentication>user</authentication> </webscript>
Response Templates
File: upload.get.html.ftl
<html>  <head>     <title>Upload Web Script Sample</title>     <link rel="stylesheet" href="${url.context}/css/main.css" TYPE="text/css">  </head>  <body>    <table>      <tr>        <td><img src="${url.context}/images/logo/AlfrescoLogo32.png" alt="Alfresco" /></td>        <td><nobr>Upload Web Script Sample</nobr></td>      </tr>      <tr><td><td>Alfresco ${server.edition} v${server.version}    </table>    <p>    <table>      <form action="${url.service}" method="post" enctype="multipart/form-data" accept-charset="utf-8">        <tr><td>File:</td><td><input type="file" name="file"></td></tr>        <tr><td>Title:</td><td><input name="title"></td></tr>        <tr><td>Description:</td><td><input name="desc"></td></tr>        <tr><td></td></tr>        <tr><td><input type="submit" name="submit" value="Upload"></td></tr>      </form>    </table>  </body> </html>

Upload Script

URL
POST /sample/upload
Description Document
File: upload.post.desc.xml
<webscript>   <shortname>File Upload Sample</shortname>   <description>Upload file content and meta-data into Repository</description>   <url>/sample/upload</url>   <authentication>user</authentication> </webscript>
Execute Script
File: upload.post.js
var filename = null; var content = null; var title = ""; var description = "";  // locate file attributes for each (field in formdata.fields) {   if (field.name == "title")   {     title = field.value;   }   else if (field.name == "desc")   {     description = field.value;   }   else if (field.name == "file" && field.isFile)   {     filename = field.filename;     content = field.content;   } }  // ensure mandatory file attributes have been located if (filename == undefined || content == undefined) {   status.code = 400;   status.message = "Uploaded file cannot be located in request";   status.redirect = true; } else {   // create document in company home for uploaded file   upload = companyhome.createFile("upload" + companyhome.children.length + "_" + filename) ;      upload.properties.content.write(content);   upload.properties.content.setEncoding("UTF-8");   upload.properties.content.guessMimetype(filename);      upload.properties.title = title;   upload.properties.description = description;   upload.save();     // setup model for response template   model.upload = upload; }
Response Templates
File: upload.post.html.ftl
<html>  <head>     <title>Upload Web Script Sample</title>     <link rel="stylesheet" href="${url.context}/css/main.css" TYPE="text/css">  </head>  <body>    <table>      <tr>        <td><img src="${url.context}/images/logo/AlfrescoLogo32.png" alt="Alfresco" /></td>        <td><nobr>Upload Web Script Sample</nobr></td>      </tr>      <tr><td>Alfresco ${server.edition} v${server.version}</td></tr>      <tr><td></td></tr>      <tr><td>Uploaded <a href="${url.serviceContext}/sample/folder${upload.displayPath}">${upload.name}</a> of size ${upload.properties.content.size}.</td></tr>    </table>  </body> </html>

URL Argument Handling

This sample demonstrates how to process URL arguments (single and multi-valued).

URL
GET /alfresco/service/sample/args

Examples:

http://<host>:<port>/alfresco/service/args?a=2&a=1&b=3
Description Document
File: args.get.desc.xml
<webscript>  <shortname>Argument Handling Sample</shortname>  <description>Demonstrate access to single and multi-valued arguments</description>  <url>/sample/args</url>  <authentication>none</authentication> </webscript>
Execute Script
File: args.get.js
// log each argument (assuming only one value has been provided for each) for (arg in args) {   logger.log(arg + "=" + args[arg]); }  // log each argument (assuming one or more values have been provided for each) for (arg in argsM) {   for each (val in argsM[arg])   {      logger.log(arg + "=" + val);   } } 
Response Templates
File: args.get.html.ftl
<#list args?keys as arg>   ${arg}=${args[arg]} </#list>  <#list argsM?keys as arg> <#list argsM[arg] as val>   ${arg}=${val} </#list> </#list>

Cache Control

This sample demonstrates how to specify Cache control at definition-time and run-time. (sorry, available 2.1 Enterprise onwards)

URL
GET /alfresco/service/sample/cache

Examples:

http://<host>:<port>/alfresco/service/sample/cache
Description Document
File: cache.get.desc.xml
<webscript>  <shortname>Cache Sample</shortname>  <description>Demonstrates how to control caching for a Web Script</description>  <url>/sample/cache</url>  <authentication>guest</authentication>  <format default="text"/>  <cache>   <never>false</never>   <public/>  </cache> </webscript>
Execute Script
File: cache.get.js
var tutorial = companyhome.childByNamePath("/Guest Home/Alfresco-Tutorial.pdf"); model.tutorial = tutorial;  cache.ETag = tutorial.properties.description; cache.lastModified = tutorial.properties.modified;
Response Templates
File: cache.get.text.ftl
${tutorial.properties.description}

A Complete Webscripts Caching Example

To effectively speed up webscripts execution through caching one, at least, needs to:

  • enable caching
  • quickly decide if a new response has to be generated or if the response cached by the requester is still valid.

The new response may be different because the webscript code has changed or the data managed by the webscript have changed.

  • Output the new response or simply a "NotModifiedHeader" based on decision at previous point

This Caching Alfresco Webscripts article explains how to implement these and other requirements. A reusableworking example is supplied to ease experimentation.

3xx Status Code Redirection

This sample demonstrates how to support redirection for the 3xx family of status codes. (available in 2.1.2 Enterprise onwards)

URL
GET /alfresco/service/sample/location

Examples:

http://<host>:<port>/alfresco/service/sample/location
Description Document
File: location.get.desc.xml
<webscript>  <shortname>Status Location</shortname>  <description>Demonstrates how to handle 3xx redirection status codes</description>  <url>/sample/3xxLocation</url>  <authentication>none</authentication> </webscript>
Execute Script
File: location.get.js
status.code = 307;  // Temporary redirect status.location = url.service + "/temp";
Response Templates
File: location.get.html.ftl
This resource you're looking for is at <a href="${status.location}">${status.location}</a>.

Associating Web Script with Custom View

This functionality will not have any user interface in 2.1, but you can execute a very simple JavaScript via URL to set a web script as a nifty custom view for a space:

Web Script Custom View Example #1
// example script to set the Document List webscript as the custom view for a node  // @param noderef    space to set webscript against as custom view  var dest = search.findNode("<noderef>");  dest.addAspect("cm:webscriptable");  dest.properties["cm:webscript"] = "/service/ui/doclist?q=*";  dest.save();

Web Script Custom View Example #2

You may wish to pass context to your web script to inform it which space or document it is processing against. This can be done as follows:

// example script to set the Document List webscript as the custom view for a node  // @param noderef    space to set webscript against as custom view  var dest = search.findNode("<noderef>");  dest.addAspect("cm:webscriptable");  dest.properties["cm:webscript"] = "/service/ui/doclist?nodeRef={noderef}";  dest.save();

Your web script will now receive an argument with the name nodeRef whose value is the node reference of the space or document to which the web script is being applied. The following code demonstrates how you can use this argument within your web script to retrieve the node:

<#assign nodeRef = args["nodeRef"]> <#assign node = companyhome.nodeByReference[nodeRef]>

Your web script can then proceed to business as usual with code like:

The name of this space is ${node.name}

and so forth.

JSON example

If you want to generate JSON output in your templates you can do it using Spring's helper Json classes in your freemarker template.

For example:

<#escape x as jsonUtils.encodeJSONString(x)>  {  "Results" : [    <#list data as item>     {"label":"${item.label}", "value":"${item.value}"},    </#list>    ]  } </#escape>

Webscripts in dialogs

See this page for how to easily create dialogs displaying web scripts. Using this mechanism, the creation of a dialog is only the definition of a corresponding well-configured action.

Java-backed Web Scripts Samples

A Wiki page is available that documents several Java-backed Web Scripts Samples which were developed during the Alfresco Barcelona Community Conference in 2008. This covers the concepts as well as development and code. It provides a link to an AMP file that you can use to quickly see how these are put together and deployed.