Skip navigation
All Places > Alfresco Content Services (ECM) > Blog > 2016 > April


This post is going to describe how you can build next-generation web client technologies into Share and standalone web-clients. I’ve taken a pre-existing tutorial that I found on the Smashing Magazine web site and have adapted it for use in Surf. This is simply a demonstration that Share does not prohibit the use of any of these technologies and the method shown here is by no means the only way in which this task could be accomplished. The intention here is to shed further light on some of the Surf concepts.


You might be wondering why would you want to do this? Why not just go the whole hog and re-implement everything on a Node stack?


One reason is that you might simply want to add an existing page into Share and that you don’t want to have to reimplement all the features that Share currently provides. It’s also important to remember that through its use of Surf, Share is able to take care of a host of issues that you never need worry about - a single point of authentication to an Alfresco Repository across multiple REST APIs (CMIS, WebScripts, Public API) being the most obvious.


Rather than working with Share though, in this instance we’re going to create a standalone client using the Aikau Maven Archetype. We’re not going to be using Aikau, but it’s worth being aware that the archetype will build you a client that has everything you need to authenticate against an Alfresco Repository.


I’m not going to go through the details of the next-generation concepts as these are well documented in the Smashing Magazine article and you can read up on them there if you’re not familiar with them yourself.


Essentially we’re going to be writing ES6 JavaScript that is transpiled to ES5 via Babel, compiled into a single module (with associated source maps) using WebPack and minimized using Uglify. The whole JavaScript build process will be taken care of using Gulp and will all be wrapped within a Maven build.


Short Cut to Code

If you don't want to manually follow all the steps you can find the source code that you would otherwise build in this GitHub repository.



You have Node.js, NPM and Maven installed


Create a new client

Execute the following command in a location where you want to create your project

mvn archetype:generate -DarchetypeCatalog= -DarchetypeGroupId=org.alfresco -DarchetypeArtifactId=aikau-sample-archetype -DarchetypeVersion=RELEASE


Enter suitable suitable group and artifact ids and accept the remaining defaults (for example, I’ve used “org.alfresco” as the groupId and “next-gen” as the artifactId).


Building from an archetype is described in more detail in the Aikau tutorial.


Install gulp and webpack globally

Run the following command:

npm install -g gulp, webpack


Create Build Files

