I’m doing Part Two of a three-part “Developer’s Introduction to Alfresco” webinar tomorrow at 11:00 Central/12:00 Eastern/16:00 GMT. We’ll be covering custom content modeling and actions.
Last week’s Part One webinar was well-attended and we had a great Q&A session following so I’m looking forward to another good one, particularly as we start to get a little more technical.
Don’t forget to sign-up for the first ever DFW Alfresco Meet-up. It’s happening Monday, 3/9 at Ackerman McQueen over in Las Colinas. Plan to arrive around 5:30 and we’ll start our first topic at 6:00. We’ll hear about Ackerman McQueen’s recent Alfresco WCM-based project as well as the portal implementation built on Alfresco DM and Django (a Python-based framework) from the folks over at Neiman Marcus.
We’re letting Optaros pick up the tab on food and drinks so if you’re doing an Alfresco project right now or considering it, you need to join us. Come share what you’ve learned with others and maybe leave with a few new ideas as well.
With Alfresco 3 (both Labs and Enterprise), Alfresco added a new thumbnail service. It isn’t documented too well yet so I thought I’d write up a quick example.
What is it
The Thumbnail Service is used to create alternate renditions of objects. Typically, those alternate renditions are small images called “thumbnails”. You can see a working application of the thumbnail service if you take a look at Alfresco Share’s document library. When you upload a document, the thumbnail service is invoked, and a small image is shown next to each item in the list.
Where thumbnails live
Like everything else in Alfresco, thumbnails are stored as nodes. Nodes are instances of cm:thumbnail and are stored as children of the object they represent. (You can see this for yourself by looking at the thumbnailed object in the node browser). Objects can have any number of thumbnails. This lets you have thumbnails of different sizes and mime types, for example.
Once Alfresco generates a thumbnail for an object, the object will have the cm:thumbnailed aspect applied to it so it is easy to find or filter objects based on whether or not they have at least one thumbnail.
Thumbnail definitions & thumbnail names
Every thumbnail has a thumbnail definition. The thumbnail definition keeps track of things like the mime type, transformation options, placeholder path, and thumbnail name. The thumbnail name uniquely identifies the thumbnail definition in the thumbnail registry. When you want to generate or display a thumbnail for an object, you must specify the name. For example, given a thumbnail definition named “scImageThumbnail”, you could use JavaScript to create a thumbnail for an object by calling the “createThumbnail” method on a ScriptNode like this:
The first argument is the name of the thumbnail definition. The second argument says the thumbnail should be generated asynchronously.
Registering thumbnail definitions
The thumbnail registry needs to know about your thumbnail definitions. The out-of-the-box thumbnails are registered in the thumbnail-service-context.xml file. I don’t see a clean way to extend that without repeating the definitions, so in my example, I wrote a bean that calls the Thumbnail Registry and registers the custom thumbnail definitions provided in the Spring context file:
public class ThumbnailRegistryBootstrap {
private ThumbnailService thumbnailService;
private List<ThumbnailDefinition> thumbnailDefinitions;
private Logger logger = Logger.getLogger(ThumbnailRegistryBootstrap.class);
public void init() {
ThumbnailRegistry thumbnailRegistry = thumbnailService.getThumbnailRegistry();
for (ThumbnailDefinition thumbDef : thumbnailDefinitions) {
logger.info("Adding thumbnail definition:" + thumbDef.getName());
thumbnailRegistry.addThumbnailDefinition(thumbDef);
}
}
public void setThumbnailService(ThumbnailService thumbnailService) {
this.thumbnailService = thumbnailService;
}
public void setThumbnailDefinitions(
List<ThumbnailDefinition> thumbnailDefinitions) {
this.thumbnailDefinitions = thumbnailDefinitions;
}
}
So this class will add all of my thumbnail definitions to the thumbnail registry. The class and the definitions are configured in a Spring context file. The config for a single thumbnail called “scImageThumbnail” which is a PNG 100 pixels high and retains the original aspect ratio of the image would be:
The placeholder is a graphic that the thumbnail service can return as the thumbnail if the thumbnail for a given node has not been generated. In my example I just copied one of the out-of-the-box placeholders and renamed it but you could use anything you want there.
Example
I built a simple example to show how this works. Here is a screencast that shows it running or you can download the source and build it yourself.
In the example, a simple form is presented to allow a file to be uploaded. The form posts to a web script which creates a new node using the file provided. The form GET and POST web scripts are essentially the “helloworldform” web scripts from the Alfresco Developer Guide.
The “image list” is a simple GET web script that queries the folder where the images are uploaded to and writes out a list of image tags. The interesting thing to note here is the URL that’s used:
That URL is an out-of-the-box web script that returns the specified thumbnail for a given node reference. In my example I’m using the “ph” and “c” arguments. The “ph” argument says whether or not the placeholder image should be returned if the thumbnail does not exist. The “c” argument says that if a thumbnail doesn’t exist, queue a request for thumbnail creation. (Note that the descriptor says the queue create argument is “qc” but if you look at the controller source you’ll see it is actually just “c”. I’ll check to see if there’s a Jira on that).
When you add a new image and then go to the image list you’ll see the placeholder graphic. Behind the scenes, a thumbnail creation request has been queued. If you refresh the page, the thumbnail should show up because Alfresco has had a chance to generate it. If you wanted to queue the request when the node is created, you could either create a rule on the folder that holds the images, or you could add a call to “createThumbnail” in the upload POST web script controller, as shown earlier. (I’ve got an example of that commented out in the source).
That’s it
Hopefully this has given you some insight into the new thumbnail service in Alfresco. If you want to play with it yourself, you can download the source for the example and build it with Ant (make sure you set build.properties to match your environment first) by running “ant deploy”. Make sure you’ve got ImageMagick installed on your Alfresco server–the thumbnail service depends on it. You’ll also need the SDK to compile the registry bootstrap class. If you want to see what the thumbnail service is actually doing you’ll need the Alfresco source. None of the thumbnail source is included in the source code that currently accompanies the SDK.
I’m doing a one-hour webinar with Alfresco today at 12:00 Eastern. This is part one in a three-part series that introduces the Alfresco platform from a developer perspective. Learn more at Alfresco’s events page.
Update: You can catch the playback if you want. We did the webinar in two separate chunks. The first was a pre-recorded presentation and demo. The second was live Q&A.
As I’ve mentioned here and on twitter, we posted our Alfresco-Drupal integration on Drupal.org on Friday. I did a short write-up on it over at Optaros.com that gives the why and the what so I’ll not repeat it here.
We split the integration into two modules: CMIS API has nothing Alfresco-specific–it just knows how to make RESTful CMIS calls to an arbitrary CMIS repository. The Alfresco CMIS module has the Alfresco-specific logic. You need both to make the integration work. If you’ve got Alfresco 3 (Enterprise or Labs) you don’t need to do anything to your Alfresco install to enable the integration because it’s already CMIS compliant.
There is still a lot of work to do on this integration. For example, right now we’re only moving plain text content back-and-forth between Drupal and Alfresco. And we use a “single account” approach so that to Alfresco, every request appears to come from one user instead of passing through the authenticated Drupal credentials. But this is an imporant integration to us so I expect it to evolve substantially in the coming months.
I got good feedback on the recent screencasts I put together for Share (Part 1, Part 2) so if I get some time this week I’ll do one that gives a quick tour of the Drupal integration.
Okay, we’ve got a venue lined up, Optaros is bringing the food, and we’ll have two real world presentations from Ackerman McQueen and Neiman Marcus. Get directions, see the agenda, and RSVP at Upcoming.
My colleague, John Eckman, has posted the second part of the Alfresco Share screencast at Optaros Labs. In this screencast I show how a couple of examples of custom share components. One is a team bookmarks component and the other is a status/microblogging component. These components were built with Surf and should work in any Surf-based web site. Obviously, that includes Share but could be other Surf sites that you build. We will make both components available as open source.
My Optaros colleague, John Eckman, has been asking me to do this for some time so I finally caved and knocked it out. It’s a 12-minute screencast that shows the basics of Alfresco Share, an open source team collaboration tool which Alfresco markets as an alternative to Microsoft Sharepoint.
There’s also a “Part Two” which John will post on Optaros Labs next week that shows a couple of the custom Share components we developed. One is a Facebook-like “status” component and the other is a “team bookmarks” component. I’ll post the link when it’s up.
Share is pretty cool both from a functional perspective and with respect to the underlying technology. Share is built on Alfresco Surf plus a ton of YUI. The version I used in the screencast is 3.0.1 Enterprise.
A few of us in the area are talking about putting together an Alfresco meet-up the first week of March. Nothing fancy (and definitely not a sales pitch). Maybe we’ll have one or two presentations from real world implementations. The goal is for everyone to learn what we’ve all been up to, share ideas, etc.
I’ve got a venue squared away and someone to foot the bill for pizza and beer. Now I need the most important ingredient: You.
So respond here with a comment or contact me directly if this is something you think you might attend. If you have a topic you want to share with the group let me know that too. We’ll finalize the agenda and logistics based on the level of interest.
Did you miss the Alfresco Surf Code Camps? I’ve got you covered. With Alfresco’s blessing (they wrote most of the content, after all) I’ve uploaded the Optaros Alfresco 3.0 Surf Code Camp instructor presentations and class labs to slideshare.net.
You might start by looking at the agenda to get an idea of the order you should progress through the lecture and labs. Then, move on to the introduction. Use the agenda to guide you through the rest.
The labs will be a little bit more painful than they were in-person. That’s because for the in-person camps, we used a virtual machine image that had everything pre-installed. For the DIY Code Camp, you’ll need to set this up yourself. To approximate what was on the image:
Install the Alfresco-Tomcat bundle.
Install a second Tomcat instance. This will be your Surf tier.
Build a fresh Surf war. It’s in the “web framework” project in the source code. It will produce a WAR called alfwf.war.
The labs will refer to “assets.zip”. I had an assets.zip file for just about every lab. For this setup, I’ve just got one zip, which is the entire solution source available for download. So when you see that, you’ll have to pick through the solution to find the file dependencies. Sorry.
The image we used for the class ran on 3.0 Labs from head circa mid-November. I believe people have had success running on 3.0 Enterprise. I haven’t tested on Labs 3 Stable. If someone tries it please post a comment here to let us know your degree of success.
The Code Camp doesn’t cover Web Studio. I’ll leave that up to someone else–I’ll be happy to link to it.
UPDATE: Making you find your own dependencies for the labs was lame. I had a few extra minutes so I pulled them into a Code Camp Assets file organized by lab/walkthrough. Now you’ve got no excuse.