Alfresco Share 3.3 Extensions and SpringSurf

This quick tutorial shows how much easier it is to package up custom extensions to Alfresco Share in version 3.3.

The features for handling the new single package deployment and simpler more compact configuration are part of the SpringSurf web framework recently contributed to SpringSource by Alfresco engineering.

Background

In versions of Alfresco Share previous to 3.3, developing and particularly packaging extensions was a laborious task, the number of individual config files required and the need to place web-assets such as CSS and JavaScript files directly into a separate web-app – such as the TomCat ROOT web-app and then referencing them there was particularly fiddly.

Most of these issues have been solved with SpringSurf:

  • Loading of Surf configuration files directly from a JAR
  • Referencing web-assets packaged within a JAR or the class path via a simple Resource servlet URL
  • Combining multiple Surf config elements – pages, templates, component into a single file

It might not sound like much, but these changes make a big difference to reducing the complexity of developing and packaging Share extensions.

Downloads

The tiny JAR files related to this tutorial – it’s worth having them open to examine while reading the rest of the article:
share-sample-dashlet-extension-3.3.jar
share-sample-page-extension-3.3.jar

Share Dashlets

Dashlets are small portlet like units of functionality available in either the User or Site dashboards (or both). An example might be a summary of user tasks, site activities or documents recently added to a site. Custom dashlets are one of the easiest items to add to Alfresco Share

Each dashlet is generated by a single Share WebScript component. The needs to be marked as a member of the “site-dashlet” family. The ‘family’ of a WebScript is like a simple tagging or categorisation mechanism – applications can use the Surf APIs to retrieve the IDs of all WebScripts within a named family, which is exactly what Alfresco Share does to generate the list of dashlets available to the user on the Configure Dashboard page.

So, no further configuration of Share is required other than to make sure it is found by the web-app on initialisation.

To mark a dashlet as available in the User dashboard, use the “user-dashlet” family. The mark as dashlet as available for both dashboard types, use the “dashlet” family. Of course a site dashlet written expecting specific context information such as the current site id will not work in the user dashboard context so care should be taken when applying the correct family category.

Dashlet Example

This example shows how to package up a Tag Cloud dashlet that was previously built for use as a demonstration of how to incrementally develop a dashlet for Alfresco Share 3.2 at the recently held Alfresco Meetup user conferences. This article won’t go into the detail of the dashlet code itself – but it does make an excellent example of several key concepts and features that are important to understand if you want to build rich, Ajax enabled components for Alfresco Share. It demonstrates:

  • The artifacts that make up a WebScript component
  • How simple it is to make a remote call from web-tier JavaScript (part of the WebScript component) to an Alfresco server and process the JSON response
  • Passing values from the JSON response into the WebScript FreeMarker template for rendering the dashlet response
  • Including component specific CSS and client-side JavaScript into the main page (the .head.ftl part of the WebScript component)
  • The client-side JavaScript required for a rich Ajax enabled Share component
  • Performing an Ajax call via the Surf proxy back to the Alfresco server to perform live refresh of the Tag Cloud
  • Retrieving labels from the WebScript I18N message bundle
  • Linking to other Share pages (the Search results page when clicking on a tag)
  • Making the dashlet resizable

So there is quite a lot of functionality in a small dashlet – and a lot of Alfresco and Surf framework knowledge required to build it. Obviously it could be made much simpler – for instance the Ajax refresh is not essential and would reduce the complexity a lot (no client-side JavaScript would be required for a start). It is well worth examining further as a starting point for these concepts.

A blog page on the original Tag Cloud dashlet can be found here http://blogs.alfresco.com/wp/wabson/site-tags-dashlet and some other blog pages on Alfresco Share dashlets http://drquyong.com/myblog/?cat=15 and http://www.ixxus.com/blog/2009/04/dashlet-tips

Packaging the Dashlet

To reduce the complexity when packaging this dashlet for deployment in Alfresco Share 3.3, several small changes were made. Firstly since web-assets can now be packaged along with the component, the URLs to those assets were modified. Within the site-tags.get.head.ftl file the path to the CSS and JavaScript files now start with /res this is the path to the SpringSurf Resource servlet. This servlet looks for web-assets within the usual servlet context and web-app and also the classpath and JAR files – which means any web-assets can now be packaged up into the same JAR as the components.

