Adding Custom Aspect Support in Alfresco Share

Since Alfresco 3.2 introduced the ability to configure the metadata forms used in the Document Library, there have been several good articles published on how to add support for custom document types.
One of the first questions people often ask when they see Share is how they can easily extend the metadata fields that are stored against a document. Whilst this can be done using custom document types, aspects often provide a more agile solution.
So this article should explain how Share can be easily extended to support custom aspects using good practice techniques, specifically

  • Ensuring all extended configuration is placed outside of the share webapp, so protecting it from upgrades and redeployments, and
  • Using i18n labels for all text strings that appear in the UI, thus allowing translation of the labels.

The example provides a number of files, all of which should be placed below the tomcat/shared/classes directory of your Alfresco installation. If you are not using the Alfresco-bundled version of Tomcat then you may need to create this directory yourself and configure Tomcat’s shared classloader to use it.
First you will need to configure the repository with your custom model definition. In my case I am using a simple knowledge base model that defines a single aspect kb:referencable. The aspect adds a new text property that allows a unique KB reference number to be added to documents.
First, the Spring configuration defined in alfresco/extension/kb-model-context.xml

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
    <!-- Registration of new models -->
    <bean id="extension.kb.dictionaryBootstrap" parent="dictionaryModelBootstrap" depends-on="dictionaryBootstrap">
        <property name="models">
            <list>
                <value>alfresco/extension/kb-model.xml</value>
            </list>
        </property>
    </bean>
     <bean id="extension.kb.resourceBundle" class="org.alfresco.i18n.ResourceBundleBootstrapComponent">
       <property name="resourceBundles">
          <list>
             <value>alfresco.messages.knowledgebase</value>
          </list>
       </property>
    </bean>
</beans>

Then, define the model itself in alfresco/extension/kb-model.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- Definition of Knowledge Base Model -->
<model name="kb:knowledgebase" xmlns="http://www.alfresco.org/model/dictionary/1.0">
   <!-- Optional meta-data about the model -->
   <description>Knowledge Base Model</description>
   <author>Will Abson</author>
   <version>1.0</version>
   <!-- Imports are required to allow references to definitions in other models -->
   <imports>
      <!-- Import Alfresco Dictionary Definitions -->
      <import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
      <!-- Import Alfresco Content Domain Model Definitions -->
      <import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
   </imports>
   <!-- Introduction of new namespaces defined by this model -->
   <namespaces>
      <namespace uri="http://www.alfresco.com/model/knowledgebase/1.0" prefix="kb"/>
   </namespaces>
    <aspects>
      <!-- Definition of new Content Aspect: Knowledge Base Document -->
      <aspect name="kb:referencable">
         <title>Knowledge Base Referencable</title>
         <properties>
            <property name="kb:documentRef">
               <type>d:text</type>
            </property>
         </properties>
      </aspect>
   </aspects>
</model>

The last file in our model definition adds some i18n labels for the aspect and property names. Add the following content to the file alfresco/messages/knowledgebase.properties.

# Custom knowledge base messages
kb_knowledgebase.property.kb_documentRef.title=KB Reference
kb_knowledgebase.aspect.kb_referencable.title=Knowledge Base Referencable
aspect.kb_referencable=Knowledge Base Referencable

With the model added the repository should start up without errors and will know about the new aspect. In order to use it, we need to configure Share to show this aspect in the Manage Aspects dialogue and to display the KB Reference field in forms, when a node has the aspect applied.
The file alfresco/web-extension/share-config-custom.xml can be used to do both these things.

<alfresco-config>
   <!-- Document Library config section -->
   <config evaluator="string-compare" condition="DocumentLibrary">
      <!--
         Used by the "Manage Aspects" action
         For custom aspects, remember to also add the relevant i18n string(s)
            cm_myaspect=My Aspect
      -->
      <aspects>
         <!-- Aspects that a user can see -->
         <visible>
            <aspect name="cm:generalclassifiable" />
            <aspect name="cm:complianceable" />
            <aspect name="cm:dublincore" />
            <aspect name="cm:effectivity" />
            <aspect name="cm:summarizable" />
            <aspect name="cm:versionable" />
            <aspect name="cm:templatable" />
            <aspect name="cm:emailed" />
            <aspect name="emailserver:aliasable" />
            <aspect name="cm:taggable" />
            <aspect name="app:inlineeditable" />
            <aspect name="kb:referencable" />
         </visible>
         <!-- Aspects that a user can add. Same as "visible" if left empty -->
         <addable>
         </addable>
         <!-- Aspects that a user can remove. Same as "visible" if left empty -->
         <removeable>
         </removeable>
      </aspects>
   </config>
   <!-- cm:content type (existing nodes) -->
   <config  evaluator="node-type" condition="cm:content">
      <forms>
         <!-- Default form configuration used on the document details and edit metadata pages -->
         <form>
            <field-visibility>
               <show id="kb:documentRef" />
            </field-visibility>
         </form>
         <!-- Document Library pop-up Edit Metadata form -->
         <form id="doclib-simple-metadata">
            <field-visibility>
               <show id="kb:documentRef" />
            </field-visibility>
            <edit-form template="../documentlibrary/forms/doclib-simple-metadata.ftl" />
         </form>
         <!-- Document Library Inline Edit form -->
         <form id="doclib-inline-edit">
            <field-visibility>
               <show id="kb:documentRef" />
            </field-visibility>
         </form>
      </forms>
   </config>
