Tag: Alfresco Share Customization

Keep your users informed with this new Alfresco Share add-on

A common request from clients is the ability to manage a simple set of system announcements which can be displayed on the Alfresco Share login page. These might be used to let everyone know about important events like an upcoming system outage or that there are cronuts in the breakroom.

This is a straightforwaShare Announcementsrd add-on to write, but I thought it might be useful to others, so I’ve packaged it as an open source add-on available on GitHub.

The idea is simple: When you install the module, it will automatically create a folder in the Data Dictionary called “Announcements”. Administrators will create one plain text file in that folder for every announcement. There is no custom content model or properties to mess with. The content of the file is the body of the announcement.

An Alfresco Share Extension Module does the work on the Share side. When a user opens the Share login page, a Share-tier web script calls a new announcements web script on the repo tier that returns the announcements as JSON. The Share extension formats the JSON response as an un-ordered list that gets injected into the login page between the Alfresco logo and the username/password fields.

When you are ready to take an announcement down an admin can either delete the announcement file or move the file to an arbitrary folder under “Announcements” to save for later reuse.

Some installations–like those with Single Sign-On enabled–never see the Alfresco login screen. For those installations, or for anyone that wants to expose the announcements to logged in users, the add-on also includes an announcements dashlet.

Announcements DashletHopefully you’ll find this useful. If you find issues or want to make enhancements, pull requests are always welcome.

Alfresco embraces AngularJS: Now what?

Alfresco plus Angular2In 2009 I wrote a blog post called “Alfresco User Interface: What are my options?”  because people frequently asked for recommendations around that and they still do. Then, in 2010 at the very first Alfresco DevCon, I gave a talk called “Alfresco from an agile framework perspective“. My talk summarized how painful it was to build custom apps on Alfresco by building one simple app twice–once using Share and once using Django–and then comparing the effort it took. Django won, hands down, in terms of level-of-effort and lines of code.

Share was fairly new at the time, and it has improved a lot since 2010 in terms of ease-of-customization. In fact, a few of us met with Alfresco engineering at the conference to give feedback about the Share developer experience and Alfresco listened. The next release of Share had improved extension points. It became much easier to extend or override pieces of Share without massive copying-and-pasting of Alfresco’s code.

But there was another aspect of my talk, which boils down to this: If you are trying to appeal to developers, why are you asking us to learn a new framework? There are already frameworks out there that are extremely popular, have all sorts of tooling, and are well-documented. Use what you want to build Alfresco Share, but what can you do to make it easier for developers to build content-centric applications on Alfresco using tools we already know?

Fast-forward to BeeCon, the community-led Alfresco conference held in Brussels back in April of this year. During that conference, Alfresco announced that it was doing something about this problem: They would create libraries and components to help people create custom apps on top of the platform external to Share. Some of these will be framework agnostic. But after looking at the frameworks out there they realized they cannot deny the popularity of AngularJS, so they also want to provide customizable components that Angular developers can use.

About two weeks ago, we got our first glimpse of what this really means. Alfresco made its alfresco-ng2-components GitHub repo public followed closely by a live streamed hangout where they discussed the vision for the components (YouTube link).

Definitely clone the repo, try it out yourself, and watch that video for context. But let me try to summarize what it means for you…

What is happening to Alfresco Share, Aikau, and Surf?

Alfresco Share is the shipping web client. It is built on top of Aikau and a lower-level framework called Surf. If Alfresco is getting behind Angular, are these going away? No. Both John Newton, Alfresco’s co-founder, and John Sotiropoulos, Alfresco’s new VP of Applications, were emphatic on that point. There are no immediate plans to make any significant changes to the direction of Alfresco Share, Aikau, or Surf. Many people have customized Share–those customizations should remain safe. Plus, a lot of people use Share out-of-the-box. Alfresco still needs a web client and they are their own biggest fans when it comes to Aikau and Surf.

I am customizing Share right now. Should I stop?

No, these components aren’t going to affect you. If you have no reason to build a custom front-end on top of Alfresco, you can safely ignore this announcement. However, if you are customizing Share because you thought it would be easier than writing your own custom application, and your customizations are so significant, that it feels like you are basically re-building an application from the ground-up, with little or no re-use from what Share offers, you may want to keep an eye on this. These components will give you a jumpstart on what otherwise would have been a from-scratch effort.