SpringSurf features a number of “persisters” which iterate the configured classpath and JAR locations for all the various page, component and template files that are available. This means to make WebScript components, pages and other objects available to Share, they simply need to be located under one of those configured paths. The JAR file structure required is as follows:

   /alfresco
      /site-webscripts
         /dashlets
            site-tags.get.* <- the WebScript artifacts for the dashlet component
   /META-INF
      /components
         /dashlets
            site-tags.css
            site-tags.js
            /images
               refresh.png

Your WebScript components can live in any folder structure you require under alfresco/site-webscripts – that is one of the paths automatically searched by Share.

Note that it is possible to override the default SpringSurf persister configuration if you want to add your own classpath/JAR path search locations. This is exactly what Share itself does to to add the Alfresco specific paths in addition to the common SpringSurf locations.

The web assets required for your components now live under META-INF – this is effectively the root of all URLs that are processed by the Resource servlet. For example:

   <link rel="stylesheet" type="text/css" href="${page.url.context}/res/components/dashlets/site-tags.css" />

You should find that relative paths to images etc. in CSS classes work also, for example in the Tag Cloud dashlet CSS the file <CODE>images/refresh.png</CODE> is referenced thus:

   .site-tags .refresh
   {
      background-image: url(images/refresh.png);
   }

No references to any other web-app are required!

Deploying the Dashlet

