Month: December 2009

Alfresco Developer Guide source code update for 3.2 Enterprise

I’ve updated the source code that accompanies the Alfresco Developer Guide to be compatible with the recent 3.2 Enterprise release of Alfresco. You can get the link from my original post on the source code re-org, or download it directly.

Most of it hasn’t changed terribly much. The BootstrapAuthorityCreator class, which you don’t need unless you are playing with the AMP example in Appendix C, isn’t working yet due to changes in the AuthorityService with 3.2 Enterprise.

The biggest change is in the LDAP configuration (Chapter 9). Overall, setting up LDAP authentication and chaining has gotten much easier in 3.2 Enterprise. But the configuration is much different than in previous releases (See the Alfresco wiki pages on Subsystems and the Authentication Subsystem for more info).

I don’t have CAS SSO working with 3.2 Enterprise quite yet, so the authentication filter included in the Chapter 9 source code is commented out for now.

cmislib: A CMIS client library for Python

I’ve started a new project on Google Code called cmislib. It is an interoperable client library for CMIS in Python that uses the Restful AtomPub Binding of a CMIS provider to perform CRUD and query functions on the repository.

I created it for a couple of reasons. First, it’s been bugging me that, unlike our Drupal Alfresco integration, our Django Alfresco integration does not use CMIS. After talking it over with one of our clients we decided it would make more sense to create a more general purpose CMIS API for Python that Django (and any other Python app) could leverage, rather than build CMIS support directly into the Django Alfresco integration.

Second, around the time I was putting together the Getting Started with CMIS tutorial, it struck me that there needed to be an API that didn’t have a lot of dependencies and was very easy to use. Otherwise, it’s too easy to get lost in the weeds and miss the whole point of CMIS: Easily working with rich content repositories, regardless of the underlying implementation.

Even if you’ve never worked with Python before, it is super easy to get started with cmislib. The install is less than 3 steps and the API should feel very natural to anyone that’s worked with a content repository before. Check it out.

Install

  1. If you don’t have Python installed already, do so. I’ve only tested on Python 2.6 so unless you’re looking to help test, stick with that.
  2. If you don’t have setuptools installed already, do so. It’s a nice tool to use for installing Python packages.
  3. Once setuptools is installed, type easy_install cmislib

That’s all there is to it. Now you’re ready to connect to your favorite CMIS-compliant repository.

Examples

There’s nothing in cmislib that is specific to any particular vendor. Once you give it your CMIS provider’s service URL and some credentials, it figures out where to go from there. But I haven’t tested with anything other than Alfresco yet, and this thing is still hot out of the oven. If you want to help test it against other CMIS 1.0cd04 repositories I’d love the help.

Anyway, let’s look at some examples using Alfresco’s public CMIS repository.

  1. From the command-line, start the Python shell by typing python then hit enter.
  2. Python 2.6.3 (r263:75183, Oct 22 2009, 20:01:16)
    GCC 4.2.1 (Apple Inc. build 5646)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>>
  3. Import the CmisClient and Repository classes:
  4. >>> from cmislib.model import CmisClient, Repository
  5. Point the CmisClient at the repository’s service URL
  6. >>> client = CmisClient('http://cmis.alfresco.com/s/cmis', 'admin', 'admin')
  7. Get the default repository for the service
  8. >>> repo = client.getDefaultRepository()
    >>> repo.getRepositoryId()
    u'83beb297-a6fa-4ac5-844b-98c871c0eea9'
  9. Get the repository’s properties. This for-loop spits out everything cmislib knows about the repo.
  10. >>> repo.getRepositoryName()
        u'Main Repository'
    >>> info = repo.getRepositoryInfo()
    >>> for k,v in info.items():
        ...     print "%s:%s" % (k,v)
        ...
        cmisSpecificationTitle:Version 1.0 Committee Draft 04
        cmisVersionSupported:1.0
        repositoryDescription:None
        productVersion:3.2.0 (r2 2440)
        rootFolderId:workspace://SpacesStore/aa1ecedf-9551-49c5-831a-0502bb43f348
        repositoryId:83beb297-a6fa-4ac5-844b-98c871c0eea9
        repositoryName:Main Repository
        vendorName:Alfresco
        productName:Alfresco Repository (Community)

