Flex/AIR, CMIS, & Alfresco

Thursday, January 29, 2009

Intro

Last week I started building a CMIS browser with Adobe AIR.

I have built POCs with Flex before, but that was about it. Then, I downloaded thwirl and I remembered why I like AIR so much. It was easy to install, the UI is nice, and I imagine it was not too difficult to write. This is also a great example of why I like RESTful services too. I believe in the physical separation of the presentation tier, and working with RESTful services is a breeze. So is writing them for that matter. Twitter is a great example of building a social services platform and allowing for the development of third party applications to utilize it. It is a win, win situation. Perhaps ‘platform’ is the key word there. I’d like to shift from building web applications to building web platforms.

So, I decided to build a CMIS browser with AIR.

Flex/AIR

I didn’t really have too many issues with the Flex/AIR side, but here are a few things that tripped me up.

  • Authentication w/HttpService - This was not so much an issue as I simply didn’t know how to do it. Then I found this post.
  • Posting XML w/HttpService - I tried this, but it just didn’t seem to work. Then I found this post. Apparently the author ran into the same problem I did and ended up resorting to the Flex URLRequest.
  • Authentication w/URLRequest - I thought the approach would be identical to that of using the HttpService, but that is not quite the case. This post shows you how to do it with the URLRequest.
  • XML Namespaces - This ones gets me every time. You have to register any namespaces in your XML response or E4X will not work right.
  • E4X w/List & fieldLabel - I thought if I set the dataProvider for a list to an XMLListCollection that I could just specify the name of the child element as the fieldLabel. Apparently that doesn’t work. I had to use the labelFunction property. I then wrote a tiny method that accepts an XML object and returns an E4X expression (as a String).

CMIS

I’ve now spent some quality time with CMIS. For the most part, things have gone smoothly. Here are a few things of note.

Content Type

Don’t forget to set your content type when posting XML. When I was posting a query, I was not setting the content type to ‘application/cmisquery+xml’ and Alfresco was not happy about it. Once I did, it worked like a charm.

Schema - Repository Info

<cmis:repositoryInfo>
  <cmis:repositoryId>9920fa2a-7a3c</cmis:repositoryId>
  <cmis:repositoryName>Main Repository</cmis:repositoryName>
  <cmis:repositoryRelationship>self</cmis:repositoryRelationship>
  <cmis:capabilities>
    <cmis:capabilityMultifiling>true</cmis:capabilityMultifiling>
    <cmis:capabilityUnfiling>false</cmis:capabilityUnfiling>
  </cmis:capabilities>
</cmis:repositoryInfo>

I think this is a little too rigid. I don’t like that every property/capability is a unique element. I’m also not too happy to see the capabilities in the form of a complex property. All of this can make the client code a little more complex and a little more difficult to maintain than it needs to be.

I’d prefer something along these lines…

<cmis:repositoryInfo>
  <cmis:properties>
    <cmis:property type="id">9920fa2a-7a3c</cmis:property>
    <cmis:property type="name">Main Repository</cmis:property>
    <cmis:property type="relationship">self</cmis:property>
  </cmis:properties>
  <cmis:capabilities>
    <cmis:capability type="multifiling">true</cmis:capability>
    <cmis:capability type="unfiling">false</cmis:capability>
  </cmis:capabilities>
</cmis:repositoryInfo>

I think a schema like this would be much more flexible. Perhaps it is because I’m using E4X.

Schema - Object

<cmis:object>
  <cmis:properties>
    <cmis:propertyId cmis:name="ObjectId">
      <cmis:value>workspace://SpacesStore/a0e6612b-9771</cmis:value>
    </cmis:propertyId>
    <cmis:propertyString cmis:name="BaseType">
      <cmis:value>document</cmis:value>
    </cmis:propertyString>
    <cmis:propertyDateTime cmis:name="CreationDate">
      <cmis:value>2009-01-20T14:23:27.867-06:00</cmis:value>
    </cmis:propertyDateTime>
    <cmis:propertyBoolean cmis:name="IsImmutable">
      <cmis:value>false</cmis:value>
    </cmis:propertyBoolean>
    <cmis:propertyInteger cmis:name="ContentStreamLength">
      <cmis:value>0</cmis:value>
    </cmis:propertyInteger>
  </cmis:properties>
</cmis:object>

And again, I’d rather seem something along these lines.

<cmis:object>
  <cmis:properties>
    <cmis:property type="id" cmis:name="ObjectId">
      <cmis:value>workspace://SpacesStore/a0e6612b-9771</cmis:value>
    </cmis:propertyId>
    <cmis:property type="string" cmis:name="BaseType">
      <cmis:value>document</cmis:value>
    </cmis:propertyString>
    <cmis:property type="dateTime" cmis:name="CreationDate">
      <cmis:value>2009-01-20T14:23:27.867-06:00</cmis:value>
    </cmis:propertyDateTime>
    <cmis:property type="boolean" cmis:name="IsImmutable">
      <cmis:value>false</cmis:value>
    </cmis:propertyBoolean>
    <cmis:property type="integer" cmis:name="ContentStreamLength">
      <cmis:value>0</cmis:value>
    </cmis:propertyInteger>
  </cmis:properties>
</cmis:object>

Service - getChildren

Next up is the fact that the getChildren service returns every single property for all of the objects returned by default. I guess this is both good and bad. It can be good if you expect to display the properties of a majority of the objects, or if you want to reduce the number of requests. However, it makes the response quite large. I think I’d rather not have any of the properties returned by default. There does appear to be the option of using a filter. I need to explore this some more. Perhaps I’d have liked the opposite. Rather than having to specify a filter, I’d prefer to specify the properties returned.

Service - query

I’m a little bit uncertain about having to post XML and use a specific content type in order to search a repository via CMIS. I suppose I’d rather see it done with URL path and query parameters. I’m also wondering if a full blow query language is really in order here. It seems a bit overkill.

Alfresco

Hats off to Alfresco for helping bring about CMIS and delivering the first implementation. I’ve actually worked in an enterprise where SharePoint was used for project collaboration, Alfresco for document management, and Day Communique for web content management. I bet I could have made use of CMIS there if it was around at the time. I found the CMIS specification easy to understand and the Alfresco implementation easy to use. I don’t really have any issues with the decision to use ATOM.

That being said…

  • JCR - I still hope that one day Alfresco will drop their DM and AVM repositories in favor of a single JCR repository whether it be Jackrabbit or their own. The JCR specification is much more flexible. While Alfresco/CMIS treats everything as a folder or a file, a JCR repository treats everything as a node.
  • JAX-RS - It would be nice if Alfresco would replace web scripts with JAX-RS services whether it be an open source implementation or their own. I’d much rather add some annotations to a POJO than write an XML configuration file, a JS controller, and an FTL template if I just want to return XML/JSON.

Cool Links

comments powered by Disqus
Top

Shane Johnson

Recent Posts

Blog Archive