In a default Alfresco installation the included TomCat bundle is already configured to pickup extensions of classes and JARs added to $TOMCAT_HOME$/shared/classes and $TOMCAT_HOME$/shared/lib respectively. So it is a simply matter of dropping the JAR into the lib folder and then restarting the app-server. Note that a plain install of TomCat 6 will need to be tweaked to find classes and jars in those locations – ensure this line is present in $TOMCAT_HOME/conf/catalina.properties

   shared.loader=${catalina.base}/shared/classes,${catalina.base}/shared/lib/*.jar

If you create a new Share site (or navigate to an existing one), click the Customize Dashboard button on the toolbar and then click the Add Dashlets button you should see the Tag Cloud dashlet listed! That’s it. If you want to play with the tag cloud itself you’ll need to add some documents to the site and tag them.

Share Page Extensions

Additional custom pages with associated templates and components can be added to Share, it is a little more complex than adding a dashlet, but less so with Share 3.3. This article does not go into great detail on the structure of Share pages or specific SpringSurf concepts here, however more information on concepts like pages, templates and component binding can be found on the Alfresco Developer Wiki http://wiki.alfresco.com/wiki/Surf and http://wiki.alfresco.com/wiki/Surf_Platform_-_Developers_Guide

Page Extension Example

This example is a simple Share page extension that again introduces a number of concepts that should be understood before developing Share pages. The example demonstrates adding a new Site page called Site Profile. The Site Profile page configuration identifies the template used to render it and the template itself supplies the mark up and the location of the “regions” that bind to the components within it. Templates are generally small, lightweight and responsible only for providing the markup for the component areas – generally just a few nested DIVs and SPANs – it’s the WebScript components bound to the regions that really do the work. The template is as follows:

   <#include "org/alfresco/include/alfresco-template.ftl" />
   <@templateHeader>
      <!-- add template HEAD items here - such as additional CSS or script includes -->
   </@>

   <@templateBody>
      <!-- standard Alfresco Share header component - you may wish to add navigation etc. -->
      <div id="alf-hd">
         <@region id="header" scope="global" protected=true />
         <@region id="title" scope="template" protected=true />
      </div>
      <!-- YUI layout for a body component area in Share -->
      <div id="bd">
         <!-- Site Details page component binding -->
         <@region id="sitedetails" scope="page" protected=true />
      </div>
   </@>

   <@templateFooter>
      <!-- standard Alfresco Share footer component - you may wish to add your own -->
      <div id="alf-ft">
         <@region id="footer" scope="global" protected=true />
      </div>
   </@>

Note the @region tags – these define the component bindings. The complete page is designed to look like most other Share pages – with the “global” scoped header and footer regions already defined in Share. The interesting parts are the “title” and “sitedetails” regions. Previously to Share 3.3 each of these template or page specific components would require another configuration file – but with SpringSurf these components can be defined as part of the page and template configuration files to reduce complexity further.

The “sitedetails” page component is defined within the page definition thus:

   <?xml version='1.0' encoding='UTF-8'?>
   <page>
      <id>siteprofile</id>
      <title>Example Site Profile Page</title>
      <template-instance>siteprofile</template-instance>
      <authentication>user</authentication>

      <!-- in SpringSurf page scoped component config can now be embedded directly
           into the page config - no more additional xml files required -->
      <components>
         <!-- a custom page component packaged with this example -->
         <component>
            <region-id>sitedetails</region-id>
            <url>/components/sitedetails</url>
         </component>
      </components>
   </page>

It binds the “sitedetails” region id to the WebScript with a URL of /components/sitedetails – we register our WebScript with the same URL. Here is the WebScript descriptor for our sitedetails component in sitedetails.get.desc.xml

<webscript>
   <shortname>Example Site Details</shortname>
   <description>Example Site Details Share extension component</description>
   <url>/components/sitedetails</url>
</webscript>

The WebScript component itself does not do much work, it is quite simple and does not require any client-side JavaScript. It does include a CSS file via the .head.ftl file using the Resource servlet mentioned above. Within the component web-tier JavaScript a remote call is executed to retrieve details of the current site – with the Site Id retrieved from the Share URL template. The JSON response is processed and the data is placed in the model. The model is passed to the component template for markup by the framework. Within the component template the site details are marked up with snippets of XHTML. Within the template there is also another example of using a Resource servlet URL to access an image that is packaged up within the JAR.

Packaging the Page Extension

As noted above, to make your configuration objects available to Share, they simply need to be located under one of its configured search paths. The JAR file structure required is as follows:

   /alfresco
      /site-data
         /pages
            siteprofile.xml
         /template-instances
            siteprofile.xml
      /site-webscripts
         /sitedetails
            sitedetails.get.* <- the WebScript artifacts for the Site Details page component
   /META-INF
      /components
         /sitedetails
            sitedetails.css
            /images
               SurfLogo200.jpg

In addition to the alfresco/site-webscripts folder mentioned in the previous example, we have added an alfresco/site-data folder – this is on the search path to lookup pages, template and component definition files. Again you can use any structure you like under this folder, the page and template definition files here have been placed into separate folders but that is not essential.

Deploying the Page Extension

Place the JAR file into the $TOMCAT_HOME/shared/lib location as mentioned above as start the server. Then either create or navigate to an existing Share site. To access the new page, modify the url in the browser as follows:

 <your-server>/share/page/site/<your-site-id>/siteprofile

Obviously ensuring the your-server and your-site-id elements are correct. You should see a new page appear containing details on the current site with the Surf logo at the bottom!

Conclusion

This quick example of repackaging and light refactoring of a dashlet and a simple page extension into single “drop-in” JAR files show some of the improvements in Share 3.3 now possible thanks to SpringSurf. The combination of the two examples also introduce most of the concepts and frameworks required to developer rich Alfresco Share pages and Ajax enabled components.

Follow me on Twitter!

6 thoughts on “Alfresco Share 3.3 Extensions and SpringSurf

  1. Gabriele Columbro

    I love this dude…

    working with AMPs has been a pain for me in my multi year Maven experience, so that I had to introduce the maven-amp-plugin (http://maven.alfresco.com/nexus/content/repositories/alfresco-docs/maven-alfresco-lifecycle/plugins/maven-amp-plugin/index.html) to be able to manage Alfresco repository extensions in a standard maven lifecycle.

    Now that we have this simplification it’s gonna work just like a charm in standard J2EE environments…what do you think if I make an new Share Module Maven archetype based on this sample code so that we can complete the set of archetypes available for the Maven Alfresco community (http://wiki.alfresco.com/wiki/Managing_Alfresco_Lifecyle_with_Maven) ?

    And I can only think later on about dynamic classloading and drag’n’drop (or web based) plug-in installation for share…

    THIS IS SOOO COOL!

    Great stuff..

    Reply
  2. Pingback: uberVU - social comments

  3. Pingback: Will Abson on Alfresco » Blog Archive » Share extensions build script

  4. Pingback: [HOWTO] Build your JAR Alfresco Share Dashlet with Maven in 3 minutes

  5. Pingback: Kev’s blog » Blog Archive » Developer tips for Alfresco Share 3.3

  6. Emma

    I dropped the jar in tomcat/shared/lib then restarted alfresco. Alfresco displays details of the dashlet on its share/page/index/all page (when browsing all web scripts from the /share/service/index page) but does not display it on the list of dashlets when I click “Customize Dashboard” > “Add Dashlet” from the share dashboard.

    Reply

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>