</alfresco-config>

This configuration will add the KB reference field at the bottom of the main Edit Metadata form, the pop-up edit form used in the document list view and lastly the in-line edit form used for HTML, text and XML content (introduced in Alfresco 3.3).
Note: More advanced control is possible over the placement of the field within the form, but this requires copying over the full form definitions for the cm:content type from the file alfresco/web-framework-config-commons.xml (or alfresco/share-form-config.xml in 3.3 onwards) inside the Share webapp and adding the attribute replace="true" on the <config> element.
Now that you’ve configured Share, you must restart Tomcat so that the changes are picked up. The application should start up and you should be able to add the aspect to some content and see the document reference field appear in forms.
The last thing to do is to add an i18n label for the Knowledge Base aspect in the Manage Aspects dialogue. To do this we need to define a small bit of Spring configuration in the file alfresco/web-extension/custom-slingshot-application-context.xml, which will wire the knowledgebase.properties file we created earlier into Share.

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
   <!-- Add Knowledge Base messages -->
   <bean id="webscripts.kb.resources" class="org.springframework.extensions.surf.util.ResourceBundleBootstrapComponent">
      <property name="resourceBundles">
         <list>
            <value>alfresco.messages.knowledgebase</value>
         </list>
      </property>
   </bean>
</beans>

In versions prior to Alfresco 3.3 (when some changes were made to the Share resource bundle classes) the following configuration must be used instead (note the different class name)

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
   <!-- Add Knowledge Base messages -->
   <bean id="webscripts.kb.resources" class="org.alfresco.i18n.ResourceBundleBootstrapComponent">
      <property name="resourceBundles">
         <list>
            <value>alfresco.messages.knowledgebase</value>
         </list>
      </property>
   </bean>
</beans>

This configuration tells Share to look in the file knowledgebase.properties for aspect labels, in addition to the core message bundles.
With that file added you should be able to restart Tomcat again and see the correct label in the Manage Aspects dialogue. You’ve now fully-customised Alfresco Share to support additional custom aspects.
Update: Thanks to Brian Ochs, who pointed out that the additional message aspect.kb_referencable is also required in knowledgebase.properties.
Update: The configuration files in this tutorial can now be downloaded in ZIP format. To use them directly extract the archive into tomcat/shared/classes and restart the server. Please do not use these files, which are now outdated.

Share Extensions Build Script

Update, 4th May 2011: The latest version of the build script and sample Eclipse project is now hosted on Share Extras. For more information please see the Sample Project page.
With Kev’s recent SpringSurf changes in the 3.3 code line, Share extensions are now much easier to deploy as shared libraries. However, it’s still up to individual developers to set up their own project structure and to package this up as a JAR.
So, to build the latest Site Tags dashlet using this method I put together an Ant build script, which hopefully will be useful to others.
As well as building a JAR it also supports the unofficial ZIP structure that we’d used previously to package up sample dashlets, in addition to the AMP format that we use for the more complex DoD extensions for Share.
The build script assumes a standard Alfresco project layout as follows

 /config - all web-tier configuration files, with a top-level 'alfresco' package
 /web - all static resources, e.g. CSS and JS files

You can use the build script with your existing projects if they fit this structure, or you can use my own zipped-up site tags dashlet project as a template for your own. This should import into a fresh Eclipse project but you could extract it elsewhere.
Once your project is set up and you’re ready to package up your extension, you can run the following command to build the JAR.

 ant -Djar.name=my-sample-project.jar package-jar

To package up a ZIP or AMP, substitute ‘jar’ in the parameters to ‘zip’ or ‘acp’. Easy, eh?

Site tags dashlet improvements

If you attended one of the recent Meetups in Europe of the US you may have caught us using the site tags dashlet as an example of how to develop a custom dashlet for Alfresco Share.
Mike Hatfield did a great job of taking my original code and re-working it to shift most of the logic to client-side JS where it should be, as well as adding some funky scoping stuff using a couple of YUI controls.
The resulting code that we demonstrated ourselves in Madrid, and which others showed in other locations has been posted under the Meetups Worldwide space on share.alfresco.com (free login required) as a ZIP file. Also in the bundle is an example of how to extend the Document Library actions in Share with your own custom action.
For the latest version of the dashlet, however, you’ll need to head over to the site tags dashlet page. Version 0.1.1 contains a couple of extra lines to sort the tags into alphabetical order before they’re displayed – more consistent with other tag clouds I’m told – and the code has also been back-ported to Alfresco 3.1 because a few people asked for this.
The subject of porting dashlets between v3.1 and v3.2 is another topic in itself, as the pattern used to define JS modules in the latest version has improved substantially. I’ll try post more on this soon.

Tag cloud dashlet for Alfresco Share

This small extension to Share provides a new site dashlet to display the most popular tags within the site as a tag cloud.

The dashlet uses the existing tagging REST API, so no additional repository tier scripts are required. The zipped files can be extracted into your tomcat/shared/classes directory to add the Share support. You should find that the directory structure will be automatically created, although you will need to move the site-tags.css file to the components/dashlets directory in the webapp.
It should be trivial to write a second dashlet to surface a global tag cloud, suitable for display in a user dashboard, using the list all tags method, rather than the tagscope-based approach used by this script.
UPDATE: The latest version of the code can now be found on the site tags dashlet page.