Once you’ve got the Repository object you can start working with folders.

  1. Create a new folder in the root. You should name yours something unique.
  2. >>> root = repo.getRootFolder()
    >>> someFolder = root.createFolder('someFolder')
    >>> someFolder.getObjectId()
    u'workspace://SpacesStore/91f344ef-84e7-43d8-b379-959c0be7e8fc'
  3. Then, you can create some content:
  4. >>> someFile = open('test.txt', 'r')
    >>> someDoc = someFolder.createDocument('Test Document', contentFile=someFile)
  5. And, if you want, you can dump the properties of the newly-created document (this is a partial list):
  6. >>> props = someDoc.getProperties()
    >>> for k,v in props.items():
    ...     print '%s:%s' % (k,v)
    ...
    cmis:contentStreamMimeType:text/plain
    cmis:creationDate:2009-12-18T10:59:26.667-06:00
    cmis:baseTypeId:cmis:document
    cmis:isLatestMajorVersion:false
    cmis:isImmutable:false
    cmis:isMajorVersion:false
    cmis:objectId:workspace://SpacesStore/2cf36ad5-92b0-4731-94a4-9f3fef25b479
  7. You can also use cmislib to run CMIS queries. Let’s find the doc we just created with a full-text search. (Note that I’m currently seeing a problem with Alfresco in which the CMIS service returns one less result than what’s really there):
  8. >>> results = repo.query("select * from cmis:document where contains('test')")
    >>> for result in results:
    ...     print result.getName()
    ...
    Test Document2
    example test script.js
  9. Alternatively, you can also get objects by their object ID or their path, like this:
  10. >>> someDoc = repo.getObjectByPath('/someFolder/Test Document')
    >>> someDoc.getObjectId()
    u'workspace://SpacesStore/2cf36ad5-92b0-4731-94a4-9f3fef25b479'

Set Python loose on your CMIS repository

These are just a few examples meant to give you a feel for the API. There are several other things you can do with cmislib. The package comes with documentation so look there for more info. If you find any problems and you want to pitch in, you can check out the source from Google Code and create issues there as well.

Give this a try and let me know what you think.

[UPDATE: I had the wrong URL for the Alfresco-hosted CMIS service. It’s fixed now.]

Spring, Roo, and Alfresco Too: What Alfresco Gave to Spring and Why

Surf Logo

You’ll recall from my community event takeaways post in November that Alfresco announced plans around Surf, the Apache license, and Spring but the details were foggy at the time. This week, Alfresco and SpringSource announced that Surf, Web Scripts, and Web Studio have been donated to the Spring open source community under the Apache 2.0 license.

What is Surf?

Surf is a lightweight web application development framework. At a very high-level, Surf is essentially Alfresco Web Scripts (an MVC framework for binding URLs to server-side JavaScript/Java and Freemarker-based views) plus some page layout constructs and some built-in objects for connecting to and authenticating with remote HTTP end points, including Alfresco (See also “Alfresco UI Options” and “Surf Code Camp“).

Why Spring Surf Makes Sense

Alfresco’s team collaboration application, Alfresco Share, is built on top of the Surf framework and clients and partners, including Optaros, have built solutions on top of Surf. But so far, our experience has been that we probably could have built solutions faster using a different framework. One of the reasons is because you often can’t do everything you need to with Surf alone–it lacks services that would normally be provided by a broader framework. Your choice is either to re-create what’s missing or bolt on something that exists. So that’s the first reason why Surf becoming part of Spring makes sense. Spring is already a mature and widely-adopted framework. It’s much better to make Surf and Web Scripts part of an established framework (and community) than to try to grow Surf into a full-featured framework.

The second reason is more strategic. Alfresco sees a future dominated by CMIS (See “Getting Started with CMIS“). They want to be the go-to CMIS platform. From a repository perspective, they’ve been very active on this front. But development tools are going to be important, and although part of the beauty of CMIS is that it is tool-agnostic, I think SpringSource and Alfresco would obviously be pleased if their framework became a very natural and productive way to build CMIS apps.

Third, Alfresco doesn’t necessarily want to spend a lot of time on tools and frameworks if it doesn’t have to. Look at how much time Web Studio has languished in Community limbo–it’s clearly not a priority. If Surf catches on in the broader Spring community maybe Web Studio has a chance to turn into something. My guess is that SpringSource would prefer all development to take place within STS, its Eclipse-based IDE. Maybe Web Studio will get sucked into that somehow.

So what is Roo?

One of the things mentioned as part of the Spring Surf announcement is that Spring Roo integration is included. Spring Roo is pretty new so you might be wondering what that is. It’s pretty cool, actually. Basically, it’s a productivity tool for people who are building Spring apps. If you’ve ever worked with frameworks like Ruby on Rails, Grails, or Django, one of the first things you learn is how to use the command-line project scaffolding tools. Those tools make it easy for you to spin up and configure your project. Spring Roo is similar–it gives you a shell and a bunch of commands for things like setting up persistence, adding unit tests, and configuring security.