What exactly is shipping right now?

Alfresco is making an initial set of components available that includes:

  • Login
  • Document list
  • Document viewer
  • Datatable
  • Search
  • Uploader

In addition to the components, Alfresco offers a Yeoman generator to help you bootstrap an Angular2 application that makes use of one or more of these components.

I am writing a custom front-end using Angular right now. Should I stop?

Alfresco is shipping Angular components that can be used to build custom apps on top of Alfresco. And you are doing the same thing. It would seem like you might want to stop and leverage the new components. Before you do that, you need to be aware of two very important caveats.

First, Alfresco is using Angular2 which has very significant differences with Angular. And Angular2 is still shipping as a release candidate. Depending on your appetite for refactoring and risk, you may or may not want to make the switch to Angular2 just yet. Still, I think it was smart for Alfresco to choose Angular2 to avoid making that move later.

The second thing is that the new Alfresco Angular2 components rely on significant enhancements to the Alfresco REST API. Those enhancements are not in any stable version of the product. They are only available starting with 201606 EA (Early Access) release, which includes 5.2.a of the Alfresco platform. There is no way to know when Alfresco 5.2 Community Edition will go to a GA (Generally Available, aka “stable”) release. Which means we also do not know when 5.2 Enterprise Edition will ship.

You should not run any Early Access release of Community Edition in production. Therefore, if you need to be in production any time soon, you will not be able to leverage these components.

This second caveat has caused a fair amount of grumbling amongst the community. There has been some talk about back-porting the new REST API to a stable Alfresco release, but, unfortunately, this cannot be done without changes to the core.

People have been developing custom front-ends on top of Alfresco using Angular and other frameworks for years without making deep changes to the core product. Alfresco didn’t have to do it in this case, but they chose to, because they wanted to clean up the API simultaneously. Basically they chose the “rip the bandage fast” approach, which I understand. However, the impact of this decision is that it will be many, many months before real world feedback on these components makes it into the shipping code. Hopefully, enough people will still be motivated enough to try them out with the EA release.

I want to try the new components, how do I get started?

First, you’ll need a running version of 5.2.a (201606-EA) with CORS enabled. I forked the gui81/alfresco Docker image and upgraded it to 5.2.a with CORS enabled and pushed the result to Docker Hub if you want to use it. Or you can download it from the wiki or Sourceforge.

The GitHub repo has a good readme, so take a look at that. I’m not going to duplicate it here, so follow those directions.

I had good luck installing the Yeoman generator and then just running “yo ng2-alfresco-app”. You’ll get a chance to specify which components you want installed into your new app–I had problems unless I selected all of them.

Yeoman generates the app. NPM is used to run it locally for development purposes. To fire it up, just run “npm start”. Once up, I was able to use the sample app to work with the back-end Alfresco repository, as shown here (click to enlarge):

Alfresco Angular2 Components

It’s probably important to note that what you see running is basically a sample app or sandbox for these components. It’s up to you to write a functional app with all of the features your users need. You’ll incorporate and customize these components as part of your own development effort. You can check the documentation to learn more about how to customize each component.

Alfresco wants your feedback on these components. Don’t be afraid to report issues or submit pull requests on the GitHub repo.


I am excited to see this from Alfresco. It is too early to use these in production, but once the new REST changes ship in a GA product, you should definitely consider this as a way to jumpstart your custom apps, even if you don’t use Angular. If you’ve been looking for a way to get involved in the Alfresco community, trying these out and giving your feedback is an excellent opportunity to do so.

Quick Hack: Restricting Create Site Links to a Site Creators Group

At Alfresco Summit 2014 there was a wonderful session from Angel Borroy called, “10 Enhancements That Require Less Than 10 Lines of Code“. If you missed it you should follow that link and watch the recording.

Angel said the talk was inspired by my blog post about an example add-on I created that allows you to define default folder structures that get populated in the document library when you create a new site (see share-site-space-templates on GitHub).

One of the other 9 enhancements Angel showed was how to hide the “Create Site” link. I’ve seen so many of my clients and people in the forums asking for this functionality, I decided to enhance it a little bit, put it in an AMP, and make it available on GitHub. You can download share-site-creators and try it out for yourself.

