Instantiate Space Template on creation of Alfresco Site

Alfresco ShareWe could already create custom Share Site definitions (dashboard definitions actually), but in the past one could not determine by the Site object what ‘type’ of Site was initiated. I filed an enhancement request (May 2010), and recently I noted that it has been implemented (already for a while probably, 3.3 or 3.4). Now this property exists (st:sitePreset) we can use it to instantiate a RUP folder structure for a RUP site, and a Prince2 folder structure for a Prince2 site, and so forth. This blog describes my findings and solutions to instantiate a Space Template into the documentLibrary of a Share Site.

It is my intention to instantiate a Space Template when a Site is created of having some specific st:sitePreset value. I experimented in the past using a Site-name convention, but gave up due to time and no success. The challenge appears to be the creation of documentLibrary Space. The script processing the form and creating the Site does a lot, but creating the documentLibrary sub-space underneath the Site object does not come first in line… How to get this documentLibrary space…

I don’t want to mess around creating a customized version of this site creation script. If a new version of Alfresco arrives I have to do quite some double checking if any code has changed. The brilliant Alfresco repository offers a nice stable mechanism of Behaviours and Rules. Since the timing of it all seemed to be important, I decided to give the Behaviour a try. It seemed I need to wait until TRANSACTION_COMMIT of my Site object before having access to the documentLibrary sub space.

First, create a bean definition of a Behaviour. It should fire only if a Site object is created and committed. The action that needs to be executed is a (classpath) JavaScript. I created this behaviour-bean-context.xml bean definition in the folder shared/classes/alfresco/extension:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>

