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.