Here’s a little more about how it works…

Instead of hiding the “Create Site” link from everyone but administrators, my add-on allows you to create a group that is used to determine who can create sites. The group, appropriately enough, is called “Site Creators”. If you aren’t in that group, you won’t see the “Create Site” link in any of these places:

  • The Sites menu
  • The “My Sites” Dashlet
  • The “Welcome” dashlet

Additionally, the add-on changes the underlying permissions at the repository tier so that if your teammates are hackers, they cannot circumvent the user interface and create their sites using other means.

The screenshot below (click to enlarge) shows what it looks like when you aren’t a member of the Site Creators group:

The Share Site Creators add-on restricts the Create Site link to a specific groupYou might notice that the text of the “Sharing” column in the welcome dashlet also changes to be more applicable to someone who cannot create their own sites.

The new text is in a properties file. Currently I have only an English version, so if any of my multi-lingual friends want to translate the new string, that might be useful to others.

Just like my Share Site Space Templates add-on, this one is not mind-blowing. But it is useful, both in terms of functionality, and as an example of how to override Alfresco Share web scripts without copying-and-pasting tons of code.

I’ve tested this with Alfresco 4.2.f Community Edition. If you want to get it working with other versions, or you have other improvements, bring on the pull requests!

New tutorial on Share customization with Alfresco Aikau

Alfresco community member, Ole Hejlskov (ohej on IRC), has just published a wonderful tutorial on customizing Alfresco Share with the new Alfresco Aikau framework.

You may have seen one of Dave Draper’s recent blog posts introducing the new framework. Ole’s tutorial is the next step you should take in order to understand the framework and how it can be used to make tweaks or additions to Alfresco Share.

I was happy to see Ole follow my example for the format and publication of his tutorial and that he’s made both the tutorial itself and the source code available on GitHub for anyone that wants to make improvements.

Thanks for the hard work and the great tutorial, Ole!

Five steps you can use to figure out how anything in Alfresco Share really works

A forums user recently asked how to use the “quick share” feature from their own code. The implementation is easy to figure out, but I thought illustrating the steps you should use to dig into it would be instructive, because it is the same general pattern you would follow to learn how anything works in Alfresco.

What is Quick Share?

Quick Share makes it easy for end-users to share any document with anyone whether or not that person is a member of a site or has specific permissions on a document. Clicking the “Share” link in the document library or document details displays a dialog with a shortcut URL that will allow anyone to see a preview of the document. If that person also has access to the document, they can optionally download the document as well.

The Quick Share feature in Alfresco Share


How does this work behind-the-scenes? Let me show you how to figure that out. These steps can be used to demystify any Share-based functionality you need to learn more about.

Step 1: Determine the call Share makes to the repository

Share is just a front-end web application. It always talks to the repository via HTTP. Step 1 is to take advantage of that. Use Firebug or a similar browser-based client-side debugging tool to watch the network traffic between Share and the repository. If you turn that on you’ll see that when you click “Share” the browser makes a POST to:


What comes back is JSON representing the quick share ID:

"sharedId": "oD9wUfV_SPS9eG-CFEpwbQ"

The first part of that URL, “/share/proxy/” is the Share proxy. It simply forwards the request on to the repository tier. In this case that’s a web script residing at “/alfresco/api/internal/shared/share”. The rest of the URL is the node reference of the node being shared.

As a side-note, unsharing works similarly. Share sends a DELETE to http://localhost:8080/share/proxy/alfresco/api/internal/shared/unshare/oD9wUfV_SPS9eG-CFEpwbQ

That returns JSON with the return flag:

"success" : true

So now you know how Share interacts with the repository. The next step is to dig into the repository tier implementation.

Step 2: Look at the repository web script

Now that you know the repository web script URL you can go to the web script console, http://localhost:8080/alfresco/s/index, to learn more about the web script. I find searching by URI to be easiest. Here’s the web script in the list:


Clicking on that link shows high-level information about the web script. Make note of this web script’s lifecycle–it is set to “internal”. That means you shouldn’t call it from your own applications or customizations. If you do, you may be creating a future maintenance headache because the web script may change without warning.