<beans>
 	<bean id="onCreateNode_Site" class="org.alfresco.repo.policy.registration.ClassPolicyRegistration" parent="policyRegistration">
               <property name="policyName">
                       <value>{http://www.alfresco.org}onCreateNode</value>
               </property>
               <property name="className">
                       <value>{http://www.alfresco.org/model/site/1.0}site</value>
               </property>
               <property name="behaviour">
                       <bean class="org.alfresco.repo.jscript.ScriptBehaviour" parent="scriptBehaviour">
                        <property name="notificationFrequency">
                           <value>TRANSACTION_COMMIT</value>
                        </property>
                               <property name="location">
                                       <bean class="org.alfresco.repo.jscript.ClasspathScriptLocation">
                                               <constructor-arg>
                                                       <value>alfresco/extension/script/onCreateSite_addSpaceTemplate.js</value>
                                               </constructor-arg>
                                       </bean>
                               </property>
                       </bean>
               </property>
       </bean>
</beans>

For more info about the possible events, the PDF article of Jeff Potts (of September 2007) still is a good resource!

Next, lets see what the JavaScripts needs to do. I created a file shared/classes/alfresco/extension/script/onCreateSite_addSpaceTemplate.js. It surprised my that I got a ChildAssociation in the args section of the behaviour object (line 2). I had to get the child  object to get hands on the Site object.  Next, determine if the dashboard definition (st:sitePreset) meets our required value to instantiate our Space Template. If so, get the Space Template, get the documentLibrary space, and instantiate the Space Template accordingly. Remind that companyhome is not at your service in the current context, so we need to execute a little search here.

// execute onCreate of a Site
var childAssoc = behaviour.args[0];
var site = childAssoc.getChild();

if (site.properties["st:sitePreset"]=="rup-dashboard"){
  logger.log("It is our dashboard/site type");
  var companyhome = search.findNode("path", ['workspace','SpacesStore','app:company_home']);
  var templates = companyhome.childByNamePath("Data Dictionary/Space Templates/RUP Template").children;
  var docLib = site.childByNamePath("documentLibrary");
  if (docLib){
    for (var i in templates){
      var child = templates[i];
      child.copy(docLib, true);
      logger.log("### copy "+ child.name);
    } // end for i in templates
  } else {
     logger.log("### Shame, there is no docLib");
  } //end if target
} // end if site.properties

My conclusion is that that using a behaviour doesn’t change the success-rate. The folder instantiation failed after all. The script/siteService to create a Site does quite a lot, and the creation of the Space “documentLibrary” is not the first on its list. So, what would happen if I create it first in my script? … Nothing serious. The Site creation script is just tolerant for the existence of this Space. So I insert the code in line 10 to create my own documentLibrary space:

  if (!docLib) {
     docLib = site.createFolder("documentLibrary");
  }

And it works indeed. I tried for a while, but could not find any flaws in the functional behaviour.

But, if this is the trick, than the Rule based Script could do the trick as well. And it can. If you execute the script (below) in a synchronous manner (not as a background task, then sometimes the create Site script will create the Space just between the test if it exists and the creation of the documentLibrary in ‘my’ script). Using the synchronous action I have seen no functional issues yet.

// execute onCreate of a Site
var site = document;

if (site.properties["st:sitePreset"]=="rup-dashboard"){
  logger.log("### Prepping to get Templates folder");
  var templates = companyhome.childByNamePath("/Data Dictionary/Space Templates/RUP Template").children;
  var docLib = site.childByNamePath("documentLibrary");
  if (!docLib){
    docLib = site.createFolder("documentLibrary");
  }
  if (docLib) {
    for (var i in templates){
      var child = templates[i];
      child.copy(docLib, true);
    } // end for
  } // end if
} // end if

This enables us to instantiate any space template without having to mess with Alfresco’s provided scripts. I personally like the behaviour/script combination. Especially if scripts and rules are defined all over the space-structure, there is no way to centrally manage or update the system behaviour once in production (or to cumbersome to recreate this structure). SVN and straight-forward deploy once again!

Advertisements

7 Responses to “Instantiate Space Template on creation of Alfresco Site”


  1. 1 Denys G. Santos July 5, 2011 at 16:25

    Hi, Congratulations. This is a good post. I go use this in my company, but before would like make one modification.

    In your post you can create a template and fisically set it in your site. I propose create one template area where we can put many diferents templates like RUP and SCRUM.

    When anybody will create any site one javascript will list all templetes present in template area and put them in the sites combo box (note that the name of template will be the name of node/folder).

    During the site creaton, the onCreateSite_addSpaceTemplate.js get the site.properties[“st:sitePreset”] parameter that is the name of template in the template area.

    In this case you have the site type and the path of template (path_of_template_area/site.properties[“st:sitePreset”]). So, we can continue do the same of onCreateSite_addSpaceTemplate.js do, coppy content of template choosed and paste in the DocumentLibrary folder of site.

  2. 3 Remco Hannink July 11, 2011 at 10:01

    Hello Tom,

    Thanks for the great post. I have tried something similar about 6 months ago and i the noticed that initial rights I had set on the template folders where not copied to the documentLibrary. According to the Alfresco forum this was some sort of bug in the Javascript API. Did you try to copy folders with specific rights in 3.4? Where the rights honored and copied?

    With kind regards,

    Remco Hannink
    The Netherlands

  3. 5 dido87 February 16, 2012 at 10:56

    Hi,
    thanks for the article,I try it with alfresco share 4.0.c but it doesn’t work I create a site but I didn’t get the space template under it.Did you try it with this version?

  4. 7 dido87 February 18, 2012 at 22:21

    I put behaviour-bean-context.xml file under shared/classes/alfresco/extension and onCreateSite_addSpaceTemplate.js :
    var site = document;
    if (site.properties[“st:sitePreset”]==”site-dashboard”){
    logger.log(“It is our dashboard/site type”);
    var companyhome = search.findNode(“path”, [‘workspace’,’SpacesStore’,’app:company_home’]);
    var templates = companyhome.childByNamePath(“Data Dictionary/Space Templates/Projet de conception logicielle”).children;
    var docLib = site.childByNamePath(“documentLibrary”);
    if (!docLib){
    docLib = site.createFolder(“documentLibrary”);
    }
    if (docLib){
    for (var i in templates){
    var child = templates[i];
    child.copy(docLib, true);
    logger.log(“### copy “+ child.name);
    } // end for i in templates
    } else {
    logger.log(“### Shame, there is no docLib”);
    } //end if target
    } // end if site.properties

    I create a folder script under shared/classes/alfresco/extension and put this onCreateSite_addSpaceTemplate.js.I restart and when I want to create new site I get :failure to create the site because the URL is already used.
    and when I remove the 2 files and create the site with the same name it’s created,did I have an error in js file?


Comments are currently closed.