Charts in JSF: OpenFaces, PrimeFaces and JSFLot

I’ve been playing around with a small application that needs to display results of data collection in a chart as a certain selection is made on the jsf page. So I set myself the task of looking around for libraries that could provide me this charting support. One of the important considerations was that this library had to be compatible with Richfaces, since that was my default jsf library until further notice. It was a pity though that Richfaces didn’t have one, because most of their components seem to be fully fleshed, and I don’t tend to need other components libraries unless they don’t have it.

Primefaces

I’d already heard and read about Primefaces, and the reviews were quite positive. It comes with quite an impressive set of components, and will definitely fill in the holes that Richfaces has left quite nicely, with all the cool items like Accordions, Carousels, Docks (for MacOS fans), an IdleMonitor, ImageCropper and the rest. The documentation was also quite detailed from PDF and html docs as well from forums, so I was bound to have a good time, or so I hoped. I “mavened” it and configured it alongside Richfaces, without any complaint. So, to the hacking went on. The chart components were quite may and as cool as Primefaces always tends to be, and it’s model was quite easy to work with. All I needed was to create a Map<String,Integer> containing text and data points for a pie chart. For my needs, which is a bar char, all that was needed was something like the ff from their own documentation:

public class BirthDisplayBean {

private List<Birth> births;

public ChartBean() {

births = new ArrayList<Birth>();

births.add(new Birth(2004, 120, 52));

births.add(new Birth(2005, 100, 60));

births.add(new Birth(2006, 44, 110));

births.add(new Birth(2007, 150, 135));

births.add(new Birth(2008, 125, 120));

}

public List<Birth> getBirths() {

return births;

}

}

and then on the page

<p:lineChart value="#{chartBean.births}" var="birth" xfield="#{birth.year}">

<p:chartSeries label="Boys" value="#{birth.boys}" />

<p:chartSeries label="Girls" value="#{birth.girls}" />

</p:lineChart>

Sweet! Simply using my own model and basic collections, I had my data all ready to go.

Just when I was getting ready to enjoy splattering my pages with charts all over, I came across a problem. The number of points on which data is collected in my application is flexible, therefore I do not know before hand the number of “series” that I have to display. Unfortunately, Primefaces assumes that I know them before hand, in which case all I needed was to specify each p:chartSeries with label and value. Oops, spanner in the works!! I tried to use a ui:repeat to force it to render a dynamic number of p:chartSeries, but that didn’t work. So, my honeymoon with Primefaces charts was ended abruptly. But Primefaces is still in my web application classpath, waiting for the next interesting component I might think of using which Richfaces does not have. I suspect that will definitely be sooner than later. Primefaces is way too cool to ignore.

JSFLot

My next search threw up an interesting result: JSFLot. It’s quite an interesting libray only focusing on charting, and relying mostly on JavaScript to render the chart and it’s content. It has support for pie, bar, and line charts, which would meet most application needs. It seemed not to have as yet a big community around it like the others, but it’s documentation was good enough to focus on what it does best – charting. I only wished there was a downloadable version of the documentation, so I could take my time with it at home when I’m offline. In the end I had to use Scrapbook to grab a few pages, but that was good enough. It indeed has a very small footprint, with a jar around 245k. It had it’s own datamodel that you had to stuff your results to display in, so in that sense it is intrusive on your codebase. However they are quite simple and intuitive. They are XYDataPoint (for x and y data points) , XYDataList (for a series of x and y data points, as well as other information concerning the series) and XYDataSetCollection (an aggregation of 1 or more series or XYDataLists). But nowadays, what other JSF component library doesn’t call for some small intrusion to get you going?

I began digging into it, and was getting some interesting results. The charts were quite clean and easy to label. But when I wanted to be a bit more dynamic and display different charts based on different selections from a Seam DataModelSelection, I noticed that it didn’t seem to refresh to show the changing data points from the different objects from which the data points were being displayed. I thought maybe it had to work only with full page refreshes, so I resorted to using the normal <h:commandLink/> to make sure that the whole page was refreshing and not doing any funky Richfaces ajax thingy. But no go. Seeing as I was spending too much time trying out all my Seam hacking skills, I rather decided to focus my energies on finding a different library that could fulfil my needs. Maybe I was being dumb and making some mistake somewhere, but time wasn’t on my side.

OpenFaces

Having had two heartbreaks, I went back to looking for a new JSF library love that could fulfil my need for dynamic series data, and interestingly 2 weeks ago TheServerSide had an article about OpenFaces. Hmm, not heard of them; let’s see what they’ve got. It turns out that they weren’t that bad after all. Documentation was in an html which comes bundled with the library download, and contains everything you need to know to use it. They had quite a sweet implementation of DataTable, and their implementation of sorting via headers of the columns was far cleaner and more “pimped up” than Richfaces Datatable, so I’ve switched my pages to use theirs, and I’m loving it. They also have a TreeTable, a cool way of using a table to display hierarchical structures, and a DayTable for showing scheduled events. All this and it sat quite well with Seam and Richfaces.

Here they had support for pie, bar and line charts, which though less than Primefaces’s plethora of charts, is more than enough for most purposes. Oh by the way, they could do dynamic series data quite well. All would have been rosy, except for the fact that I have to use their model to squeeze my data in. Well, it involved using 2 of OpenFaces model classes to contain my data, and coming from JSFLot’s 3 and from all the disappointments, I definitely could live with that. So like Primefaces, I could define my data points in a Map<String,Integer> structure, but unlike it, I’d put them in a PlainSeries, and then put all my PlainSeries in a PlainModel. Job done, we can all go have a beer now.

But then what will software development be like if you had technologies which thought of the developer’s every need and did them even before he could think he needed them? That will be utopia, but then I’m still on this earth. I realised that I couldn’t specify a color per data element, again because the number of data points I have to display is dynamic. I tried to use a property that will generate a random comma separated list of colours for each data point as a string property , but the tag could not resolve EL when it came to reading the “colors” property. In the end I had to hard code one colour for every element to save me from disgrace.

<o:barChartView labelsVisible="true" valueAxisLabel="No. of respondents" keyAxisLabel="Responses" colors="#800000"/>.

In fact, neither could the valueAxisLabel and the keyAxisLabel read from my locale files to determine the right text to show there. Who in this day and age still hard codes labels, when there is something call internationalization? OpenFaces, sit up!!! This is JSF, and here EL is king, not hardcoded text values.

In the meantime, I don’t have a choice. At least OpenFaces meets the real important requirement of showing charts from content which is dynamic and ajax driven. I hope OpenFaces will wake up and realise that their new lover requires some additional pampering, but I guess for now the relationship seems to be working. Who knows, if they do get better at the EL stuff, I just might actually consider moving from a relationship to a marriage.

One thing I’ve taken away from the experience though – JSF has come a long way, for me to be able to have Richfaces, Primefaces and OpenFaces in one application. And my application is not even JSF 2, where the vendors are supposed to have worked on better integration paths for the component libraries. I’m waiting for Seam 3 to be fully released, and then I’ll switch everything to CDI, JPA2 and JSF2 without sacrificing any of my PDFing, Excel-ling, SMPCing (Managed Persistence Context) and the like.