Tag: Alfresco Share Customization

Adding actions to the Alfresco Share Selected Items menu

In a typical Alfresco implementation it is quite common to develop one or more custom actions to encapsulate a set of operations that need to be performed against a folder or document. Custom actions can be called from folder rules, added to the user interface, or called programmatically from web scripts. To learn more about developing custom actions, check out my tutorial on custom actions.

When actions are added to the Share document library or document details page they operate against a single folder or document. But the Share document library also lets users select multiple objects and then run actions against them. Out-of-the-box examples are things like “Download as Zip”, “Copy”, “Move”, “Start Workflow”, and “Delete” as shown in the screenshot below.

Alfresco Share out-of-the-box selected items menu

This blog post explains how you can add your own custom actions to the “Selected Items” menu in Alfresco Share.

First, I’m going to assume that you already have a custom action that works when invoked from a rule or from the UI and you just need it to work from the Selected Items menu. I’ll call mine “Example Action”. It doesn’t do anything exciting except log the node reference of the object the action is run against. Here it is sitting in the list of document actions on the document details page:

Custom action displayed in the Alfresco Share document details actions list

Now the goal is to add Example Action to the “Selected Items” menu so that the action will run against each object the user has selected. If you want to skip right to the working project on GitHub that’s fine, otherwise, read on for a step-by-step…

Step 1: Extend the multi-select configuration

I used a Share extension to add some custom configuration to get Example Action to show up in the document library browse list and the document details page. I’ll add additional config to extend the out-of-the-box “multi-select” list of action links:

<config evaluator="string-compare" condition="DocumentLibrary">
    <multi-select>
        <action type="action-link" id="onExampleAction" label="actions.example-action"></action>
    </multi-select>
</config>

The action label is a property bundle key that has the text I want to appear in the menu. The action ID, onExampleAction, is the name of a client-side JavaScript function to be called when the user selects the menu item.

I’ll implement the onExampleAction function in a file named custom-actions.js. I need to get Share to include that file as a dependency, so I add an additional config block:

<config evaluator="string-compare" condition="DocLibCustom">
    <dependencies>
        <js src="resources/multi-select-demo-share/custom-actions.js"></js>
    </dependencies>
</config>

That’s all I need to change in my Share extension XML file. See the full file on GitHub.

Now let’s look at the client-side JavaScript.

Step 2: Implement the client-side JavaScript

In the previous step I configured Share to add an action to the “Selected Items” menu that invokes the onExampleAction function when clicked and I told it where to find the function. Now I need to implement the function. To do that, I use YUI to fire a “registerAction” event, passing in an object with two properties: one is the name of my action and the other is a function to execute:

(function() {
      YAHOO.Bubbling.fire("registerAction",
          {
              actionName: "onExampleAction",
              fn: function custom_DLTB_onExampleAction(assets) {
                  // Function logic goes here
              }
          });
})();

Note that “onExampleAction” matches whatever I specified as the action ID in the multi-select config. It has nothing to do with the name of the Java class that implements the back-end action executer.

Within that function body you could do whatever you want. Maybe you need to capture some additional data from the user, so you present a modal. Maybe you want to display a progress bar. It’s up to you.

In my case, I just need to send the selected nodes to the back-end. Remember that I already have a working action. Mine is a Java class named ExampleAction that writes a log message with the node reference of the node the action is running against.

It would be nice if I could just somehow call that action and hand it my list of selected node references, but the execute method in the ActionExecuter interface only accepts a single node. Plus, we’re currently sitting in client-side JavaScript delivered by Share that needs to invoke an action in the Alfresco back-end–a completely separate web application. I need a way to asynchronously make an HTTP call to the Alfresco back-end from here.

The solution is to call a custom repository-tier web script with the list of selected node references, and use the web script controller to invoke the action for each of the node references in the list.

Alfresco provides a utility for making asynchronous posts and a constant that has the Share proxy URI. (The Share proxy avoids making the call from the browser all the way back to the Alfresco back-end, which could be running on a different host.) All I have to do is provide the path to the web script and the list of assets:

Alfresco.util.Ajax.jsonPost(
    {
        url: Alfresco.constants.PROXY_URI + "ecmarchitect/example-action-multi",
        responseContentType: "application/json",
        dataObj: assets,
        successMessage: this.msg("message.example-action.success"),
        failureMessage: this.msg("message.example-action.failure"),
        successCallback:
            {
                fn: function exampleSuccess() {
                    console.log("Success");
                },
                scope: this
            },
        failureCallback:
            {
                fn: function exampleFailure() {
                    console.log("Failure");
                },
                scope: this
            }
});