In this case, we don’t want to call the web script, we want to know what the web script is doing. Clicking on the web script ID will tell you more about how it is implemented. Here’s the URL where you’ll end up:


This page is really helpful because it shows you the details about the web script implementation, including its views and controllers.

Web Script Implementation Details

In this case, the web script uses a Java controller implemented in the following class:

The next step is to dig into the web script implementation.

Step 3: Read the source code for the implementation

If you search through your Alfresco source code you’ll find ShareContentPost.java. It’s a very simple web script. Here’s the line that does the work:

QuickShareDTO dto = quickShareService.shareContent(nodeRef);

Cool, so there is a QuickShareService. I’m going to make a time-saving leap here which is to assume that anything named like FooService is likely defined as a Spring bean that I can inject in my own code.

Step 4: Find the QuickShareService bean

If you’re going to write some Java code that leverages the QuickShareService you’ll probably want to see the Spring bean configuration for that bean. To find that, go into $TOMCAT_HOME/webapps/alfresco/WEB-INF/classes/alfresco and do a grep for QuickShareService. You’ll see that it is defined in quickshare-services-context.xml.

Now you have a Spring bean ID you can use as a dependency in your code.

Step 5: Understand the content model

You might choose to do this in an earlier step, but if you haven’t already, you should use the node browser in Share to see what happens to a node when it is shared just in case you need to make use of any of that information. By doing that you’ll see that a shared node has an aspect called qshare:shared. When it gets shared, the qshare:sharedId and qshare:sharedBy properties get set. In this example, the QuickShareService handles that for you–you shouldn’t have to set those manually. But it is good to know those properties are there in case you need them.

If you needed to learn more about the content model you could grep for that aspect ID, qshare:shared, in $TOMCAT_HOME/webapps/alfresco/WEB-INF/classes/alfresco/model to figure out where the model XML is.

Now you have everything you need to make use of this functionality in your own code. For example, if you wanted to create a rule action that automatically shared everything matching a certain criteria, you could easily do that by injecting the QuickShareService into your action and then calling the shareContent() method (see my actions tutorial).

This example covered the Alfresco Quick Share feature in the Alfresco Share web client, but you can use these steps to dig into any functionality in Alfresco Share that you need to deconstruct.

Tech Talk Live, Dashlet Challenge, & other Alfresco community events

Just wanted to clue you in to some upcoming Alfresco events in case you missed them via other channels.

Tech Talk Live Reloaded

We’re going to start doing Tech Talk Live webinars again. In the past these webinars were run by Luis and Yong pretty much on a weekly basis. They typically started out with a short presentation on some topic and then opened up to general technical discussion. We’re going to start these back up, but we’ll do them monthly (at least to start out) on the first Wednesday of each month and we’re going to rotate the Alfresco engineers that participate.

The first call will be Wednesday, July 6th. Will Abson is going to talk about Share Extras and then field questions on Share dashlet development and other customizations. Get more information on the event details page.

Community Vision and Plan

I’ve presented a vision and plan for the Alfresco community to the rest of the senior management team at Alfresco, and recently I’ve been sharing that presentation with members of the community. On July 7th, I’ll be sharing it more broadly in a webinar. I’d really like as many members of the community to attend as possible and then provide me with feedback on the plan. Sign up for the webinar here.

Intro to Alfresco Development

On July 20th I’ll be giving a talk for people new to the Alfresco platform. We’ll be walking through the major sub-systems and taking a high-level look at the development model. Again, this is aimed a beginners–this is not a technical deep dive. Sign up for the webinar here.

Take the Dashlet Challenge

Speaking of writing code, got any cool ideas for Alfresco Share dashlets? If you code it up, make it available as open source, and send a pointer to your project to dashletchallenge@alfresco.com, you could win an iPad2. Your dashlet has to run on either Community or Enterprise 3.4 and will be judged on the basis of creativity, business applicability, code quality, and packaging. Will Abson, Mike Vertal (RivetLogic), and I will pick the winner. The contest runs until the end of August, so get coding. More details on the contest can be found here.

Will Abson’s Wonderful World of Dashlets

Back when Alfresco first launched Surf, the framework on which Alfresco Share is based, a handful of us went to Chicago to hang out in a conference room on a ship in the harbor where we did a deep dive on the framework and then came up with proposed add-ons that would leverage it. I was at Optaros at the time. Our add-on was the Alfresco Share microblogging component and we also did some Surf Code Camps. The goal, of course, was to get the word out about Surf and encourage others to develop and contribute Share customizations.

The deep dive was great and the code camps that followed were valuable and well-attended. What I think the approach missed was that you don’t need to be a Surf expert to code some simple dashlets. We were handing out “How to Fly the Space Shuttle” when we probably should have started with “Building and Launching Your First Model Rocket”.

That’s why Will Abson is my current Alfresco community hero. At this year’s Alfresco Kickoff meeting in Orlando (notes), Will showed a project he and a few others have been working on called Share Extras. Share Extras is a collection of small projects ranging from “Hello World” dashlets to custom theme, data lists, and document action examples.

For example, the list of what I’d call simple, mash-up examples includes things like:

  • Twitter Feed Dashlet – Shows a specific Twitter user’s feed.
  • Twitter Search Dashlet – Shows a Twitter feed based on a hashtag.
  • BBC Weather Dashlet – Shows weather feed from BBC.
  • Flickr Dashlets – Shows flickr photos in a slideshow.
  • Google Site News – Shows the last ten blog posts from Google News.
  • iCal Feed – Shows entries from an iCal feed.
  • Notice Dashlet – Stores/shows arbitrary text, like what you’d use for a maintenance message or an announcement.
  • Train times – Shows the National Rail train schedule.

From there, you can move on to more extensive examples. For example, rather than simply displaying data from public services, these examples start to store/retrieve data in the underlying Alfresco repository:

  • Site Tags Dashlet – Displays a tag cloud consisting of tags used in your site.
  • Site Poll Dashlet – Uses a custom data list type called Poll to configure a simple poll. Shows results in bar chart.
  • Document Geographic Details – Adds a map using the document’s geocoding metadata just below the permissions section.
  • Sample Data Lists – A simple data list example that lets you capture info on Books (author, title, ISBN).
  • Execute Script Custom Document Action – Shows an example of adding a custom action to the action list that runs server-side JavaScript against a node.

The nice thing is that (almost) every one of these extensions deploys as a self-contained JAR file. Will’s build assumes you are running the repository and the Share web apps in the same container, so it deploys the JAR to $TOMCAT_HOME/shared/classes/lib, but you can obviously tweak that if your config is different. The ability to run everything out of a JAR, including what would normally be file system based resources like CSS, client-side JavaScript, and images is a relatively new feature (3.3, I think). It’s much nicer than fooling with AMPs.

Here is a list of my five favorites from the collection:

  • Node Browser – A port of the Explorer client’s node browser to the Share UI. I like this one because it brings an extremely useful developer tool into Share, which is where most of us are spending time these days. It also shows how you can plug your own tools into Share’s admin console.
  • Red Theme – A simple custom theme example. This is on my favorites list because creating a custom theme is something that is requested often and should be easy to do. Follow this example to create your own.
  • Site Geotagged Content Dashlet – Adds a dashlet that shows a map of geotagged content contained in the document library. I can’t help it. I like maps.
  • Site Blog Dashlet – Dashlet that shows site blog posts. This is a favorite because it plugs a hole in the product. If you’re going to use the blog tool in a Share site, you’re going to want to show those posts somewhere and a dashlet makes a lot of sense.
  • Wiki Rich Content – Automatically puts a table of contents at the top of a wiki page based on the headings contained within the page. Also does a nice job with pre-formatted text. This is another example of a feature that should probably be in the core product.

The Google Code project includes screenshots for each of these projects, but it is really easy to do a checkout on the code, import the projects into Eclipse, create a build.properties file in your home directory to override the tomcat.home prop, then run “ant hotcopy-tomcat-jar” to deploy one and see it in action for yourself. I tried them all out on Alfresco 3.4d Community and they worked great. I think all but one or two will work on 3.3.

The Share Extras project includes a Sample Project with a folder structure and Ant build that you can clone and use as a starting point for your own development. If you create something cool, you should share it on Google Code and then let me know about it. Or give it to Will and he can add it to his ever-growing pile of cool Share add-on examples.

Now available: Alfresco Fivestar Ratings add-on for Alfresco Share

A couple of weeks ago I posted a survey asking if anyone saw any value in a five star ratings widget for Alfresco Share. Honestly, it would have only taken one or two positive responses–even if no one needed one, there’s value in it for example’s sake. It turns out about 20 readers of this blog voted positively, so I went ahead and knocked it out.

This Alfresco Share customization makes it possible for any document in the repository to become “rateable”. When a document is rateable, the Alfresco Share user interface will show a clickable five star ratings widget. The stars light up to indicate the average rating for that document. Users simply click one of the stars to post their own rating. When clicked, the widget refreshes itself with the updated average.

Here is a short screencast that demonstrates the customization. You’ll want to make it full screen.

To implement this, I took the Someco Ratings Service from the Alfresco Developer Guide, moved it to the Metaversant namespace, and changed the names of my Spring beans and JavaScript root variable. Even though my initial target Alfresco version is 3.3, I didn’t want the code to conflict with Alfresco’s new back-end-only ratings service in 3.4 which uses some of the same names that were in the book. I also changed the JSON that the ratings web scripts use to be closer to what exists in 3.4. That way, when I do make a version that works with 3.4, it could potentially work with either my ratings back-end or Alfresco’s.

I then went to work on the UI side, integrating the widget into Share’s document details page, document library (both Share and repository views), search results page, and document-related dashlets. To go from what was in the book to a working integration I revamped the client-side ratings JavaScript from a set of functions to an actual object. Then, I started injecting my own methods into Alfresco’s client-side object prototypes to drop my widget in where appropriate.

Alfresco is still working to make customizations like this more modular and easier to plug in alongside their code and code from the community. Until then, be aware that if your Alfresco implementation already has customizations that override some of the same web scripts and client-side components this module does, there may be some manual integration needed. If you have an out-of-the-box installation (or a set of customizations that won’t conflict with this one) you can deploy the AMP to the Alfresco WAR and the Share customizations to the Share WAR and you’ll be set.

The Alfresco Fivestar Ratings project lives at Google Code. Feel free to check out the source, try it out, and use it on your projects. If you find a bug, log it, then fix it!

Any interest in a pre-3.4 five star ratings widget for Alfresco Share?

One of the examples I put in the Alfresco Developer Guide is a five star ratings widget. The example company in the book, SomeCo, uses it to let their web site users rate whitepapers published on the site. Metaversant recently took that code and implemented it in a production web site, and that client gave us permission to take the code (which wasn’t really changed that much from the book anyway) and release it as open source.

But in Alfresco 3.4 Community and Enterprise, Alfresco has implemented partial ratings functionality. Right now, it consists of the back-end, repository tier services and it is darn close to what’s in the book.

With the back end in place, I expect Alfresco to release ratings functionality in the Share front-end in an upcoming release. So, I’m somewhat reluctant to package up my ratings stuff and release it as it is partially obsolete in 3.4 anyway. On the other hand, it would give those of you on releases earlier than 3.4 a functional ratings widget, and, with some adjustments, I could make the front-end work with Alfresco’s rating service in 3.4, which would mean functional ratings in Share for those of you that have already upgraded.

If the code was ready to go, I’d just package it up and if only one person used it, great. But, the client we did the widget for was using a heavily customized version of Share–we didn’t integrate the widget into the out-of-the-box document library or document details page. That’s the last bit of work that needs to be done. Even if there is no interest, I might do it anyway just to have as an example. But, I’d be even more motivated if there were folks out there who would use it in their production implementations.

So what do you say? Any interest? Take the survey below and let me know.

Create your free online surveys with SurveyMonkey, the world’s leading questionnaire tool.

Monitoring folders with Alfresco workflows

This is the second part of a two-part post on some recent work Metaversant did with Alfresco workflows. The first part was a post on Workflow Reporting. It outlined a high-level recipe for creating a workflow dashboard in Share that showed a list of workflows started for a specific Share site and allowed bulk actions (such as “cancel”). In this post, we’ll look at Folder Monitoring which deals with how to automatically start an Alfresco jBPM workflow when a document is dropped into a folder.

The easy answer

The embedded jBPM workflow engine that’s embedded in Alfresco is flexible and powerful. Creating a new process and wiring it into the Alfresco Explorer or Alfresco Share user interface is straightforward once you’ve done it a time or two. If you need a refresher on the details, see “Get your Alfresco ‘flow on“. For the purposes of this discussion, just know that your process definition can have process variables which you can read and set from the user interface and from code within the process definition.

