Tuesday, 26 August 2008

Icefaces, After years of usage


I've been tempted into creating a blog entry about Icefaces (www.icefaces.org) for some clothing reason :)

Here's my story with IceFaces, I'm working for a small developement company and for a long time I was the sole java developer so I was doing design, architecture, developement, build management of all our java applications. Around december 2006 I was assigned the task (by me) of finding better JSF component for our web applications because I was getting tired of debugging javascript when It was time to modify of create a new AJAX component. Back then I was doing javascript to communicate with my custom servlets on my web container, that how I was doing AJAX with my JSF web applications. At the time, that's the best I could do with the resources I had (i.e me) It wasn't secure, it wasn't error proof but it was working.

So I looked at a few component library back then (ajax4jsf, Google widget etc..) and I found IceFaces, I started playing with it and I liked the simplicity of it and it was well documented.
At the time it was the 1.5.0 version. That was back in december 2006, during the christmas holiday I started a personal project that would be using the new functionallity of IceFaces I needed to test for my work applications. I got familiar with the Ajax Push, Drag n Drop and the partial submit, events and all other components IceFaces is offering.

When I went back to work in January I showed my boss the personal application I made during the holiday and right away he agreed with me, we would be converting our web applications to IceFaces.

So a long process started mostly because I was the only developer on the project, with sometimes help from the HTML designer that was working on CSS for the web applications. I was doing in 1 days using IceFaces components it was taking me a week to developed before. After a few weeks the application was fully converted and I was adding nice features to it that would have been unthinkable before IceFaces.

I guess we did a good job since IceFaces decided to showcase our application on their site : Mobile Application Demo

So now that the story is told, Today I wanted to share some usage tip I've been using along with IceFaces and Facelets.

In our applications in many screen we have a Vehicle Selector, This vehicle selector is a test input field where the user enter the name of the Vehicle, using IceFaces this field became a SelectInputText where some values are suggested to the user when entering the vehicle name. With a few thousands vehicle entry in the database the suggestion really helps the user to select the correct vehicle.

The implementation I did with this component is that I had a JSF managed bean behind the IceFaces's selectInputText component to feed the suggestion values and all that wrapped into a Facelets custom component to have it reused in many other screen of our application.

But now I was facong the problem on how I would notify other managed beans that a vehicle selection was made. and here's what I did and how I do now for many selection component in our applications.

First of all I create and Interface VehicleSelectionListener :

public interface VehicleSelectionListener {

public void vehicleSelected(VehicleDTO aVehicleDTO);


The manage beans that needs to be notify will implement this interface.

I then define the Icefaces SelectInputText with my added attribute like this:
<ice:selectInputText listVar="vehicle" listValue="#{myVehicleSuggest.vehicleSuggestionList}" partialSubmit="true" actionListener="#{myVehicleSuggest.vehicleSelected}" valueChangeListener="#{myVehicleSuggest.vehicleInputChanged}" vehicleSelectionListener="#{myOtherBackingBean}">

<f:facet name="selectInputText">
<ice:panelGrid columns="2">
<ice:outputText value="#{vehicle.name}" />
<ice:outputText value="#{vehicle.carrierLabel}" />


Now inside the VehicleSuggest BackingBean I do this to get the right instance of my OtherBackingBean interested in VehicleSelection:
public void vehicleInputChanged(ValueChangeEvent aValueChangeEvent) {
SelectInputText selectComponent = (SelectInputText)aValueChangeEvent.getComponent();
VehicleSelectionListener selectionListener = selectComponent .getAttributes().get("vehicleSelectionListener");
// get suggestionList
// if only 1 suggestion available make it as selected
// notify the selection listener that the vehicle was selected

Also have the actionListener method mapped for when the user select a vehicle from the suggestion list :
public void vehicleSelected(ActionEvent anActionEvent) {
SelectInputText selectComponent = (SelectInputText)aValueChangeEvent.getComponent();
VehicleSelectionListener selectionListener = selectComponent .getAttributes().get("vehicleSelectionListener");
// notify the selection listener that the vehicle was selected

And this is how we have clean code that in the web application layer can reuse "Suggestion Components". It can apply to any BackingBean that implements the interface and that Backing Bean must be defined as an extra attribute on the IceFaces component.

Hope it helps someone out there.

Long live IceFaces