Tuesday, March 19, 2013

Introducing Ganelon - micro-framework supporting AJAX in Clojure/Ring web apps

I've recently published a simple Open Source micro-framework which allows server-side Clojure code to update web page content or invoke any JavaScript operations dynamically through XHR requests and thin JavaScript layer. 

Ganelon is fully Ring compatible and based on Compojure and lib-noir. Being a AJAX focused, it is not a direct replacement for Noir. It can rather ease the pain of handling dynamic page requests in any Ring-based web application.

The execution model is heavily influenced by Weblocks or Vaadin, but without session-statefulness and out-of-the-box rich user interface:

  • Certain parts of the page can be scoped as Widgets (for example using id attribute in HTML or ganelon.web.widgets.with-div utility macro) and referenced by id in Actions, and updated by Operations. Widgets can reference Actions to be invoked.
  • Actions are invoked as XHR requests and return a set of Operations to be performed client-side. Actions are in fact simple Ring handlers.
  • Operations provide abstraction layer over client-side JavaScript execution - e.g. using Bootstrap Modal or just updating part of DOM tree (a Widget or any other) or open certain URL in a browser window - or just anything else that has a simple integration layer provided.

The source codes are on GitHub: http://github.com/tlipski/ganelon and demo site and documentation is available at http://ganelon.tomeklipski.com.

Sample code (a shoutbox) is listed below:

;A Widget, returning HTML code:
(defn box-widget []
 (widgets/with-div
   [:p "Call count (since restart): " [:b @COUNTER] ". Last 4 entries:"]
   (for [entry @ENTRIES]
     [:div.hibox [:b (:time entry)] ": "
      (hiccup.util/escape-html (:msg entry))])
   (widgets/action-form "say-hi" {} {:class "form-inline"}
     [:input {:name "msg" :placeholder "Say hi!" :type "text"
              :maxlength "20" :size "20"}] " "
     [:button {:class "btn btn-primary"} "Send!"])))

;An Action, performing side effects and returning part of the page to be updated
(actions/defwidgetaction "say-hi" [msg]
 (swap! COUNTER inc)
 (swap! ENTRIES #(util/smart-subvec (flatten [(mkmsg msg) %]) 0 4))
 (box-widget))

JavaScript code uses jQuery and optionally Bootstrap, but the implementation is really trivial and therefore easy to replace using your favorite JS library.

Monday, March 18, 2013

Porting Activiti Explorer to Liferay Portal

In the following blog post,  I have highlighted the matter of embedding Activiti BPMS inside a Liferay Portal. With Activiti Explorer built in Vaadin and Spring, it is fairly easy to use entire  components in a totally different environment. 

Proof of concept fork with Tasks and Admin portlets is available in 
https://github.com/tlipski/Activiti/tree/master/modules/activiti-portlets.

Porting Activiti Explorer to Liferay Portal

Activiti is a popular Open Source, BPMN2.0-compliant BPMS that provides a great overall package. Not only there is a library that can be embedded inside your application, but Activiti also comes with an Explorer web application, which provides an ergonomic user interface for basic operations:



But, Activiti is "just" a BPMS - you can run your processes with it, maybe even connect to Active Directory, Alfresco or ESB - but if you want to embed it in your intranet/extranet portal, you are almost on your own. 

Please note, that embedding Activiti in portal is not the same as using it to manage portal assets - for example, as a replacement for Liferay's Kaleo Workflow. The matter discussed here is more focused on using all of Activiti features, including user interface.

Luckily, this is when frameworks used in Activiti pay off - Activiti Explorer is written in Vaadin 6 and Spring. With component oriented approach from Spring and UI modularity encouraged by Vaadin, it is fairly easy to port this application to Liferay. We can extract entire components from Activiti Explorer (e.g. Tasks panel) and use them in a whole new environment.
Extracting and re-using entire components requires much more work in a classical MVC approach and even may not always be possible. Also, portlet support in Vaadin makes a whole task much more pleasant.

For the impatient: The code is available in my fork of Activiti 5.13-SNAPSHOT: http://github.com/tlipski/Activiti, especially in activiti-portlets module https://github.com/tlipski/Activiti/tree/master/modules/activiti-portlets.

Necessary steps

"Fairly easy" does not mean without any effort. There are differences between a standard Vaadin application and a portletized one:
  • Portlet descriptors are necessary
  • GUI should be divided into separate portlets
  • Spring-Vaadin integration is different due to a portal-specific request life-cycle
  • Navigation can be provided by portal - including friendly URLs, which makes for a more standard user experience.
In addition to that, some mechanisms used by Activiti are already provided by Liferay Portal and we need to bridge them:
  • Users and Groups should be managed by Liferay Portal
  • Authentication data should be taken from a portlet container
  • Mail notifications could possibly use Liferay Mail API
Some other things have to be taken into account as well:
  • Distribution and management of Vaadin widgetset and version - we should use Vaadin Control Panel portlet and Liferay to manage Vaadin dependencies. This requires special handling, since Activiti Explorer 5.13 utilizes dCharts Vaadin Add-on.
  • Vaadin theme used in portlets - which is also customized by Activiti, but should be coherent with portal's look & feel.

Current state of work

It is nice to theorize, but certain things need to be verified in practice. At this moment, my fork at http://github.com/tlipski/Activiti provides:
  • Activiti Tasks portlet, which works in a user's context as if the user would log in to Activiti Explorer app. The portlet provides full functionality, including operations as starting a new task, fetching it from a task list, displaying task's events, assignment/ownership transfers, file attachments and so on.
  • Activiti Admin portlet in Liferay Control Panel - most tabs seem to work fine - except Users and Groups, which should be disabled as we are using Liferay Portal to do that.




Implementation details:

On the implementation side, most noteworthy changes which have been implemented in activiti-portlets module: https://github.com/tlipski/Activiti/tree/master/modules/activiti-portlets are:
  • IdentityProvider implementation utilizing Liferay API (need to work on user photos though!)
  • Spring-Vaadin bridging for portal (see my previous post).
  • Custom portlet applications and main Window class. The interesting detail here is that with Vaadin portlets, you should not set width of components to 100%, as it will result in 0px height. Generally speaking, the height in Vaadin portlet components should be set to undefined - null, or a preset value in pixels.

Next steps?

Connecting Liferay with Activiti brings a myriad of new possibilities, but before that, some basic things need to be done:
  • More portlets! Reporting and Processes tabs need their respective portlets, but also "start process" portlet might be worth considering since we can manage UI contents in a more flexible way.
  • More testing! If anyone is interested in testing Activiti portlets in Liferay, let me know and I will provide prebuilt applications. So far, I've used Liferay 6.1 GA2 CE and H2 in-memory database for Activiti.
  • Friendly urls - especially for tasks resolved by id, and for interportlet communication - e.g. when starting a process.