Spring Roo is extensible which is where Surf comes in. Let’s say you’ve created a Spring project and you want to use Surf as part of that project. All you have to do is go into your Roo shell and type “surf addon install”. No monkeying with the web.xml. No hunting for JAR files. It just happens. Next, suppose you want to add some Surf pages. Type “surf page create –id ‘SomeOtherPage’ –templateInstance home” and the XML is created for you in the right place (yes, the shell provides keyboard assist and hints so you don’t have to remember those commands).

Roo is definitely better appreciated by seeing it or trying it yourself. Michael Uzquiano did a short screencast showing the Spring Roo Surf extension. If you want to try Roo out yourself, go through Ben Alex’s “Getting Started with Spring Roo” posts.

Learn More

The bottom-line is that Surf becoming part of the Spring community is a good thing. You should check it out. The official Spring Surf page is the place to start. That’s where you’ll find the SVN URL, binary downloads, and links to other resources. There’s also going to be a webinar in January if you want to learn more.

Forrester says 2010 looks good for ECM

Forrester has released the results from its 2009 Global Enterprise Content Management Online Survey. Here are a few of the things that jumped out at me…

72% of respondents plan on increasing their ECM investments in the coming year. That’s certainly good news. Of those increasing their investment, the big drivers are content sharing, compliance, search, and automation, which are all typical reasons to roll out a content management solution.

When asked to list the vendors that supply them with ECM solutions, 63% of respondents included Microsoft with EMC a distant second at 35%. (I kind of expected that Microsoft number to be higher). OpenText/Vignette (29%) and IBM (28%) were clustered right around there with a third clump forming around Autonomy/Interwoven (19%), Oracle (17%), and Alfresco (14%). The only other open source ECM players explicitly named were KnowledgeTree and Nuxeo, each with 1%. Almost a third of respondents also listed “Other, please specify” but Forrester doesn’t provide the list of write-ins. I assume it is a bunch of small, niche or homegrown solutions because the usual suspects were listed as explicit choices. Still, this chart and the one following that shows that nearly 3/4 of respondents have 2 or more ECM solutions in-house confirms what we’ve seen in our Optaros clients: Most people haven’t settled on a single ECM provider.

A little more than 1 in 4 of respondents were unsatisfied with their ECM solution. Of those, 41% blamed the solution itself as failing to “live up to expectations” followed by the usual grab bag of non-technical reasons IT projects fail. I would have liked to see a follow-up that dissected the various ways the solution fell short. Was it not able to do something you thought it was going to be able to do? Was stability an issue? Scale? Bad support experience? Or was it just that the beans you were told were magic turned out to be just plain old beans?

As my college stats teacher was fond of saying, “There are three kinds of lies: Lies, Damn Lies, and Statistics,” so take all of this with a grain of salt.

Book Review: Django 1.0 Web Site Development

I just finished “Django 1.0 Web Site Development” by Ayman Hourieh (2nd Ed). Packt sent me a copy and I was happy to read it. I thoroughly enjoy Python and Django and would like to see it more broadly adopted, so anything that helps people get started is a good thing.

Ayman’s book is clean and crisp. The book is built around a single cohesive example: Building a Delicious-style collaborative bookmark application with Django. That was a great pick for an example app. It’s easy to get your head around yet broad enough to provide good coverage of the topic. I also liked that Ayman threw in some JQuery to add a few AJAX features to the app. It was just the right amount to give you the idea without turning into a book on AJAX or UX development. Readers are similarly spared from wasting too much time on look-and-feel. CSS is kept to a minimum so that the focus remains squarely on Django.

Ayman flows logically from topic to topic. The book starts with a simple example and then gradually adds features until you’ve got a decent little app by the end. Within and between topics, the reader always has a good feel for what’s going on and what’s coming next. Initially, I was surprised that the admin UI–one of the cool time-saving features of Django that comes out of the box–was covered so late in the book, but later I decided that Ayman’s decision to focus on the shell to show API examples and test the app’s back-end was the right way to go. Chapter 12 is pretty weak–I would have traded most of the “ideas for evolving your bookmarking app” content for a discussion around Django on Google App Engine or maybe go deeper on some of the more interesting topics in that chapter that are only briefly covered, but that’s a minor nitpick.

I really enjoyed this book. Can you tell? Part of it is that Python and Django are such a pleasure to work with. The book itself is almost a metaphor: It’s concise (250 pages), well-written, and fun. If you’re new to the framework this book is a good way to see what all of the fuss is about.