Archive for the ‘Java’ Category
Things to ponder with Alfresco (Part-II: Workflow Design)
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.
Alfresco: Workflow managed by JavaScript
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:
Alfresco: Server side JavaScript, anyone interested?
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 -
Java: static and transient keywords
I came across transient keyword and wanted to get few more details about it. This is one of the most ignored or rarely used keyword by me. It is really funny but, I never really used this keyword extensively. The main reason is, this keyword has a very specific use and most of the applications don't need that for building the business applications. As per info here, when any object state is getting serialized, static and transient variables will be ignored for serialization. Still, Java compiler doesn't give any warning or prohibit from making a variable static and transient at the same time. I don't think this as error but a warning should make more sense in this case.
Java on Multicore: Is definately good!
This is another new discussion topic in Java circle. To get the background for this post you would like this good article. This post has some great comments so don't miss that either. Followed by this and this article. There are different opinions about the topic. I studied Parallel computing & architecture as my graduate studies. So I would like to poke my nose in this topic.
This discussion is circling around GC threads and JavaEE threading model. Although experienced bloggers have already touch length and breadth of the topic, I would like to express my view in this regard. Operating system designers and architects thought a lot about Uniprocessor and Multiprocessor execution methods. There is huge literature present on these topics on public sources. But multicore techniques are relatively new.
Java scales very well on multi-processor servers from long time. Since multi-core is similar to multiprocessor in great sense, there should be increase in performance. Although as Billy mentioned there is GC bottleneck but, that is something can be worked out through JVM only. If JVM can utilize different processor for GC then why not different core?
In addition to that, there are very sophisticated parallel computing algorithms and utilities which may increase the performance by re-writing the existing application or designing new applications to work better on multi-core architectures.
This problem can be worked out and not impossible. If Java is having problem so do all the other monolithic applications which were designed by keeping in mind uniprocessor / unicore architectures.
And there is always option to use libraries like Pervasive Datarush and Javolution to increase application performance without bothering about details of architectures


