$ thought | blog

Place to serialize my thoughts…

Archive for the ‘Programming’ Category

Things to ponder with Alfresco (Part-II: Workflow Design)

with 2 comments

Complex Workflow Designs  

Complex Workflow Designs

As I mentioned in my earlier post that I will be writing few more posts about the Alfresco. This is second installment in the series. If you are thinking to use Alfresco at the center of your application then it is hard that it will not have a workflow. If your business process is just more than simple workflows mentioned in Alfresco, then for sure you have to write your own business model definition.

If you are planning to do so, here are few lessons I have learned –

  • Simplicity – We got lot of benefits just by keeping our process definition simple and neat. Don’t add unnecessary steps which will cause confusing steps for the end users.
  • Right things at right place – Alfresco is very flexible in terms of business logic implementation. You will always have multiple options to accomplish same operation. Web Scripts, Java classes or Web Service and you will be tempted to use different things at times. Decide one approach and stick to it. Put as much as logic in the workflow and don’t spread across the workflow business logic outside the workflow.
  • Loops can be evil – Loops in the workflow actions can be daunting at times. Rethink on the circular steps in the workflow and make sure you are not violating the “simplicity” rule. It might be difficult sometimes to achieve these steps.
  • Blocking is good sometimes – Next bigger decision should be synchronous operations or asynchronous. All the operations which might result in inconsistent states should be synchronous i.e. transactional. Asynchronous operations are better in terms of responsiveness. Sending e-mails could be asynchronous tasks as you people can receive emails after couple of seconds, but if it is related to pushing records to a queue, let it be synchronous. You got the idea!

You are advised to check Alfresco wiki for more details. There is plenty of documentation available for the administration and authoring custom workflows.

Written by Sachin

September 21st, 2008 at 5:17 pm

Posted in Developer, Java, Programming

Things to ponder with Alfresco (Part-I: Content Model)

without comments

For any content repository, content model definition is similar to the DDL (schema definition) for databases. It is expected in a big application to have evolutionary content model like databases. Updating the table structures or introducing new tables is common in any business application. In content repository, you should also keep in mind that your content model should be open to evolve. Define the content model which will be extensible. Most of the good practices of database design should be applicable here.

Few tips for better content models -

  • Use aspects for specializing types instead of defining content types. There are few advantages of that, aspects can be applied or removed at run-time which gives you much more control over the dynamic nature of types.
  • Aspects also helps in keeping the default set of properties over a content type to be small. Alfresco recommends you to prefer aspects over custom content types.
  • Aspects helps you to logically group properties. This helps your data to be part of multiple groups at the same time. If you have aspects Publishable and Indexable; you can apply or revoke a nature at your will without much hassle.
  • Indexing is very helpful for searchable content. It is useful but use it wisely. The cost of indexing in Alfresco is much higher than cost of index in Databases as this will be full-text search indexes. It will take up more disk space as well as time to index the data. Don't index the content which people are not expect to search! You can define this at the time of content model definition.
  • Versioning is similar to indexing and use this wisely. The content which is versionable is handled separately by Alfresco. This might be affecting performance as your repository size grows. Don't mark content as versionable if you don't plan to maintain revisions for content.

I will continue this series with other experiences with Alfresco. Later.

Written by Sachin

September 13th, 2008 at 11:51 pm

Alfresco: Workflow managed by JavaScript

with 4 comments

If you are a regular reader of this blog, you might have figured out that I am currently working on a project involving alfresco at the center and it's a content management system. Earlier I have worked with Content repository (Apache Jackrabbit) and that was a good experience. Alfresco is next step of a content repository which extends it into a full blown content management system and much more. I was working on a problem where we defined a custom (Advanced workflow) to be precise in Alfresco lingo. This workflow was needed to be monitored, managed and accessed only via a webscript as we have used webscripts to do almost everything in our project. I was very pleased to see this, but that is only available in 2.9 labs release (as of now). We are using alfresco 2.2.0 version for our development and that is production stable version, so I have very little choice but go with production version. Alfresco has very limited JavaScript API support for workflow manipulation and that was difficult job for manage. There was no other option than writing custom JavaScript API which allows to manage workflow in Alfresco. We did that and it was very powerful and easy! :) I wanted following features for JavaScript API -

  • Easy to extend
  • Can handle any workflows
  • Provides easy ways to retrieve tasks, definitions, paths etc.
  • Provides as much functionality possible which is available in Alfresco Workflow Console.

