November 12, 2010 by huionn
Most of my time in this week is being used to develop a functional prototype of web-based form builder with JSF. This is one of the new requirements for the new platform.
I get some initial ideas from JotForm. It has very nice user interface which I try to imitate.
After some exploration, it turns out that the WYSIWYG UI of form builder is not hard to develop with RichFaces.
- drag and drop support for input components
- inline editing for label
- modal dialog for input component properties
- context menu for delete, shrink and expand the columns
After I complete the UI part, there is another problem to solve: how to display the generated form?
Unlike JSP, the lifecycle of JSF requires that the components tree to be built before rendering the view. This means the components cannot be generated on runtime.
Although the solution in http://confluence.highsource.org/display/~lexi/Programmatic+usage+of+Facelets is not applicable for my use case, it provides very informative explanation for advanced topic in facelets.
After eliminating possibility of runtime component rendering, I still have another option – rendering the facelets when user saves/updates the form. It turns out to be a simple task. The facelets xhtml can be easily generated with FreeMarker. FreeMarker is a Java template engine to generate text output. seam-gen uses it to generate the codes and views.
After I developed and integrated everything, I thought facelets can pick up newly generated xhtml on the fly. Unfortunately, it is not that straightforward. My application code cannot write to deployed folder returned by ServletContext.getRealPath(). So, I have to use a CustomResourceResolver as explained in http://seamframework.org/Documentation/HowDoILoadAFaceletsViewTemplateFromASharedJAR. I map a virtual path in request URL to a specific directory (configurable in database).
Everything should be working now – I can drag and drop input components into a form builder template, save the form and then view the rendered JSF form.
Nevertheless, I still have to look into the potential performance issue and concurrent issue. In addition, I also need to figure out how to handle versioning – especially there are conflicting changes.