Alfresco Process Template on Classpath

Processing a template that is on the classpath instead of in the repository:

I’m deploying an Alfresco module (AMP) with a scheduled script that processes a FreeMarker template. The script resides on the classpath instead of in the repository and I thought it would be cleaner to deploy if the template was also on the classpath. I was sure that processing a FreeMarker template from the classpath must be functionality available in Alfresco out-of-the-box. However, after searching tirelessly for as long as my attention span would allow (admittedly not long) I couldn’t find such a call. So here is what I did…

All work was done on Alfresco 3.2r Enterprise.

The standard JavaScript API allows you to call processTemplate(template, args) on a node. “template” is either a string containing the FreeMarker or a node whose contents contains the FreeMarker. So I looked at org.alfresco.repo.jscript.ScriptNode and in particular at:

public String processTemplate(String template, Object args)

Then I looked at org.alfresco.repo.jscript.ClasspathScriptLocation since I knew the scheduled script bean uses it for the script which is on the classpath.

As described in the Alfresco Wiki (http://wiki.alfresco.com/wiki/3.2_JavaScript_API#Adding_Custom_Script_APIs) I extended the JavaScript API. I’ve already got several handy extensions in a NodeUtilScript Java class with an extension name of “nodeUtil” so I just added to it as follows:

/**
 * Process a FreeMarker Template against the given node.
 *
 * @param templateLocation the classpath of the template to execute
 * @param args Scriptable object (generally an associative array) containing the name/value pairs 
 *			   of arguments to be passed to the template
 * @param node the node to process the template against
 * @return output of the template execution
 * @throws AlfrescoRuntimeException
 */
public String processClasspathTemplate(String templateLocation, Object args, ScriptNode node) {

   ClasspathScriptLocation location = new ClasspathScriptLocation(templateLocation);

   try {
      // retrieve template content
      String template = IOUtils.toString(location.getInputStream());

      // process template
      return node.processTemplate(template, args);

   } catch (IOException ioe) {
      throw new AlfrescoRuntimeException("Error retrieving template", ioe);
   }
}

There’s not much to it:

  • create a ClasspathScriptLocation with a path to the template
  • get the template contents as an InputStream
  • use IOUtils.toString(InputStream) from Apache Commons IO to pull the template into a string
  • call processTemplate() on the given node using the retrieved template string, returning the result

It can then be called from my scheduled script (or from a web script).

Calling Script:

// get a node

var myNode = search.findNode("workspace://SpacesStore/c7e27390-12f0-44dd-b89b-ef63a8320d6b");

// prepare some data to pass to the template
var args = new Array();
args["arg1"] = "Hello";
args["arg2"] = "The World";

// process the template agains the node
var result = nodeUtil.processClasspathTemplate("alfresco/templates/email/MyTemplate.ftl", args, myNode);

MyTemplate.ftl:

I say, ${args["arg1"]!} to ${args["arg2"]!}.

Node-uuid is ${document.properties["sys:node-uuid"]}

So after executing the above script “result” contains “I say, Hello to The World. Node-uuid is c7e27390-12f0-44dd-b89b-ef63a8320d6b”.

Having my template deployable within my AMP really simplifies moving from development to UAT to production repositories. I don’t have to remember to actually upload it to the repository separately or to export it as an ACP and bootstrap it.

Of course, in many cases the template is in the repository for a very good reason – so that changes can be made to it by less technical users and those changes can be seen without restarting Alfresco. But it’s still nice to have the choice.

References:

Alfresco Wiki, 3.2 JavaScript API, Adding Custom Script APIs

http://wiki.alfresco.com/wiki/3.2_JavaScript_API#Adding_Custom_Script_APIs

Apache Commons IO (http://commons.apache.org/io/)

IOUtils (http://commons.apache.org/io/api-release/org/apache/commons/io/IOUtils.html)

 

This entry was posted in Alfresco, ECM and tagged by tim.frith. Bookmark the permalink.
tim.frith

About tim.frith

Alfresco Certified Engineer

Senior ECM Consultant
Tim holds a diploma in Computer Systems Technology from Camosun College as well as a Bachelor of Commerce Degree with a Finance specialization from the University of Alberta. He has over 10 years of experience developing web applications with Java as well as extensive database development experience with Oracle, IBM DB2, MS SQL Server, and MySQL.

In recent years he has focused on Enterprise Content Management, with specific training and experience in Alfresco's content management suite.

And finally, Tim is a strong believer that the Edmonton Oilers will soon reclaim their rightful place at the top of the hockey world. Yes, Stanley will once again come to town.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>