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 frommycomponent.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.<tag> <name>menuItem</name> <tag-class>net.devgrok.component.MenuItemTag</tag-class> <body-content>JSP</body-content> <attribute> <name>value</name> <required>false</required> <deferred-value> <type>java.lang.String</type> </deferred-value> </attribute> </tag>Becomes:
<tag> <tag-name>menuItem</tag-name> <component> <component-type>net.devgrok.MenuItem</component-type> </component> </tag>And the newly created xml file is referenced as a context-param in web.xml (it could just be located under WEB-INF):
<context-param> <description>list of facelet libraries</description> <param-name>javax.faces.FACELETS_LIBRARIES</param-name> <param-value>/WEB-INF/classes/META-INF/custom.taglib.xml</param-value> </context-param>
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 {
value;
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 extendscom.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");
Nice, Christopher!
ReplyDeleteBut I have some questions..
Where are defined the prefix for the component?
.tld file continues?
Thanks
@David
ReplyDeleteQ1:-the prefix of component is defined in .xhtml page where you use your component.
like xmlns:prefix="namespace"
Here namespace value should be the same that you mentioned in the taglib.xml file
Q2:- .tld file not required.you have to create taglib.xml file and give its reference in web.xml as suggested by christoper.