?

Log in

No account? Create an account
Overriding Alfresco webscript library ftl files - Nick [entries|archive|friends|userinfo]
Nick

[ website | gagravarr.org ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Overriding Alfresco webscript library ftl files [Jan. 30th, 2013|07:04 pm]
Nick
[Tags|, ]

On the whole, Alfresco is pretty good for customising and overriding, and there's been a lot of work done in 4.2 to make it even easier to customise Share and Surf. Overriding the spring beans for Java backed webscripts can be done with a bit of fiddling. One problem we have hit though is with overriding FTL files, especially library ones.

I'll use the Workflow REST API as an example here, as it's one we needed to change, but it applies to a lot of the webscripts too. A common JSON emitting Alfresco REST API has a FTL file somewhat like:

<#import "workflow.lib.ftl" as workflowLib />
{
   "data":
   <@workflowLib.taskJSON task=workflowTask detailed=true/>
}
It imports a library file, then calls one of the functions in there. If you want to inject a few extra bits into the JSON structure, then your only option is to edit the library file, or clone it. For simple libraries with a single macro, you could just clone the whole thing and customise, but for a library with many macros that gets rather nasty especially when upgrading. FreeMarker macros get replaced when a new one is defined with the same name, much like spring beans, so for our hypothetical macro file:

<#macro taskJSON task detailed=false>
<#escape x as jsonUtils.encodeJSONString(x)>
      {
         "id": "${task.id}",
          ....
      }
</#escape>
</#macro>

<#macro propertiesJSON properties>
<#escape x as jsonUtils.encodeJSONString(x)>
{
<#list properties?keys as key>
   "${key}":
   ...
</#escape>
</#macro>
To change taskJSON to inject some extra bits from the model, we'd have to copy the whole file and customise. However, there is a way that makes things a little less evil, which relies on macros overwriting each other. We take the original file, and copy it to the same directory structure in our module, but with a new name. Instead of workflow.lib.ftl we might instead go for workflow-original.lib.ftl. Next, add a new comment to the top, documenting where it originally came from, what version it is taken from etc. Now, create a new workflow.lib.ftl, and copy into that the whole of the macro we want to override. Add in the extra few JSON clauses. At the top of the file, add some documentation saying what version you copied and pasted from, what file it came from, and what changes you made. Trust me, you'll be thankful you did this when you come to upgrade... Finally, at the top of the file, before your customised macro, add in an include (not import, include) of the renamed original. Your new lib, with the name of the old one, now looks something like:

<#-- Customised File -->
<#-- Original: remote-api/config/alfresco/templates/webscripts/org/alfresco/repository/workflow/workflow.lib.ftl -->
<#-- Alfresco Version: 4.1.1.3 -->
<#-- Modification: Added custom1 and custom2 properties to the JSON -->

<#-- This pulls in all the macros we haven't needed to change -->
<#include "workflow-original.lib.ftl">

<#-- Override and customise the one we do need to change -->
<#macro taskJSON task detailed=false>
<#escape x as jsonUtils.encodeJSONString(x)>
      {
         "id": "${task.id}",
          ....
         "myCustom1": ${task.custom1},
         "myCustom1": ${task.custom2}
      }
</#escape>
</#macro>
(It's probably best to put your custom json at the start or end, to make upgrading easier)
linkReply