Skip navigation
All Places > Alfresco Content Services (ECM) > Blog > 2010 > May
2010
A relatively unknown capability of CMIS 1.0 is Renditions. In the content management world, the term 'renditions' typically means a facility to generate and retrieve alternative representations of content or a document. CMIS formalizes only the retrieval of such alternative representations. Although this may seem limiting, it does standardize common use cases such as the preview of reduced fidelity representations (e.g a thumbnail), the discovery and retrieval of processed images and videos from a Digital Asset Management system, and the publishing of web compliant content from a Web Content Management system.



Alfresco has provided Renditions support since its inception, although it wasn't until the recently released v3.3 that we actually called them Renditions. More on that later. In fact, anyone who has used Alfresco Share has used the Rendition capabilities of Alfresco. It powers the Thumbnail and Web Preview features of the Document Library.



[caption id='attachment_175' align='alignnone' width='300' caption='Share Document Library Thumbnails'][/caption]



[caption id='attachment_177' align='alignnone' width='300' caption='Share Document Library Web Preview'][/caption]



Alfresco v3.3 also implements the CMIS 1.0 specification including support for CMIS Renditions. This means that all Renditions generated by Alfresco are accessible through the CMIS bindings in a standardized way.



Lets take a look at how to retrieve an Alfresco Share Document Library thumbnail through the CMIS AtomPub binding.

curl -uadmin:admin

  'http://localhost:8080/alfresco/s/cmis/ren/documentLibrary/Spring%20Surf%20and%20OpenCMIS%20Integration?renditionFilter=cmis:thumbnail'


The response to the above HTTP GET request, which is the equivalent of issuing CMIS getObject(), includes additional information describing the 'cmis:thumbnail' rendition, the only rendition kind standardized by CMIS. A Repository may provide any number of other rendition kinds.

<entry>

  ...

  <link rel='alternate' type='image/png' cmisra:renditionKind='cmis:thumbnail' length='4190' title='doclib'

        href='http://localhost:8080/alfresco/s/cmis/s/workspace:SpacesStore/i/ef7e9a9b-c847-4023-b527-17243c72ade6/content' />

  ...

  <cmisra:object>

    ...

    <cmis:rendition>

      <cmis:streamId>workspace://SpacesStore/ef7e9a9b-c847-4023-b527-17243c72ade6</cmis:streamId>

      <cmis:mimetype>image/png</cmis:mimetype>

      <cmis:length>4190</cmis:length>

      <cmis:kind>cmis:thumbnail</cmis:kind>

      <cmis:title>doclib</cmis:title>

      <cmis:height>100</cmis:height>

      <cmis:width>100</cmis:width>

    </cmis:rendition>

  </cmisra:object>

</entry>


Each rendition is described as a link and additional meta data such as its mime type, size and dimensions. You may have noticed the 'renditionFilter' argument on the GET request. This controls which renditions, if any, are to be included in the response and is expressed as a rendition kind or mime type, or list of either.



It's good to know the nuts and bolts of the CMIS bindings, but it's not really ideal to work with them directly. They are protocols after all. Developers need APIs. Lets take a look at how to retrieve the same rendition via the Apache Chemistry OpenCMIS Java client API.

OperationContext context = session.createOperationContext();

context.setRenditionFilterString('cmis:thumbnail');

CmisObject doc = session.getObjectByPath('/Sites/ren/documentLibrary/Spring Surf and OpenCMIS Integration', context);

List<Rendition> renditions = doc.getRenditions();

for (Rendition rendition : renditions)

{

   System.out.println('kind: ' + rendition.getKind());

   System.out.println('mimetype: ' + rendition.getMimeType());

   System.out.println('width: ' + rendition.getWidth());

   System.out.println('height: ' + rendition.getHeight());

   System.out.println('stream id: ' + rendition.getStreamId());

}


This outputs:

kind: cmis:thumbnail

mimetype: image/png

width: 100

height: 100

stream id: workspace://SpacesStore/ef7e9a9b-c847-4023-b527-17243c72ade6


The stream id is important as it allows retrieval of the rendition content via the CMIS getContentStream() service. Remember, the above code is applicable to all CMIS repositories, not just Alfresco.



Now, lets incorporate the above code into Spring Surf...

...

<#list renditions as rendition>

<tr>

  <td><a href='<@cmisLib.cmisContextUrl conn.name/>/rendition/${object.id}/s/${rendition.streamId}'>${rendition.kind}</a></td>

  <td>${rendition.mimeType}</td>

  <td><#if rendition.length != -1>${rendition.length?c}</#if></td>

</tr>

</#list>

...


...to display the list of renditions available for a document in a Web Application (Note: the full source of this application is available in the Spring Surf and OpenCMIS prototype integration).



[caption id='attachment_182' align='alignnone' width='300' caption='Spring Surf and OpenCMIS view of Renditions'][/caption]



Now we've seen how to retrieve renditions in a standardized way, lets dig deeper into Alfresco's rendition capabilities. Alfresco v3.3 introduces a new Rendition service that combines the best of the existing Thumbnail and Transformation services with the existing WCM forms rendering capability, providing a consistent way to generate renditions from any content in the Alfresco repository. Of course, extensions may be plugged into the Rendition service to create any kind of rendition. Used in conjunction with Alfresco Rules, the rendition service provides the basis for many types of content management application including DAM and WCM.



Lets set up a rule to transform all images that are added to a folder in an Alfresco Share Document Library...



[caption id='attachment_184' align='alignnone' width='300' caption='Rule to execute Image Swirl script '][/caption]