Alfresco workflow console is command line interaction component which allows you to manipulate, get information about workflows using simple commands and I wanted to do all that using JavaScript. I started exploring the source code and found a class 'org.alfresco.service.cmr.workflow.WorkflowService'. This class has generic API which allows you to do all the operations possible through workflow console. This bean is used for workflow console operations. So all I needed was expose this bean in JavaScript as root object and start using it. That simple! I wrote a simple java class to expose the bean as follows:

package com.xxxx.yyyy.workflow;
 
import java.util.List;
 
import org.alfresco.repo.processor.BaseProcessorExtension;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.workflow.WorkflowService;
 
public class WorkflowManager extends BaseProcessorExtension {
	private ServiceRegistry services;
 
	public void setServiceRegistry(ServiceRegistry serviceRegistry) {
		this.services = serviceRegistry;
	}
 
	public WorkflowService getWorkflowService(){
		return services.getWorkflowService();
	}
}

The method getWorkflowService() exposes the workflow service to the JavaScript calls. To expose the Workflow Manager as root object in JavaScript create WEB-INF/classes/alfresco/extension/custom-script-context.xml and you will be good! (If you don't know how to do that, read this) Now, you can get the handle of workflow service in JavaScript code. Yet, we need to write a small component which will allow us to retrieve the active workflows, tasks etc. To do so, I wrote a small JavaScript object which provides those functionality to the user.

var workflowService = workflow.getWorkflowService();
 
var W = {
	transitions: function(noderef){
		var task = W._currentTask(noderef);
		var trans = [];
		try{
		var tasks = task && task.path.node.transitions;
		for(var index=0; index < tasks.length; index++){
			trans[trans.length] = tasks[index].id;
		}
		}catch(error){
			// Ignore error
		}
		return trans;
	},
 
	move: function(noderef, command){
		workflowService.endTask(W._currentTask(noderef).id
                , command);
	},
 
	_workflowPath: function(noderef){
		var workFlows = workflow.getWorkflows
                      ("workspace://SpacesStore/" + noderef, true);
		if(workFlows.size()>0){
			return workFlows.get(0).id + "-@";
		}
		return "";
	},
 
	_currentTask: function(noderef){
		var curTask;
		var tasks;
		try{
		tasks = workflowService.getTasksForWorkflowPath
                           (W._workflowPath(noderef));
		if(tasks.size() > 0)
		      curTask = tasks.get(0);
		} catch(Error){
			// Ignore error
		}
		return curTask;
	}
}
 
function initWorkflow(noderef)
{
	var wflow = actions.create("start-workflow");
	wflow.parameters.workflowName
             = "jbpm$xxxxyyyy:abc"; // your workflow name
	wflow.parameters["bpm:assignee"]
             = person.properties.userName;
	wflow.parameters["bpm:workflowDescription"]
             = "Put your description";
	wflow.execute(noderef_for_which_workflow_will_associate);
}

Thats it! The initiate workflow method is used to apply a workflow to a node. Once that is done, the W object can be used to do operations like retrieving the active tasks, ending the workflow and making the workflow transition. Hope that helps. If you need more workflow related information and reading material you can visit following places:

  • JBPM jPDL Documentation (here)
  • Alfresco workflow wiki (here)
  • ECMArchitect Advance Workflow Guide (here)

Written by Sachin

May 29th, 2008 at 10:35 am

Guarding in JavaScript

with 7 comments

After looking at JavaScript programming sessions by Douglas Crockford (here), I couldn't stop but admire JavaScript. There are many many impressive things in JavaScript but one of the eye-catchy thing was guarding operator in JavaScript.

The && operator in JavaScript can be acted in two ways. The normal 'and' operator which is used in determining the conditional logic results. The other lesser known feature of JavaScript is the guard operator. In following code -

 
/* The if is checking if specs is not undefined, false, null,
"" (empty string) or 0 (numeric zero) as these all values
are falsy conditions in JavaScript */
 
if(specs)
     width = specs.width;
 
// To avoid the if condition you can simply do like -
 
width = specs && specs.width;
 
/* This makes sure that specs is not falsy and they
returns the second operand which is convenient
way to write null check */
 

The same is with || operator too. If the first operand is falsy then it just returns the second operand instead. Consider following code:

 
name = specs.name || "Name not set";
/* Use the specs.name, but if name doesn't have a value, use default
value instead. */
 

Very simple and very efficient!

Written by Sachin

April 25th, 2008 at 8:04 am

Posted in Developer, Programming

Alfresco: Server side JavaScript, anyone interested?

with 3 comments

I started with Alfresco and its amazing software suite. For people, who don't know about content repositories, in short its hierarchical, versionable storage (read more). Alfresco is one step ahead of other content repository implementations and it is full content management suite. This means, you have workflow, content repository and a portal which allows you to do lot of standard things e.g. communicating with external world via API, portal, security/authentication etc. From my perspective Alfresco is really great product considering the amount of features it provides and the quality of them.

I am working on a project which involves some bit of alfresco customization to meet the customer needs. This involves configuring alfresco for Windows SSO, allowing users to map their home space in alfresco as network share, knitting a workflow tightly integrated with their business process and writing some dynamic content generation code for reporting, user interaction and for auditing purpose. We could do most of the things straight away and we are quite happy with kind of response alfresco was giving. Everything is clean and configurable. Basically alfresco is built using spring framework; so you can configure custom beans or extend existing beans very easily via some xml files. There are tons of different services and pre-configured beans which might be little overwhelming for the beginners but, as you started to get familiar it doesn't feel so bad.

We were at a point where we wanted to write some server side logic to create a dynamic (web 2.0) UI which has lot of interaction based on data queries with content repository. So we needed easy approach to query repository, minimal xml configuration, ability to change / update logic easily, faster development cycle to start with. Alfresco provides lot of options to communicate to repository -

  • Java API (most raw access to the repository, repository instance is singleton so that will be injected as dependency via spring configuration)
  • Web Service - Very standard SOAP and XML RPC based communication
  • RMI - Java RMI which is another standard method looks similar to Web Services
  • RESTful JavaScript API :)

I was excited by last option the most. I thought, lets explore the last one as first three were mundane and I knew what are the pros-cons of most of them. Alfresco provides a clean MVC around content repository and other parts of Alfresco (viz. workflow, user homes and some root objects) where controller is a pre-configured servlet, model is JavaScript code and view is a freemarker template. The beauty of the system is lying in the simplicity of JavavScript code.

Alfresco provides a nice feature rich JavaScript API (more here) where some of the objects are injected from scripting engine as root objects. These object provides the building blocks for JavaScript API e.g. search, user home, workflows etc. You can write your own Java services and inject them as root object using simple configuration to extend this foundation. Once your basic services are in place, then you can start knitting or wiring your business logic using these foundation blocks. JavaScript is an ideal choice as it expects small, working code instead of heavy logic which Java can handle. With small fluff of code you will be looking at some fantastic results.

I was amazed and surprised by the simplicity but there are few things which I needed to finalize before I decided to make a choice -

  • Performance - JavaScript is interpreted in Alfresco using Rhino which is high performance engine by Mozilla. So, no worries about performance. I have evaluated Rhino some time back and that was really great in performance.
  • Testability - That was major concern. Unit testing with JavaScript was not easy. Crosscheck is a good choice to begin with. There are other options like JsUnit and some browser based frameworks which are not that popular.
  • Debugging - Alfresco provides a very nice JavaScript debugger where you have luxury of an IDE. Its launched from browser (firefox, IE) and works with ease. Standard debugger features like breakpoints, watches and navigation control are provided.
  • Ease of deployment - Most of the scripts are convention based (naming conventions, location conventions etc) and very standard. Server can identify updated scripts and no server restart required (in development environment thats a needed feature)
  • Ability to talk to Java logic - If you want to use a external third-party library from JavaScript, no problem! JavaScript code can use API which are written in Java and work with them with ease. You can even write your heavy-weight business logic components in Java and inject that as service to reduce time and achieve code-reuse.

After all concerns are addressed, I was pretty sure I will be writing most of my business logic code and writing the services in JavaScript. I haven't stressed much in this post on view as its pretty standard freemarker template engine. I would like to touch upon that later.

If you are considering the Alfresco and writing your business logic in JavaScript (called as Web Scripts in Alfresco) then I would seriously recommend following things for reading/viewing -

  • Douglas Crockford — "The JavaScript Programming Language" series of videos (found here)
  • Alfresco Developer series - For basic hands-on tutorials for Alfresco customization and understanding (found here)

Have a great time functional programming! :)

Written by Sachin

April 22nd, 2008 at 8:35 am

Posted in Developer, Java, Programming