In the above JSON POST I am also setting a success message and a failure message so that the Share user sees feedback after the web script is invoked. Just to show you how it works, I’m also including success and failure callback functions. Mine just write a message to the browser developer console, but you could do whatever you need to, such as display data that came back in the web script response.

You can review the full source of custom-action.js or go on to the next step, which is to implement the web script.

Step 3: Implement the web script

I need a web script that will accept the list of selected nodes and invoke the action for each one. Webscript controllers can be written in either JavaScript or Java (tutorial) but I almost always write them in Java these days.

You can see the full source of ExampleActionMulti.java on GitHub–I am just going to include the relevant snippet here:

Action exampleAction = actionService.createAction("example-action");
JSONArray dataObj = (JSONArray) content;
for (int i = 0; i < dataObj.length(); i++) {
    JSONObject obj = (JSONObject) dataObj.get(i);
    NodeRef nodeRef = new NodeRef((String) obj.get("nodeRef"));
    if (nodeService.exists(nodeRef)) {
        actionService.executeAction(exampleAction, nodeRef);
    }
}

Alfresco Share handed my client-side JavaScript function an array of node objects which I then post to this web script. So the web script iterates over that array and grabs the node reference string to construct an actual NodeRef object. I use the node service to make sure that node ref actually exists, then I execute the action against it.

Other parts of the web script that I’m not showing here are the web script descriptor, the web script view template, and the Spring bean that injects the node service and action service dependencies into my controller.

Step 4: Test

With everything in place, I’m ready to test. My project was bootstrapped with the Alfresco SDK, version 4.1.0, so it uses Alfresco Community Edition 6.2.0 by default and runs locally using Docker. After running run.sh build_start I can log in to Share, go to a site’s document library, selected multiple objects, and see this in the Selected Items menu (click to enlarge):

Alfresco Share selected items menu showing the custom action

And I can see this in the log:

Log output showing that the action worked

That’s it. Now you know how to add your own custom actions to the Selected Items menu in Alfresco Share.

Alfresco User Interface Options Revisited

Alfresco has been working hard on its new Application Development Framework (ADF), which consists of a client-side JavaScript API and a set of Angular components (see “Alfresco embraces Angular: Now what?“).

Alfresco says the ADF is now ready for production use (as of the 2.0 release) and they’ve also been iterating on an Example Content Application that shows how to use the ADF to build a general document management application.

Many of my clients are watching the ADF closely. Some are dabbling with Proofs-of-Concept, but few have started building their own ADF-based applications. One reason is purely practical–the ADF requires release 5.2 or higher, so an upgrade (or two) stands in the way of production ADF use.

The other reason is more strategic, and it centers around whether or not a customer should expect a content services platform vendor to provide a user interface, and, if so, what kind, or whether that should be the client’s responsibility. This is still being worked through, both internally and externally (see “Future of Alfresco Share Remains Foggy After DevCon“). Alfresco has been very open about their plans and has been gathering input from customers so we’ll see how it plays out.

Customers that require user interface customizations today may feel stuck–extensive Share customizations don’t make sense at this point, ADF requires 5.2, and, even if that’s not the problem, the amount of work required to assemble a solution using the framework and to maintain it going forward may not make sense, especially if what is needed is just vanilla document management with some UI tweaks. (I’m not saying “Don’t use ADF”–I’ve been lobbying for it since 2010. I’m just saying it might not make sense for everyone, for all use cases).

Nine years ago (yikes!) I wrote a post called “Alfresco User Interface: What Are My Options?“. It’s probably time to revise the list. If you need to provide custom functionality on top of Alfresco today, here are your options:

Use the ADF

If you are running 5.2 or higher, clearly, this is what Alfresco would recommend. It ships with components based on Angular, which I’ve been using for a while now and I really like. But, if Angular isn’t an option for you, you can leverage the client-side JavaScript library that is part of the ADF and use React or whatever you want.

And you don’t have to start with a blank app–you can use the Example Content Application as a starting point, if it’s close to what you need, or just as a learning tool if it isn’t.

Advantages:

  • Ready-to-use components save you a lot of work
  • Components and client-side JavaScript API supported by Alfresco
  • Angular is a popular framework, so there should be a lot of developers who can help
  • Client-side JavaScript API lets you use something other than Angular if needed
  • Heavy focus by Alfresco engineering means that new components and features are being added frequently

Considerations:

  • Requires Alfresco 5.2 or higher
  • While the components are extensible, you must stick to the extension points and not customize at the component source code level, unless you want to fork the framework (or at least that component) and maintain it going forward
  • Angular components are styled with Google Material Design which may or may not be aligned with your look-and-feel standards
  • If what you really need is Share with a certain set of customizations, it may be more work to re-build Share-like functionality using ADF components, at least in its current state

Use Your Own Framework

I’ve done several projects with custom, non-ADF Angular components hitting an API layer implemented with Spring Boot. The API layer talks to Alfresco via CMIS, the Alfresco REST API, custom web scripts, or some combination. The API layer also talks to other systems, which is important because these apps are rarely just about Alfresco alone.

I’ve been using Angular but you can obviously use whatever front-end you want. You don’t have to hit an API layer–you can hit Alfresco directly from your client-side JavaScript–the architecture, the tools, and the entire stack is up to you.

The nice thing about this approach is that it works with older versions of Alfresco. And the application only includes exactly what you need to meet end-user requirements. Of course, you have to build all of it yourself and maintain it going forward.

Advantages:

  • Total flexibility in the toolset and architecture
  • Meets your exact requirements

Considerations:

  • Custom code has to be written, debugged, and maintained
  • If you choose an esoteric or short-lived framework, you may be re-writing the application sooner than planned

Use a Commercial Front-end

I’ve seen some very slick commercial front-ends of late. If your main problem is presenting a compelling user interface for finding content, take a look at Alfred Finder from Xenit. It’s got some really impressive features for building and saving queries and a blazing fast user interface. Finder, as the name implies, is read-only. If you need to create content you’ll have to talk to Xenit about a customization or use something different.

For something more specific to case management, take a look at the OpenContent Management Suite from TSG. TSG has removed the hierarchical folder metaphor entirely. Instead, content just goes where it needs to go based on user role, the type of content, and the task at hand. The focus here is on end-user productivity where end-users are most likely case workers, records managers, or similar. (Despite TSG’s proclivity to use “Open” in its branding, this is not an open source solution. You must be a paying TSG consulting customer to use it and to see the source).

If your use case centers around forms, take a look at FormFactor. This isn’t a full replacement front-end like the previous two, but a lot of the customizations people do are really there to support custom data capture, so I’m including it because it might eliminate the need to do any customizations at all. FormFactor allows non-technical end-users to build and publish electronic forms via drag-and-drop, all within the existing Alfresco user interface. The demo I saw was built on top of Share. I’ve asked FormFactor via Twitter whether they will be able to support ADF-based clients as well but have not yet heard back.

Advantages:

  • Commercial add-ons offer shorter time-to-value
  • Maintained by a vendor
  • Functionality leverages the collective feedback of the vendor’s customers

Considerations:

  • May involve up-front license cost and/or annual maintenance fees
  • Commercial products are often shipped as-is, with a close, but not exact, fit to your requirements
  • Support SLA’s can differ widely from vendor-to-vendor
  • Generally speaking, working with your procurement department may not be considered one of the simple joys of life

Customizing Share is Not a Long-Term Option

Despite the announcement that parts of Share are being deprecated and the recommendation for all custom development to use ADF (announcement), I expect the Alfresco Share client to be around for quite a while. The transition to whatever comes after Share is likely to be lengthy and orderly. No timeframe has been announced, but my guess is this will be measured in years, not months.

So if you have a custom action here or there, or you want to remove a few features to streamline a bit, you should do so.  However, if you’ve got major Share renovations in mind, like stripping it down to the studs and knocking out a load-bearing wall or two, you are going to spend a small fortune on what will someday be throwaway work. Instead of doing that, think carefully about using one of the alternative approaches I’ve outlined in this post.

UPDATE: I changed all occurrences of “AngularJS” in this post to “Angular” to make it clear that what Alfresco uses (and what I’ve been using on my own projects) is the newer version of Angular that used to be known as “Angular2” but is now referred to just as “Angular”.

Photo Credit: wireframe, ipad, pencil & notes by Baldiri, CC-BY 2.0

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.

Summary

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:

http://localhost:8080/share/proxy/alfresco/api/internal/shared/share/workspace/SpacesStore/f70e2505-5002-42b7-a71b-2e09aca0c2d0

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:

web-script-index

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:

http://localhost:8080/alfresco/s/script/org/alfresco/repository/quickshare/share.post

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:
org.alfresco.repo.web.scripts.quickshare.ShareContentPost

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!