[caption id='attachment_185' align='alignnone' width='300' caption='Image Swirl script']Image Swirl script[/caption]



Each rendition definition that's exposed or created through the Rendition service is mapped to a CMIS rendition kind. Therefore, retrieving a rendition generated through the Alfresco Rendition Service is exactly the same as retrieving a Share document library thumbnail or web preview. Here's the CMIS AtomPub HTTP GET request:

curl -uadmin:admin

  'http://localhost:8080/alfresco/s/cmis/ren/documentLibrary/photo?renditionFilter=swirl'


and its response:

<entry>

  ...

  <link rel='alternate' type='image/jpeg' cmisra:renditionKind='swirl' length='56572' title='swirl'

        href='http://localhost:8080/alfresco/s/cmis/s/workspace:SpacesStore/i/2d05d46b-ac44-4b97-8431-21f436a41c5b/content'/>

  ...

  <cmisra:object>

    ...

    <cmis:rendition>

      <cmis:streamId>workspace://SpacesStore/2d05d46b-ac44-4b97-8431-21f436a41c5b</cmis:streamId>

      <cmis:mimetype>image/jpeg</cmis:mimetype>

      <cmis:length>56572</cmis:length>

      <cmis:kind>swirl</cmis:kind>

      <cmis:title>swirl</cmis:title>

    </cmis:rendition>

  </cmisra:object>

</entry>


... and the Spring Surf / OpenCMIS Web Application shows...



[caption id='attachment_188' align='alignnone' width='300' caption='Swirl Rendition Definition']Swirl Rendition Definition[/caption]



[caption id='attachment_189' align='alignnone' width='210' caption='Swirl Image']Swirl Image[/caption]



Renditions were introduced into CMIS v1.0 quite late into its development where other features were postponed, but as you can see, the standardization of this capability allows for all kinds of use cases, in particular where a system requires integration with a DAM or WCM repository.



All the samples in this article are supported by Alfresco Community 3.3g which is to be released imminently and http://cmis.alfresco.com (our hosted CMIS repository for development purposes). The Spring Surf and OpenCMIS prototype integration is available at https://anonsvn.springframework.org/svn/se-surf/branches/DEV_CMIS_2/.



For more information on Alfresco's CMIS offering visit http://wiki.alfresco.com/wiki/CMIS.
pmonks2

Timed Deployment

Posted by pmonks2 May 7, 2010
While Alfresco WCM contains a sophisticated deployment engine, the options for initiating deployment are rather more limited, comprising the manual 'Deploy Snapshot' function in the Explorer UI, and the automatic 'Auto Deploy' function that can be configured in the Web Project Settings and then requested by an author at submission time.



While these options are useful, they each have their downsides.  Manual deployment is, well, highly manual, and in practice it's usually unacceptable to dedicate a Content Manager to monitoring promotions and deploying them as they roll in.  Auto-deployment removes the manual step (once authors are trained to check the 'auto-deploy' checkbox during submission to workflow), but has the problem that a high rate of concurrent promotion can overwhelm the deployment system (since each and every promotion is auto-deployed individually, despite the deployment engine offering a far more efficient 'batch' deployment mode).

A Better Alternative



A better approach is to have deployment initiated automatically on a scheduled basis, picking up the latest snapshot at that point in time (which will automatically include all prior snapshots since the last successful deployment).



So what would be involved in developing this as a customisation?



Not very much, as it turns out.  Alfresco already includes all of the necessary components to provide this functionality:



  1. It includes the Quartz job scheduling engine.


  2. It includes an Action for initiating deployment.



All that's needed is some glue code to tie these two components together, and thanks to the generosity of a recent Alfresco Enterprise customer, that glue code has now been developed and is available as part of the alfresco-wcm-deployment project on Google Code.

Under the Hood



As it turns out there was one critical detail that made this slightly less straight forward than I'd expected. Specifically, the action responsible for deploying a Web Site (the AVMDeployWebsite action) isn't responsible for writing deployment reports into the Web Project - that step is performed in the Explorer UI's JSF code instead (in a private class called org.alfresco.web.bean.wcm.DeployWebsiteDialog).



Given that deployment reports are a critical piece of operational reporting information, it was clear that generating the deployment reports in exactly the same fashion as the OOTB 'Deploy Snapshot' and 'Auto Deploy' functions was a high priority.  As a result the code doesn't call the AVMDeployWebsite action directly - instead I copied the relevant block of code out of DeployWebsiteDialog and added it to my own custom class.



Other than that, the code is pretty straight forward.  Following Alfresco's ubiquitous 'in-process SOA' pattern I introduced a new service interface (called WebProjectDeploymentService), wired it into my Quartz job class using Spring, then configured it (with the cron expression that controls how frequently it runs) in a separate 'trigger' bean.



As always, if you have any questions or comments, please feel free to reply here.  I would request that any bug reports or enhancement requests get raised in the issue tracker in the Google Code project however - they are far easier to monitor there than in the comments on this post.





Note that this creates upgrade risk, since that code could change in future versions of Alfresco.  Given I work with the Alfresco code day-to-day I'm in a better position to detect when such changes have occurred, but if you're doing something like this yourself I would encourage extra diligence in monitoring changes to the original code to ensure your extension doesn't break unexpectedly following an upgrade.
Earlier today, Mary McRae of OASIS, announced that Content Management Interoperability Services (CMIS) v1.0 has been approved as an OASIS Standard.



'Congratulations to the OASIS CMIS TC, and the community of implementers, developers and users who have brought the work successfully to culmination.'



As previously reported, Alfresco 3.3 implements the CMIS v1.0 standard.

Filter Blog

By date: By tag: