You are here

Creating a SiteTree webscript

 

One of the things

we needed to do was create a script that displayed the site hierarchy. I tried in vain to get this working with the built in webscripts that come with Alfresco, so in the end, decided to build my own. The steps to reproduce are as follows.

On the Alfresco side

First of all we need a script that will return the site structure. Unfortunately the only script I could find within Alfresco to do this, returned information back in CMIS format. Now whilst that should be useful, for a newbie, it was a pit of woe. Hopefully once Dave Caruana's CMIS parser comes in, this will become a lot easier to handle. So basically, what this script does is read in the site structure, and return back a JSON stream for processing at the other end.

getsitetree.get.desc.xml

 

1
2
3
4
5
6
7
8
<webscript>
  <shortname>Get Site Tree</shortname>
  <description>Retrieve the site tree from Alfresco</description>
  <url>/alfrescocms/getsitetree</url>
  <format default="json">extension</format>
  <authentication>user</authentication>
</webscript>
 

 

getsitetree.get.js

 

1
2
var folder = companyhome.childByNamePath("WebStore/www");
model.www = folder.children;

 

getsitetree.get.json.ftl

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<#macro parseChild objectModel>
	<#assign loop = 0 />
	<#list objectModel as child>
		<#if (loop > 0) >, </#if>
		{
			"name" : "${child.properties["name"]}",
			"nodeRef" : "${child.nodeRef}",
			"description" : "${child.properties["description"]}",
			"icon" : "${child.icon16}"
			<#if (child.children?size > 0)> 
				, "nodes" : 	[	
				<@parseChild child.children />
			]
			</#if>
		<#assign loop = loop + 1 />
		}
	</#list>
</#macro>
 
<#if (www?size > 0)>
{
	"nodes" : 
	[ 
		<@parseChild www />
	]
}
<#else>
	Empty
</#if>

 

A quick word about the above Freemarker template. As there may be an unlimited number of children to a folder, I needed some kind of recursive function to keep reading until there were no children left and display that in JSON format. The #macro section accomplishes this.

SpringSurf

Once we've completed that, we then need to utilise that in our SpringSurf application. The scripts are as follows.

getsitetree.get.desc.xml

 

1
2
3
4
5
<webscript>
  <shortname>Get Site Tree</shortname>
  <description>Retrieves the top level site tree from Alfresco</description>
  <url>/cms/getsitetree</url>
</webscript>

getsitetree.get.js

 

1
2
3
4
5
6
7
8
9
10
 
// get a connector to the Alfresco repository endpoint
var connector = remote.connect("alfresco"); 
var result = connector.call("/alfrescocms/getsitetree");
 
var sitetree = eval( '(' + result + ')' );
var remoteURL = remote.getEndpointURL("alfresco");
 
model.sitetree = sitetree;
model.remoteURL = remoteURL.substr(0, (remoteURL.length())-1);

 

getsitetree.get.html.ftl

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<#macro parseChild sitetree>
	<#if (sitetree?size > 0)>	
		<ul>
		<#list sitetree as node>
			<li><img src="${remoteURL}${node.icon}" /><a href="${url.context}/?filePath=${node.nodeRef}">${node.name}</a>	
				<#-- Check to see whether child nodes exist -->
				<#if node.nodes??>
					<@parseChild node.nodes />
				</#if>
			</li>
		</#list>
		</ul>
	<#else>
		Empty
	</#if>		
</#macro>
 
<h3><a href="#">Site Tree</a></h3>
<div>
 	<@parseChild sitetree.nodes />
 </div>
 

Again, the above freemarker recursively reads the site structure and formats it into HTML unordered lists for displaying within a site.

Gotchas

With everything that you develop, there's always going to be something that you miss that causes you endless hours of heartache.

  1. If there are no child nodes, nothing gets returned.
    As you'll see in the Alfresco side script, I check to see whether the current node being processed has any children, if it does, then a new element called nodes is inserted and the children listed within it. However, if no children are found, then it doesn't get created. This caused a problem on the SpringSurf end in that the template failed everytime it tried to recurse. Enter the ?? operator in Freemarker that checks for the existence of a variable. If it exists, the if statement equates to true and everything within the tags gets actioned, otherwise, it is ignored. Simple enough fix for two days of head scratching!
  2. Make sure you are passing the same type of variable at each recursion.
    All was going well with the top level, but I was getting confused when passing the next level into the same procedure. Therefore make sure that you are passing what the function is expecting to get!
  3. Authentication
    The SpringSurf script requires a user level of authentication in order to run. The SpringSurf application deals with this nicely (if configured to do so!). However the template I was working with hid much of the errors I was getting, so I decided to try and hit the script directly via the console. However, because no authentication was taking place when trying to retrieve the JSON stream, I was getting XML errors back that the script was complaining about. Of course, because I had no visibility to what was being returned, it made debugging very difficult.
Tags: