Sunday, February 26, 2012

Writing my First Web Script for Alfresco

I started with the goal of creating a custom XML file which would be somewhat a "data extract" across a set of files which, in my case, will be located in the same folder. However, understanding how web scripts work and writing a functional web script that provides some meaningful output took me a bit longer than I expected (about 6 hours total, but now I know a lot about luceneSearch function and Alfresco AVM Store API), so at least I got to the point where I can list all the files in the folder and render this data in the HTML file.

The web script required 3 files to run: a definition file, a javaScript file which gets the folder details from the AVM store and a ftl (FreeMarker template) file which renders HTML. It is also possible to render output in JSON format (and other formats, I guess) but I did not get there yet. The files are called items.get.desc.xml, items.get.js and items.get.html.ftl.

I placed these files into the Alfresco "classes" path, in the subfolder "items" under "webscripts". The full path on my PC is

C:\Alfresco\tomcat\webapps\alfresco\WEB-INF\classes\alfresco\extension\templates\webscripts\items

And the full path to the actual files I'm interested in is

Y:\hostingitems\HEAD\DATA\www\avm_webapps\ROOT\items

where Y is the drive I mapped AVM repository to. "hostingitems" is the name of the web project where files were created. Currently I'm getting back all files in the folder, so if I want to sort out only XML files I'll need to additional logic.

items.get.desc.xml is a web script description file. Basically, it tells where the script is located and what it does.

<webscript>
<shortname>Get all items</shortname>
<description>Returns a list of items</description>
<url>/items</url>
<url>/items.json</url>
<url>/items.html</url>
<format default="json">extension</format>
<authentication>guest</authentication>
<transaction>none</transaction>
</webscript>

items.get.js returns the AVM store and the particular folder. The "s" variable is the web project name, and the "p" variable is the path to the folder. They can be passed to the web script as arguments rather than being hardcoded, but again that's a future "TODO" task.

script: {
var s = "hostingitems";
var p = "/www/avm_webapps/ROOT/items/";

// get avm node
var store = avm.lookupStore(s);
if (store == null || store == undefined)
{
status.code = 404;
status.message = "Store " + s + " not found.";
status.redirect = true;
break script;
}
// get items data folder
var itemsNode = avm.lookupNode(s + ":" + p);
if (itemsNode == undefined)
{
status.code = 404;
status.message = "Could not find items folder. Path:" + p + " Store:" + s;
status.redirect = true;
break script;
}

// set store and folder in the model
model.store = store;
model.folder = itemsNode;
}

items.get.html.ftl is a template that renders html. Dead simple, it only loops through the folder contents and populates some settings of the files into an html table.

<#assign datetimeformat="EEE, dd MMM yyyy HH:mm:ss zzz">
<html>
<head>
<title>Items in folder: ${folder.displayPath}/${folder.name}</title>
</head>
<body>
<p><a href="${url.serviceContext}/sample/avm/stores">AVM Store</a>: ${store.id}</p>
<p>AVM Folder: ${folder.displayPath}/${folder.name}</p>
<table>
<#list folder.children as child>
<tr>
<td>${child.properties.creator}</td>
<td>${child.size}</td>
<td>${child.properties.modified?datetime}</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>
</td>
</tr>
</#list>
</table>
</body>
</html>

Now when my files are ready I can go and check the Alfresco web scripts by logging in and naivgating to
http://localhost:8080/alfresco/service/index

I currently have 463 web scripts.

Web Scripts Home

Browse all button shows me the list - fortunately the user defined web scripts are on the top so I do not have to scroll the whole list.

Web Script Details

This data obviously comes from my description file. This would be displayed even if the script itself results with an error. For example, if I make a syntax error in my javaScript and navigate to the alfresco/service/items.html, I will get an error message.

Web Script Error

Fortunately, the error messages have been mostly helpful - in this case, it's just a missing closing bracket after an if statement. So, I fix it, save js file, go back to web scripts page, press "Refresh web scripts" to pick up my changes and try again. And there's my list of files generated by a web script.

Web Script Results

Reference:

Alfresco Developer Guide

by . Also posted on my website

No comments: