On almost every topic

As Toni shows in his post Alfresco integrates with MS Office for iPad out of the box.

Multiple Alfresco Share Configuration Files

Like you can have multiple models in your Alfresco back-end project, you can also have multiple Share configuration files in your Alfresco Share project. This makes your Share configuration more readable. You can have for example a separate Share configuration file for your workflow form configuration and one to configure your custom content model.

You only need to provide a context file that references the configuration files using Spring bean configuration, just like in your back-end project.

Let’s say I have a custom model for partner agreements in the back-end. The following example references an agreement-share-config.xml file with the Share configuration for my partner agreement content model and an agreement.properties file for the labels.

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
  <!-- Share Configuration -->
  <bean id="custommodel.config" class="org.springframework.extensions.config.ConfigBootstrap"
	init-method="register">
    <property name="configService" ref="web.config" />
    <property name="configs">
      <list>
	<value>classpath:alfresco/web-extension/agreement-share-config.xml</value>
      </list>
    </property>
  </bean>
  <!-- Resource bundles -->
  <bean id="example.resources"
	class="org.springframework.extensions.surf.util.ResourceBundleBootstrapComponent">
    <property name="resourceBundles">
      <list>
	<value>alfresco.web-extension.agreement</value>
      </list>
    </property>
  </bean>
</beans>

Save the file for example as agreement-share-context.xml in the Share web-extensions folder where the Share configuration and the labels file are also located in this example. If you add things like type or aspect visibility or advanced search forms do not forget to set the replace attribute to false, otherwise it might overwrite settings in other Share configuration files.

This new release of Activiti Designer includes Kickstart, a simplified process editor and form editor that automatically generates the Alfresco artifacts and allows you to deploy them in various ways including using CMIS.

I have been playing with Kickstart a bit and must say it looks promising. At first it is a bit confusing as the process is not displayed as the traditional process designer with tasks and connecting arrows, but once you are used to it, it is quite powerful.

There are things not supported in this release like for example adding task listeners, but these will be added in future releases. Listeners for things like conditional tasks, e-mail notifications or to output task variables to the execution level are generated automatically.

For a good overview watch this video from the Alfresco Summit 2013: https://www.youtube.com/watch?v=S9x9uYKONSE.

The Alfresco Summit will be in Barcelona from 4 to 7 November and in Boston 12 to 15 November. Like other years there are many developer tracks, but starting form this year there are also business tracks including many customer cases. This is your chance to meet Alfresco partners, customers and employees and learn about new features, new ways of doing great work with Alfresco and exchanging ideas and experiences. Put your content to work!

Alfresco Community now has its own documentation. It also covers the Maven Alfresco SDK.

Alfresco Consultant Maurizio Pillitu wrote a blog post about the Maven Alfresco  SDK. In his post he shows you how to create projects using the Alfresco Maven archetypes.

The Maven Alfresco SDK allows you to manage the life cycle of your Alfresco projects in a standardized way without the need to download anything other than Maven. Run a single maven command on your console and start doing great work!

Today Alfresco released the Maven Alfresco SDK 1.0. The current version focuses on the Community release, but support for the Alfresco Enterprise is to be expected next month. The release provides complete and documented Maven life cycle support for Alfresco projects including dependency management, packaging and testing.

In Alfresco 4.0 you can transfer files from the repository to a remote file system. You can use it for example to publish static content to a web server. In older Alfresco versions this was only possible for Web Projects that used Alfresco’s AVM (Advanced Versioning Manager) repository.

I had some difficulties setting up the target. This feature does not seem to be documented very well. Luckily Michael McCarthey of Tribloom documented the basic steps on his blog.

Alfresco supports replication jobs that allow you to schedule transfers of content and structure between a source and a target system. In order to use it you first configure a Transfer Target, being a remote Alfresco instance or a File System Transfer Receiver, and then you use these targets in your replication jobs.

In order to succesfully transfer files to a remote file system you need to change the type of the transfer folder to File Transfer Target and you have to make sure to set the end point to /alfresco-ftr/service/api/transfer

This Alfresco forum post might also be helpful. It explains the difference between the payload property in the replication job and the root folder property in the transfer target.

Integrating the dojo.gantt widget with Alfresco using CMIS

Last week I received an e-mail from an Alfresco developer with a question about integrating dojox.gantt with Alfresco. The dojox.gantt widget is part of the popular Dojo Toolkit and provides an integrated widget for project and resource management.

I never used the Dojo Toolkit before, but I decided to give it a try and I must say that it is a poweful framework for web application development. In this tutorial I will show you how you can integrate dojox.gantt with Alfresco without much coding thanks to Alfresco’s Web Scripts and CMIS. In the end you will be able to load and save project data from Alfresco into the dojox.gantt widget. I used Alfresco Community 4.0b to test the integration, but it should also work with other versions.

Data Model

The dojox.gantt widget uses a simple JSON format to represent project management data. Here is an example:

The structure consists of one or more project items and each project has zero or more tasks. The first step is to upload a dojox.gantt project file into Alfresco. We will use this file as a source for the project data. The dojox.gantt widget requires at least one project item, otherwise you will not be able to open the context menu to add and update projects and tasks. Create a file called gantt_default.json in Alfresco in the Company Home space and add the following lines:

{"identifier":"id","items":[{"id":1,"name":"Development Project","startdate":"2012-2-11","tasks":[]}]}

Web Script

The next step is to create the Web Script. If you are not familiar with the concept of Web Scripts, I suggest that you read this first. On the file system go to the Alfresco Web Scripts folder to create a new Web Script. I used the following location:

tomcat/shared/classes/alfresco/extension/templates/webscripts

First create a file called dojox-gantt.get.desc.xml and add the following lines:

<webscript>
  <shortname>dojox.gantt</shortname>
  <description>dojox.gantt example</description>
  <url>/samples/gantt</url>
  <authentication>user</authentication>
</webscript>

This file declares the Web Script and the URL to access the service. Next create a file dojox-gantt.get.html.ftl and add the following lines:

<html>
  <head>
    <title>Dojo Gantt test</title>
    <link type="text/css" rel="stylesheet" href="http://yandex.st/dojo/1.7.1/dijit/themes/claro/claro.css">
    <link type="text/css" rel="stylesheet" href="http://yandex.st/dojo/1.7.1/dojox/gantt/resources/gantt.css">
    <script src="http://yandex.st/dojo/1.7.1/dojo/dojo.js" type="text/javascript"></script>
    <script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dojox.gantt.GanttChart");

dojo.addOnLoad(function(){
 
  // put the save code here later

  var ganttChart = new dojox.gantt.GanttChart({
    readOnly: false,
    dataFilePath: "${url.context}/s/cmis/p/gantt_default.json/content", 
    withResource: false
  }, "gantt");
  
  ganttChart.init();  
  ganttChart.loadJSONData();
  
});
    </script>
  </head>
  <body class="claro">
    <div class="ganttContent">
      <div id="gantt">
      </div>
    </div>
  </body>
</html>

This file is the view. It loads the required libraries, initializes the Gantt Chart and then loads the data from the server. This line of code is a CMIS get content request to load a file by providing the path:

${url.context}/s/cmis/p/gantt_default.json/content

Since the file is located in Company Home, Alfresco’s root space, providing the name of the file is enough. The /content part of the URL tells Alfresco to return the contents of the file in stead of the object metadata:

In order to test the Web Script first go to the Web Scripts Home page in Alfresco by visiting http://localhost:8080/alfresco/s/. Click the refresh button to add the new Web Script. When you now visit the page http://localhost:8080/alfresco/s/samples/gantt you should see a page similar to this:

When you move the mouse over the project name Requirements you will see a menu to add new tasks.

Saving Data

The dojox.gantt widget is now able to load data from Alfresco using the dataFilePath parameter, but not able to save it back into the system. To save data back into the system you can set a parameter called saveProgramPath in order to provide the server-side script that is able to persist the data. The widget will POST a request to the provided script. 

In Alfresco you can create another Web Script to process the POST data, but this requires additional server-side coding. CMIS is able to directly write content back to the server using the same URL as used to read the content, but this requires a PUT method. The dojox.gantt widget by default uses the POST method. I will first show how to use the standard POST method and then we will extend dojox.gantt to use the PUT method.

Server-side Solution

First create another description document called gantt.post.desc.xml in the same directory as where you put the Web Script to read the Gantt chart and add the following lines:

<webscript>
  <shortname>dojox.gantt</shortname>
  <description>dojox.gantt save example</description>
  <url>/samples/gantt/{filename}</url>
  <authentication>user</authentication>
</webscript>

Next create a JavaScript controller that reads the data submitted by the dojox.gantt widget and saves it back to Alfresco. Create a file gantt.post.js with the following contents:

var filename = url.extension;

if (filename == undefined || filename.length == 0)
{
   status.code = 400;
   status.message = "Filename not provided.";
   status.redirect = true;
}
else
{
  var data = args["data"];
  
  var document = companyhome.childByNamePath(filename);
  
  if (document == null)
  {
    document = companyhome.createFile(filename) ;
  }
  
  document.content = data;
  document.save();

  model.content = data;
}

The last part of the Web Script is the view. This file simply returns the JSON data received from gthe dojox.gantt widget. Create a file gantt.post.json.ftl with the following line:

${content}

The final part is updating the gantt.get.html.ftl. Add the following parameter to the constructor of dojox.gantt.GanttChart just before the dataFilePath parameter:

saveProgramPath: "${url.context}/s/samples/gantt/gantt_default.json",

The result should look like this:

var ganttChart = new dojox.gantt.GanttChart({
  readOnly: false,
  saveProgramPath: "${url.context}/s/samples/gantt/gantt_default.json",
  dataFilePath: "${url.context}/s/cmis/p/gantt_default.json/content",
  withResource: false 
}, "gantt");

Now refresh the Web Scripts and reload the page. Add some tasks to the Gantt chart and click save to save the contents back to Alfresco. You can now save project data back to Alfresco using the default dojox.gantt save method. 

Client-side Solution

To avoid server-side coding we can rewrite the dojox.gantt save function to use a PUT in stead of a POST. I prefer this approach as it does not require any custom coding on the server. When using CMIS you can use the same URL as defined in the dataFilePath parameter to save data back to the server.

The Dojo Toolkit provides the ability to extend an object. To support the PUT method, we can rewrite the saveJSONData function in order to use PUT in stead of POST. Add the following lines of code to the body of the dojo.addOnLoad function in the file gantt.get.html.ftl:

  dojo.extend(dojox.gantt.GanttChart, {
  saveJSONData: function(fileName){
    var _this = this;
    _this.dataFilePath = (fileName && dojo.trim(fileName).length > 0) ? fileName : this.dataFilePath;
    try {
      var td = dojo.xhrPut({
        url: _this.saveProgramPath,
        putData: dojo.toJson(_this.getJSONData()),
        handle: function(res, ioArgs) {
        if ((dojo._isDocumentOk(ioArgs.xhr))||
          (ioArgs.xhr.status == 405)){
          alert("Successfully! Saved data to " + _this.dataFilePath);
        }else{
          alert("Failed! Saved error");
        }
      }
    });
  } catch (e){
    alert("exception: " + e.message);
  }
  }
});

The function can be found in the file GanttChart.js in the Dojo Toolkit SVN that you can access on the Dojo Toolkit Download page. The only changes required are the replacement of xhrPost with xhrPut and the replacement of the content parameter with a parameter putData with the JSON data as value. The reference documentation for xhrPut is here.

In addition to this change the saveProgramPath needs to be added and since the value is the same as the value of the dataFilePath I added a separate variable saveAndLoadPath for the value:

var saveAndLoadPath = "${url.context}/s/cmis/p/gantt_default.json/content"
  
var ganttChart = new dojox.gantt.GanttChart({
  readOnly: false,
  saveProgramPath: saveAndLoadPath,
  dataFilePath: saveAndLoadPath, 
  withResource: false
}, "gantt");

There is no need to refresh the Web Script as the only changes were made in the template. When you run this Web Script again you should be able to save any changes back to the system.

Conclusion

As you can see there is not that much work involved to load and save data from dojox.gantt to Alfresco. Thanks to CMIS a single call can both read and write data. The only challenge was to rewrite the save function to use PUT rather than POST. You can use dojox.gantt to create project plans using Alfresco, for example by creating a custom action or through a Share dashlet. The Alfresco developer who e-mailed me about the integration will use dojox.gantt to provide reports on top of Alfresco Share Data Lists. You can for example do this by creating a custom rendition that renders a Share Task List into the JSON structure that can be loaded into dojox.gantt. 

Updates

February 19, 2012: added the server-side save method as an example.

Today Jeff Potts, Alfresco’s Chief Community Officer, writes on Social Content that the Alfresco AVM (Alternative Versioning Model) will no longer be supported from Alfresco 5. The AVM was an alternative repository implementation in Alfresco to support Web Content Management use cases. It was designed as some sort of version control system with support for repository virtualization. It was originally designed by Kevin Cochrane who left Alfresco in 2008 to work for Day Software

I am must say that I am very happy with Alfresco’s decision to get rid of the AVM store. The whole idea behind the virtualization was interesting, but having to work with two repositories always caused a lot of problems. The solution was also too complex for most end users. At Incentro we support a couple of publishers who use Alfresco and publishing to the internet is only one of their channels. For these customers we always had to write custom actions to copy content from one repository to the other using the CrossRepositoryCopyService. End users, including non-technical authors, had to execute a copy action and then they where forced to navigate to the Web Project in order to deploy the content to a web server.

Starting from Alfresco 4.0 you can deploy directly from the DM (Document Management) repository to a web server. I haven’t tried it yet, but you might even be able to add a publishing channel to do the job.