Create your package.json file in the root of the project

  'name': 'next-gen',
  'version': '0.0.1',
  'devDependencies': {
    'babel': '^5.8.23',
    'babel-core': '^5.8.24',
    'babel-eslint': '^4.1.1',
    'babel-loader': '^5.3.2',
    'eslint': '^1.4.1',
    'gulp': '^3.9.0',
    'gulp-babel': '^6.1.2',
    'gulp-rename': '^1.2.2',
    'gulp-sourcemaps': '^1.5.2',
    'gulp-uglify': '^1.4.1',
    'webpack': '^1.12.1',
    'webpack-stream': '^2.1.0'


Create a webpack.config.js file in the root folder:

module.exports = {
  entry: './src/js/index.js',
  output: {
    library: 'legoQuotes',
    libraryTarget: 'umd',
    filename: 'lib/legoQuotes.js'
  externals: [
      lodash: {
        root: '_',
        commonjs: 'lodash',
        commonjs2: 'lodash',
        amd: 'lodash'
  module: {
    loaders: [
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel',
        query: {
          compact: false


Create a gulpfile.js file in the root folder:

var gulp = require( 'gulp' );
var webpack = require( 'webpack-stream' );
var sourcemaps = require( 'gulp-sourcemaps' );
var babel = require('gulp-babel');
var rename = require( 'gulp-rename' );
var uglify = require( 'gulp-uglify' );

gulp.task('default', function() {
  return gulp.src( 'src/js/index.js' )
    .pipe( babel() )
    .pipe( webpack( require( './webpack.config.js' ) ) )
    .pipe( gulp.dest( './src/js/dist' ) )
    .pipe( sourcemaps.init( { loadMaps: true } ) )
    .pipe( uglify() )
    .pipe( rename( 'legoQuotes.min.js' ) )
    .pipe( sourcemaps.write( './' ) )
    .pipe( gulp.dest( './src/js/dist/' ) );


For more information on what these files do, you should read the Smashing Magazine article - the purpose of this blog is not to explain these things, simply to show how they can be used with Share/Surf.


Create JavaScript resources

This should be placed in the “src/js” folder of your project - note that it is intentionally not in the “src/main” folder as we are going to build the JavaScript separately from the rest of the project. The files you want are:

    • benny.js 
    • emmet.js 
    • index.js 
    • LegoCharacter.js 
    • utils.js 
    • wyldstyle.js

These can be found in the linked source from the Smashing Magazine article, they are only provided for something to build!


Create CSS resources

Copy the 'style.css' from the linked source into a new folder called 'css' in 'src/main/webapp/'. We could use WebPack to bundle up CSS resources but we're going to let Surf take care of this as we'll see later.


Maven Updates

We now want to update our pom.xml to allow us to build our next-gen resources as part of the Maven build. Add the following to the <build> <plugins> element:

          <echo>NPM Package Installation</echo>
          <exec executable='npm' dir='${project.basedir}'>
            <arg line='install' />
          <echo>Run Gulp Build</echo>
          <echo>Build and overlay JS</echo>
          <exec executable='gulp' dir='${project.basedir}'>


Here we’re using the Maven Ant Run plugin to get all the required Node packages (defined in the package.json file) and call Gulp to perform the build.


So somewhat impressively we’re using Ant, Maven and Gulp!


Next we want to ensure that we copy our JavaScript and required Node modules into the web application that we’re going to build. Add the following plugin configuration after the previous entry that you just added:



Finally we need to make one more change. The Aikau archetype configures the Jetty plugin to use the “src” rather than “target” location to enable fast development, but for a cleaner build we are copying the “node_modules” into target so need to change the plugin configuration appropriately.


Update the <webApp> section so that all instances of “src/main/webapp” are replaced with “target/aikau-sample”


Create Surf Objects

We now have our build in place, so it’s time to create the required Surf objects.


Surf has a complex but powerful set of objects for constructing pages. One of the goals of Aikau was to hide these objects away from developers to allow them to focus on creating pages with just WebScripts. We’re now going to build some of these objects and it may become apparent why we wanted to hide this complexity away.


The first thing we need to create is a Page object. This is defined as XML file and the key thing you can define in this file is what level of authentication the user requires to access the page. Here we’re going to use “none” because we want to avoid a login step - however, you could just as easily set the value to be “user” or “admin”.


Create a file called “next-gen-page.xml” in the “src/main/webapp/WEB-INF/surf-config/pages/” folder. It should contain the following XML.

<?xml version='1.0' encoding='UTF-8'?>


The Page references a Template-Instance to be rendered. This is the next file to declare. Create a file called “next-gen-template-instance.xml” in the “src/main/webapp/WEB-INF/surf-config/template-instances” folder. It should contain the following XML:

<?xml version='1.0' encoding='UTF-8'?>


The Template-Instance references a Template-Type - this needs to be declared. Create a file called “next-gen-template-type.xml” in the “src/main/webapp/WEB-INF/surf-config/template-types” folder. It should contain the following XML:

<?xml version='1.0' encoding='UTF-8'?>
  <title>Next Gen Page</title>
  <processor mode='view'>


A Template-Type can have a number of different processor modes. We really only care about the “view” mode (the other modes were created for WCM purposes that are not widely used anymore). Surf supports a number of different processors out-of-the-box and it is possible to configure in additional processors. Here we’re using a WebScript processor and are providing the URI to match against a WebScript.


This WebScript needs to be defined. In the “src/main/webapp/WEB-INF/webscripts” folder create the following files:



  <shortname>Template For Next Gen Pages</shortname>
  <family>Page Templates</family>



<!DOCTYPE html>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <title>Lego Quote Module Example</title>
    <div class='container'>
      <blockquote id='quote'></blockquote>
      <button id='btnMore'>Get Another Quote</button>
    <script src='${url.context}/node_modules/lodash/index.js'></script>
    <script src='${url.context}/node_modules/babel-core/browser-polyfill.js'></script>
    <script src='${url.context}/js/dist/legoQuotes.min.js'></script>
      (function(legoQuotes) {
        var btn = document.getElementById('btnMore');
        var quote = document.getElementById('quote');

        function writeQuoteToDom() {
          quote.innerHTML = legoQuotes.getRandomQuote();

        btn.addEventListener('click', writeQuoteToDom);



Create Reusable Page Structure

We don’t want to have to create all of these files (page, template-instance, template-type, WebScript) for every single page in our application (of course if you’re building a Single Page Application then you’re only going to need to do this once). So instead we’re going to abstract the WebScript file contents into an include template and then make it possible to parametrize a WebScript to run as is done in Aikau.


Let’s update the template file so that is looks like this:

<!DOCTYPE html>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <title>Next Gen Example</title>
    <script src='${url.context}/node_modules/lodash/index.js'></script>
    <script src='${url.context}/node_modules/babel-core/browser-polyfill.js'></script>
    <#assign regionId = page.url.templateArgs.webscript?replace('/', '-')/>
    <@autoComponentRegion uri='/${page.url.templateArgs.webscript}'/>

In this example we are using 3 custom FreeMarker directives that Surf provides:

    • <@outputJavaScript/> 
    • <@outputCSS/> 
    • <@autoComponentRegion>

The first two mark the location where page specific JavaScript and CSS will be output - in a moment we’ll show how to define what should be output.


The <@autoComponentRegion> is used to automatically create a Surf Region and a Surf Component for the WebScript that we’re going to use to define the page. The URI for the WebScript to use is taken from the same UriTemplate that is configured for Aikau pages.


Let’s now create the WebScript for our page. Create the following files in the “src/main/webapp/WEB-INF/webscripts/pages” folder.


First the descriptor: “LegoQuotes.get.desc.xml”

<family>Next Gen Pages</family>


The key thing to note here is the <url> - we’re going to be using that when we load our page.


Now the template, “LegoQuotes.get.html.ftl”

<@link rel='stylesheet' type='text/css' href='${url.context}/res/css/style.css'/>
<@script type='text/javascript' src='${url.context}/res/js/dist/legoQuotes.min.js'/>
  (function(legoQuotes) {
    document.addEventListener('DOMContentLoaded', function(event) {
      var btn = document.getElementById( 'btnMore' );
      var quote = document.getElementById( 'quote' );

      function writeQuoteToDom() {
        quote.innerHTML = legoQuotes.getRandomQuote();

      btn.addEventListener( 'click', writeQuoteToDom );

<div class='container'>
<blockquote id='quote'></blockquote>
<button id='btnMore'>Get Another Quote</button>

Again, we’re using 3 new FreeMarker directives

    • <@link> 
    • <@script> 
    • <@inlineScript>

The <@link> directive is how we reference CSS files to be output into the location of the <@outputCSS/> directive that we declared in our template.


The <@script> directive references JavaScript files to be output into the location of the <@outputJavaScript/>.


The <@inlineScript> directive allows us to write snippets of JavaScript that will be inserted at the location of the <@outputJavaScript/> directive.


There are two benefits to be aware of here - firstly all JavaScript and all CSS will be combined so that only a single resource of each type will be loaded onto the page - this reduces HTTP handshaking and improves performance.


Secondly the generated resources will have a name that is an MD5 checksum matched to their content. This means that these files can be infinitely cached on the browser as if the content changes a different resource name will be generated.


The End Result

Now run the following command:

mvn clean install jetty:run


Be aware, it will probably take a few minutes to build and startup - please be patient.


Once you see the message: “[INFO] Started Jetty Server”, open the URL “http://localhost:8090/aikau-sample/page/ngp/ws/legoQuotes” in your browser and you should see the following:




You can now click the button to generate random Lego Movie quotes.



In this post I've demonstrated that it is possible to make use of the current crop of tools for building web applications without discarding the benefits that Surf brings to the table with regards to creating clients for Alfresco. In the process I've hopefully been able to provide some useful information on creating Surf objects.

Aikau 101

Posted by ddraper Apr 22, 2016


A complaint that we have heard on occasion is that it is hard to find and hire people with Aikau skills. It’s probably not unexpected that there are few people with a lot of experience in Aikau - after all it’s only really existed as a named entity for a couple of years and is specific to a single vendor in a relatively niche market of IT.

...But “skills” ?

If you have working knowledge of HTML, JavaScript and CSS then you’re pretty much halfway there. The other half of the puzzle is getting your head around 3 concepts:

    • Modules
    • Pub/Sub
    • Services

It’s also vitally important to understand the problem that Aikau is trying to achieve. It is not intended to be the go-to solution for building any web application:


It is about providing a way in which a page can be defined in such a way that anyone can make small or large alterations to that page with the minimum of effort. It is about providing a way in which Alfresco can quickly iterate on its own use cases (as well as those of its partners, customers and community) in a backwards compatible way. Finally, it is about providing re-usable components to build solutions that are specifically targeted for Alfresco.



Aikau aims to decompose solutions into the smallest possible, reusable components (or widgets). Each widget is typically independent of any other in order that it can be tested as a single atomic unit.


Being able to test each widget is essential.


By defining a widget as a configurable “black box” we are able to write tests to verify how a widget behaves when configured in a certain way. We do not have to write full integration tests of how every widget interacts with every other type of widget - simply how a widget responds to publications (more on that later).


When we first started writing Aikau, there was no native module loading available (unlike now) so we used the AMD paradigm as provided by Dojo (also implemented in RequireJS). Native JavaScript imports (to the best of my knowledge) are still constrained to just JavaScript files - but some frameworks (such as Angular 2) are providing the ability to define components that reference external CSS and HTML templates (for the record, Aikau was doing this 3 years in earlier !)


Although it is the Surf framework that handles the CSS, HTML (and i18n) dependency loading it is the Aikau widget that defines the dependencies. When creating an Aikau widget you simply need to understand how these dependencies can be declared.


It’s important to be able to recognize the “boiler plate” of an Aikau widget. This is the most simple example of a widget that defines HTML, CSS and i18n dependencies.

       function(declare, _WidgetBase, _TemplatedMixin, template, AlfCore) {

  return declare([_WidgetBase, _TemplatedMixin, AlfCore], {

    i18nRequirements: [{i18nFile: './i18n/'}],

    cssRequirements: [{cssFile:'./css/MyWidget.css'}],

    templateString: template,

    postCreate: function() {
      // TODO Put your code here


All your code (any JavaScript you like) should go into the postCreate function.


Let’s say that you don’t want an external template and have no CSS or i18n dependencies. This reduces the basic widget to this:

       function(declare, _WidgetBase, AlfCore) {

  return declare([_WidgetBase, AlfCore], {

    buildRendering: function() {
      // TODO: Create some HTML for the widget and assign to this.domNode

    postCreate: function() {
      // TODO Put your code here


The buildRendering function should be implemented to construct the DOM for the widget - again, using any JavaScript that you’d like.


The buildRendering and postCreate functions are part of the Dojo widget life-cycle that Aikau make use of. It is necessary to extend “dijit/_WidgetBase” and to use the define and declare functions when writing a widget - but literally everything else your widget does is entirely up to you. We just happen to use a lot of other Dojo capabilities because we find them useful - whether or not you choose to is entirely up you.


But there is no magic here - it is just JavaScript.


The define function tells the AMD loader what modules to load, the declare function creates the JavaScript Class. The buildRendering and postCreate functions are called when an instance of the class is created. A more in-depth description of widget creation can be found here.


In order to make it possible for a page to be easily customized it is essential that the building blocks of that page (the widgets) be completely decoupled from one another. This is where the publication/subscription model comes in.


The Publication / Subscription Model

It would undoubtedly be much easier to implement a solution where there are fixed references between widgets, but that would greatly constrain what a 3rd party could do a page.


Instead Aikau widgets communicate with one another by publishing requests on topics and subscribing (or listening) to and responding to other requests that are published.


In order to ensure that communications between widgets can be constrained to a subset of widgets it is possible to define a scope. This allows one group of widgets that share a common topic type to communicate with each other without impacting another group of widgets.


Imagine a scenario where you have two lists on the page each with their own sorting controls - changing the a sort order in one list should not update the order of the other list. This is where scoping comes in.


A publication/subscription scope is set on a widget by setting its “pubSubScope” attribute with a string value. This value is prefixed onto all topics published and only topics prefixed with that value are subscribed to.


The “pubSubScope” attribute is one of a handful of attributes that is passed down from parent widget to child widget. A child will have the same scope as its parent unless specifically configured otherwise.



As well as being decoupled from each other via the publication/subscription model, widgets are also decoupled from data. This allows a widget to work with multiple data sources - so for example the “alfresco/lists/AlfList” widget can be used to render any list - documents, sites, people, properties, aspects, etc. All data should be accessed via a service.


Services in Aikau can be considered the glue that binds the page together. They can perform a number of roles as well as handling XHR requests - the “alfresco/services/DialogService” for example is purely responsible for the creation and management of modal dialogs. If you don’t like the default dialogs in Aikau then an alternative service can be used instead - widgets don’t “care” what services their request for a dialog, only that it is serviced.


The most common role of a service though is to make asynchronous (XHR) requests for data from the Alfresco Repository. A widget will publish a request for some data on a specific topic and if a service exists that subscribes to that topic then it will process that request, retrieve the requested data from the Alfresco repository and return it to the widget on the requested response topic.


Dipping back very briefly into the subject of publication/subscription scoping…. Services are typically not scoped. However, in order that widgets are able to communicate with them all publication configuration can include an option to publish “globally” - or without scope. This ensures that it is not necessary to have instances of services at every scope used by widgets on the page.


Putting It Altogether

An Aikau page is declared as a model in a WebScript JavaScript controller. I typically describe this as a JSON model and am frequently criticized by my colleagues for describing it as such because in the WebScript controller you are technically creating a JavaScript Object Literal - but on it’s way to being processed by Surf it does get converted into JSON, so I’m going to keep calling it JSON.


The structure of the model in your JavaScript controller should look like this:

model.jsonModel = {
  services: [],
  widgets: []
}; and widgets being added into the appropriate arrays.

The “widgets” model will typically become a deeply nested tree with widgets placed inside other widgets.

By constructing a page like this is means two things:

    1. It is possible to intercept and customize a default model before it is processed. This means that extensions can add, remove and reconfigure widgets and the fact that widgets are decoupled means that this can be done without causing reference errors
    2. Page models can be dynamically constructed and rendered safely on a running server (as demonstrated numerous times over the last year at various Alfresco conferences and Tech Talk Live sessions)


    The disadvantage of this approach is that for simplicity you normally have to rely on the various widgets in the “alfresco/layout” package to build the structure of your page rather than just using HTML/CSS.


    However it is possible to embed Aikau into any DOM node on the page by including a “rootNodeId” attribute in your model. This would allow you to construct the layout for your page in your WebScript template using HTML into which the Aikau model could be built.


    It’s also possible to have multiple Aikau models embedded into different locations on the page - the best approach for this would be to use the standard Surf region/component development approach. Effectively this is what you see on most pages in Share - the header is a Surf Component rendering an Aikau model and the remainder of the page is made up of other Surf Components rendering YUI2.



    Aikau is really just a way of packaging HTML, CSS and JavaScript into reusable modules. It isn’t a new language, but is merely a new way of thinking about web development. This approach has its advantages (reuse, extensibility, customization, dynamic page creation) but also has its drawbacks (requires a different way of thinking, is a layer of abstraction away from traditional web development).


    It’s not a framework for any use case - it’s targeted specifically for Alfresco development and depending upon your specific use case it may or may not be the right choice for you. It is worth remembering that unless we know your use cases we’ll never be able to address them - so if there’s something you’d like Aikau to do better then please let us know!


    This blog post describes how you can now safely import Aikau library files into WebScript controllers when you have multiple versions of Aikau available in your application. PLEASE NOTE: This information only applies if you're using Alfresco 5.1 or 5.0.3 onwards.




    In the Aikau 1.0.63 release we have completed the final stage of fixing AKU-411. This bug was raised because there was no reliable way of knowing which version of an Aikau library file would be imported into a WebScript JavaScript controller.


    Although Alfresco Share will only ship with a single version of Aikau (included as a JAR file in the WEB-INF/lib folder) additional JARs might be added when applying AMP files (such as Records Management). This meant that there would be duplicate versions of library files available on the classpath to be imported and as a result you could not guarantee which version would be loaded.


    We made some changes in the Alfresco 5.0.3 service pack to remedy this problem (also available in Alfresco 5.1) and have now updated Aikau to take advantages of these capabilities.


    At the time of writing there is only a single library file shipped with Aikau which can be used for building Document Libraries within a page - but in the future we hope to provide many more library files to address a variety of common use cases.



    A New Way to Import Library Files

    Previously you would have needed to imported the library file as follows:

    <import resource='classpath:alfresco/site-webscripts/org/alfresco/aikau/webscript/libs/doclib/doclib.lib.js'>


    But you can now import the file as follows:

    <import resource='classpath:alfresco/site-webscripts/org/alfresco/aikau/{aikauVersion}/libs/doclib/doclib.lib.js'>


    The {aikauVersion} token will automatically be swapped out for the version of Aikau that is being used by Surf. By default the most recent version of Aikau available will always be used, however it is possible to select and use an older version from the Module Deployment page (found at /share/page/modules/deploy - see screenshot below)




    If you use the {aikauVersion} token then you are effectively stating that you always want to use the same version of the library file that is shipped with the currently used version. However, it is still entirely possible to use a specific version, e.g.

    <import resource='classpath:alfresco/site-webscripts/org/alfresco/aikau/1.0.63/libs/doclib/doclib.lib.js'>


    However, this does mean that you need to ensure that the version specified is available.


    This means that we are now able to make incremental improvements and fixes to the Document Library import file, it also means that it now makes sense for us to start providing more files that can be imported.


    How To Use The Document Library Import

    The doclib.lib.js file has been written with re-use in mind. It provides a number of different functions that can be called giving you the choice of building an entire Document Library or just fragments of the Document Library (such as the list, the toolbar, the tree, etc) and all the functions take a configuration object so you can control how the Document Library will be built.




    So for example if you wanted to build a full Document Library for company home you could use the following in your WebScript controller:

    <import resource='classpath:alfresco/site-webscripts/org/alfresco/aikau/{aikauVersion}/libs/doclib/doclib.lib.js'>

    model.jsonModel = {
      services: getDocumentLibraryServices(),
      widgets: [
          rootNode: “alfresco://company/home”,

    There are a variety of other options that you can provide when calling the function, for example:

      • idPrefix - (string) A prefix for the IDs of all the widgets created
      • siteId - (string) the site shortName attribute of the site to build a Document Library for
      • containerId - (string) the name of the folder in which the Document Library content resides within the site (typically this would be “documentLibrary”
      • rawData - (boolean) whether or not to make XHR requests directly to the Alfresco Repository and bypass the Alfresco Share web-tier
      • rootNode - (string) A nodeRef to root the Document Library
      • rootLabel - (string) The label for the root of the Document Library as shown in the breadcrumb trail and in the navigation tree
      • useHash - (boolean) Whether or not to update the browser URL hash with Document Library state
      • getUserPreferences - (boolean) indicates whether or not the user preferences should be retrieved from the Alfresco Repository
      • docLibPreferences - (object) custom preferences for the Document Library (sortField, sortAscending, showFolders, hideBreadcrumbTrail, showSidebar).

    The functions that you can call include:

      • getDocLib (builds the whole Document Library calling the following functions as appropriate)
      • getDocLibFilters
      • getDocLibTree
      • getDocLibTags
      • getDocLibCategories
      • getDocLibToolbar
      • getDocLibBreadcrumbTrail
      • getDocLibList
      • getDocLibCreateContentMenu
      • getDocLibSelectedItemActions
      • getDocLibSortOptions
      • getDocLibConfigMenu


    Localization Properties Importing

    As well as providing an import for the Document Library model and additional properties import is provided for localization purposes. For the background on importing properties files you should read this related blog post.


    These imports support the {aikauVersion} token in exactly the same way. Previously you would have imported the file as follows:



    But now you can do so using the token:


    Filter Blog

    By date: By tag: