Tuesday, 11 May 2010

Converting custom JSF 1 components to JSF 2

These are just some observations/tips I made when converting my JSF 1 components to JSF 2.

Simpler .taglib.xml

The taglib definition changes from mycomponent.tld to mycomponent.taglib.xml. The xml inside the new file is similar but with some changes (i.e. <name> becomes <tag-name>). The major simplification is that attributes no longer need to be defined. Just the tag-name and component-type.
And the newly created xml file is referenced as a context-param in web.xml (it could just be located under WEB-INF):
   <description>list of facelet libraries</description>

Component Class

The component class is annotated with: @FacesComponent(value = "value from mycomponent.taglib.xml"). Then for each property create a setter (I also create a getter) that sets the value as evaluated at the apply request values phase. I use an enum as the key to store attributes against.
@FacesComponent(value = "net.devgrok.MenuItem")
public class MenuItem extends UIComponentBase {
 private enum PropertyKeys {
  String toString;

  PropertyKeys(String toString)  {
   this.toString = toString;

  PropertyKeys()  {
 public void setValue(Object value) {
  getStateHelper().put(PropertyKeys.value, value);
 public Object getValue()
  return getStateHelper().get(PropertyKeys.value);

No need for tag handler

As facelets is fully integrated into JSF 2 and it is not driven by JSPs, the need to create a class for every component that extends com.sun.facelets.tag.TagHandler or javax.faces.webapp.UIComponentELTag has been removed. For cases where you need to perform special actions after the values have been populated, create a simple class extending javax.faces.view.facelets.ComponentHandler. There are some instructions here: JSF2 Facelet Tag Handlers.

Some problems

Had some trouble with tag attributes, which I worked around by using the above getter instead of using (String) this.getAttributes().get("name");