It’s actually really easy to start a workflow when objects are created or updated in a folder. That’s because the Alfresco JavaScript API can run the “start-workflow” action, and Alfresco JavaScript can be invoked from a rule that runs when something is updated in a folder. The JavaScript to start a workflow using this approach looks like this:

var startWorkflowAction = actions.create("start-workflow");
startWorkflowAction.parameters.workflowName = "jbpm$wf:adhoc";
startWorkflowAction.parameters["bpm:assignee"] = assignee;
startWorkflowAction.parameters["bpm:workflowDescription"] = description;

The catch is that when you use that approach, the developer writing the JavaScript has to know at design-time what values to provide to the workflow when it starts up (in this case, the assignee and the description). Ordinarily, when a workflow is manually invoked, the end-user starting the workflow is there to provide those values. If your particular workflow doesn’t require any variables to start, or the variables are known at design-time, the simple rule-invokes-JavaScript approach will work. Otherwise, something more is required.

What we needed for this client was not only the ability to start a workflow when a new object landed in a folder, but also the ability for an end-user to specify parameters for that workflow ahead of time. When discussing the functionality we called it “precompiled workflows” and “workflow templates”, which is pretty descriptive of what we needed. From the user’s perspective, we needed one user (let’s call her a Manager) to be able to say, “When an object is created in this folder, launch this specific workflow with these parameters”. When other users (or systems) create objects in that folder, the workflow needs to launch automatically without further input.

Options considered

As usual, there are a few different ways to go about this. One is the rule-invokes-JavaScript approach discussed earlier. The problem with this is that the parameters have to be specified in the JavaScript and that won’t work for non-technical end-users. This option was discarded early.

The next option we considered was creating a custom action. This almost gets us there. The Manager user can create a rule on a folder and select the custom action. The form service (Share was the main UI in this case) can be configured to let the Manager set the parameters to use when launching the workflow. Non-Manager users can then create objects and workflows will launch automatically.

The problem with this approach is that the list of parameters is not finite–this client had big plans for the workflow engine and they did not want to modify the custom workflow launching action every time they created a workflow that had a new parameter. Similar to the first option, this approach has worked well in the past, but it didn’t fit for this client, so we moved on.

The third option we looked at was a variation on the second. Rather than having the action handler responsible for grabbing parameter values, this approach uses the workflow model itself to persist a “workflow configuration” that the action can point to. The Manager would create a workflow configuration, then configure the rule to say, “When documents are added to this folder, start this workflow with this configuration”.

The workflow configuration could be a custom object. Briefly, we considered actually persisting objects that correspond to the types defined in the workflow model (normally, those aren’t saved anywhere), and I think if we ever revist this option, we may look at that again.

The problem with this approach was that the Manager has to think too much. Am I creating a workflow that’s going to launch other workflows? Okay, then I need to create a “workflow configuration” and configure a rule. Am I just routing something through a workflow? Okay, then I need to use “start workflow” like I normally would. That’s way too confusing. Next!


Ultimately, we decided that the easiest route from both an implementation perspective and an end-user perspective was to rely on the business process to be smart enough to tell the difference between a package with a folder and a package with documents. When the workflow is run on a folder, it can iterate over the children of the folder, spawning new workflows and copying its process variables into the newly started workflows. It can then transition to a wait state until something tells it to go check for new children in the folder. When the same workflow is run on a document however, it proceeds down the “non-folder” route and performs the work it normally would.

Using this approach, every workflow is able to run as both a “folder monitor” and a “worker”. That way, when a Manager starts a workflow, she doesn’t have to think about whether she’s starting a “monitor” workflow or a one-time workflow, she just starts the workflow as normal and sets the parameters. The business process does the work of spawning additional workflows when it needs to and passes those parameters along. Now we’re talking!

High-level Recipe

Similar to my previous post on workflow dashboards, I may make this source available at some point, but until then, here are the high-level steps to do it yourself.

Create the jBPM process definition

This will work with any process definition, so I won’t describe anything business-specific here. Instead, I’ll talk about what you would add to your process definition to make this work.

The first thing the business process needs to do is make a decision: Am I running against a folder or a document? If the package contains documents, the workflow continues as it normally would. If, however, it contains a folder, the workflow iterates over the folder’s children and starts a new workflow instance for every child in the package, copying its process variables into the new workflows.

The decision is implemented as JavaScript. If we find one folder, we take the folder route. In this case, the users are only going to run the workflow on one folder at-a-time so we don’t have to worry about what to do if the workflow package contains a mix of documents and folders. The decision JavaScript looks like this:

var flag = false;
for (var i = 0; i < bpm_package.children.length; i++) {
    if (bpm_package.children[i].isContainer) {
        flag = true;
isContainer = flag;

And the transitions for the decision look like this:

<transition to="forkWork" name="toForkWork"></transition>
<transition to="forkMonitor" name="toForkMonitor">
    <condition>#{isContainer == true}</condition>

The forkMonitor node is a fork that creates a workflow dashboard task (see previous post) and simultaneously transitions to the spawnWorkflows node. The spawn workflows code is a little too lengthy to include here, but what it does is:

  • Grabs the parameters it needs to pass in to each of the newly started workflows
  • For each document in the workflow package…
  • Checks to make sure the document hasn’t already been processed (more on that later)
  • Checks to make sure the document isn’t already in a workflow
  • Starts the workflow using the out-of-the-box start-workflow action (see the code at the start of the article)

Once the workflows are spawned, the business process transitions to a wait state where the process sits indefinitely until it is told to check the folder for new children.

Create a custom action that will tell the process definition to check for children

How does the workflow know when new children have been added to the folder? I’m so glad you asked. After the workflow spawns new workflows for the children, it transitions to a wait state. To trigger the workflow to move off the wait state, we used a custom rule action. The rule action is set high enough up the folder hierachy that end-users don’t have to worry about it–it automatically inherits onto the folders created below it. The rule action is Java-based, and it takes two parameters: The name of a node and the name of a transition to take.

When a new document is added to a folder, the rule triggers the action. The action grabs the node’s parent and checks to see if it is involved in a workflow. If it is, it tries to find the workflow node named in the parameter, which will be the wait state mentioned in the previous step. If it finds that, it signals the node to take the specified transition. The transition will be to the “spawn workflows” node.

Workflow screenshotThe combination of the wait state and the spawn workflows node in the business process with the custom rule action that signals the wait state creates a cool little “interrupt” loop: The process spawns workflows for folder children, then waits until more children arrive, then spawns workflows for those children, and so on until someone kills the workflow.

Customize the Share user interface to allow workflows to start on folders

Since the dawn of time Alfresco’s UI has not allowed workflows to start on folders, but the workflow engine can handle it. For this approach to work we most definitely have to be able to start workflows on folders. That’s a pretty simple little config tweak to make that happen in Share–just copy the existing assign workflow action link from the document actionSet to the folder actionSet in documentlist.get.config.xml (and document-actions.get.config.xml), like this:

<actionSet id="folder">
    <action type="action-link" id="onActionAssignWorkflow" permission="permissions" label="actions.document.assign-workflow" />

Voila! Now you can run workflows against folders.

Create a “workflow status” aspect to avoid processing docs more than once

The last step is to make sure that documents only run through the process once. Otherwise, every time the process spawns workflows for children in a folder, he’ll start one up for every child in the folder, regardless of whether or not its been through the workflow already. This may be what you want, but this particular client wanted docs to run through the process only once.

To do this, we created a simple aspect with a “workflow status” property. In the last node of the process, the property gets set. When the spawn workflows code runs, it filters out folder children that have the status set.

That’s it!

This approach puts the burden on the workflow designer to use some standard node names and logic in their process definitions. And, it will result in many in-flight workflows (at least one for every folder being monitored), although that shouldn’t be a big deal from a performance perspective (running workflows really aren’t “running”).

The important thing for this client is that it provides a nice way for users to essentially “pre-configure” workflows so that subsequent users can start workflows simply by adding documents to a folder, all without anyone having to learn any new “workflow configuration” constructs. And, workflow designers can easily make their workflows “folder aware” or “templatable”, depending on how you want to look at it, all within the process definition, without having to recompile any custom actions or tweak JavaScript.