With the introduction of JSF-2 along came some feature which were simplified. One such feature is creation of custom JSF components.
Why is it required?
Well one reason for it is that is wrapping up the tag which is complex in itself. To make it more simple to use and user-friendly.
Consider a simple case:
I need to have a marquee component, in which I will just mention the string which will be floated in my HTML and the rest will be done component renderer itself.
How is it done?
So first of all in order to make this work, we need to understand what all files we need to create or update.
(MarqueeComponent.java) First of all we need to extend "javax.faces.component.UIComponentBase", extending this class gives us the methods which are used to translate a tag into its HTML equivalent. Look at the annotation @FacesComponent, using this we declare the component type, which is then used in faces-config.xml for declaring the component.
(faces-config.xml) After extending UIComponentBase class, it was required to communicate to JSF that a custom component is created the configuration for the same is mentioned below in the code snippets.
NOTE: You need to configure component in faces-config.xml, iff @FacesComponent is not being used to register the component. @FacesComponent and <component> tag in faces-config.xml are alternatives of each other. @henk, Thanks for pointing out.
(marquee-taglib.xml) And the next part is to create a taglib for the same so that we can use the tags JSF files. As once taglibs are loaded in web-application then only we can use those tags.
(web.xml - snippet) But still one part is missing, we still haven't mentioned the part where we are supposed to load the taglibs in the web-application. For the same, we need to mention the taglib file in web.xml, under context param javax.faces.FACELETS_LIBRARIES
(sample.xhtml) A sample to demonstrate the custom tag.
Code
Why is it required?
Well one reason for it is that is wrapping up the tag which is complex in itself. To make it more simple to use and user-friendly.
Consider a simple case:
I need to have a marquee component, in which I will just mention the string which will be floated in my HTML and the rest will be done component renderer itself.
How is it done?
So first of all in order to make this work, we need to understand what all files we need to create or update.
(MarqueeComponent.java) First of all we need to extend "javax.faces.component.UIComponentBase", extending this class gives us the methods which are used to translate a tag into its HTML equivalent. Look at the annotation @FacesComponent, using this we declare the component type, which is then used in faces-config.xml for declaring the component.
(faces-config.xml) After extending UIComponentBase class, it was required to communicate to JSF that a custom component is created the configuration for the same is mentioned below in the code snippets.
NOTE: You need to configure component in faces-config.xml, iff @FacesComponent is not being used to register the component. @FacesComponent and <component> tag in faces-config.xml are alternatives of each other. @henk, Thanks for pointing out.
(marquee-taglib.xml) And the next part is to create a taglib for the same so that we can use the tags JSF files. As once taglibs are loaded in web-application then only we can use those tags.
(web.xml - snippet) But still one part is missing, we still haven't mentioned the part where we are supposed to load the taglibs in the web-application. For the same, we need to mention the taglib file in web.xml, under context param javax.faces.FACELETS_LIBRARIES
(sample.xhtml) A sample to demonstrate the custom tag.
Code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<faces-config xmlns="http://java.sun.com/xml/ns/javaee" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee | |
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd" | |
version="2.0"> | |
<!-- Use this iff Annotations (@FacesComponent) is not being used, both serve the same purpose. --> | |
<component> | |
<component-type>com.himanshu.jsf.custom.marquee</component-type> | |
<component-class>com.himanshu.jsf.custom.component.marquee.MarqueeComponent</component-class> | |
</component> | |
</faces-config> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<!DOCTYPE facelet-taglib PUBLIC | |
"-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" | |
"http://java.sun.com/dtd/facelet-taglib_1_0.dtd"> | |
<facelet-taglib> | |
<namespace>http://himanshu/jsf-custom-components/</namespace> | |
<tag> | |
<tag-name>marquee</tag-name> | |
<component> | |
<component-type>com.himanshu.jsf.custom.marquee</component-type> | |
</component> | |
</tag> | |
</facelet-taglib> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.himanshu.jsf.custom.component.marquee; | |
import java.io.IOException; | |
import javax.faces.component.FacesComponent; | |
import javax.faces.component.UIComponentBase; | |
import javax.faces.context.FacesContext; | |
import javax.faces.context.ResponseWriter; | |
@FacesComponent ("com.himanshu.jsf.custom.marquee") | |
public class MarqueeComponent extends UIComponentBase { | |
public static final String COMPONENT_TYPE = "com.himanshu.jsf.custom.marquee"; | |
String value = null; | |
public String getValue() { | |
return value; | |
} | |
@Override | |
public String getFamily() { | |
return COMPONENT_TYPE; | |
} | |
@Override | |
public void encodeBegin(FacesContext context) throws IOException { | |
ResponseWriter writer = context.getResponseWriter(); | |
writer.startElement("marquee", this); | |
writer.write(getValue()); | |
writer.endElement("marquee"); | |
} | |
@Override | |
public void encodeEnd(FacesContext arg0) throws IOException { | |
super.encodeEnd(arg0); | |
} | |
public void setValue(String value) { | |
this.value = value; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<ui:composition xmlns="http://www.w3.org/1999/xhtml" | |
xmlns:h="http://java.sun.com/jsf/html" | |
xmlns:f="http://java.sun.com/jsf/core" | |
xmlns:ui="http://java.sun.com/jsf/facelets" | |
xmlns:customJSF="http://himanshu/jsf-custom-components/"> | |
<f:view> | |
<h:head></h:head> | |
<customJSF:marquee value="HIMANSHU" /> | |
</f:view> | |
</ui:composition> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<context-param> | |
<param-name>javax.faces.FACELETS_LIBRARIES</param-name> | |
<param-value>/WEB-INF/marquee-taglib.xml</param-value> | |
</context-param> |
If you need supporting tools, JSF Components Wizard is for you, check out http://jcw.jsfportal.org
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteno librarry found for name space "http://bla.blaa.." i got this error at facelets page.
ReplyDeleteThanks for tutorial.
ReplyDeleteCan anyone give me example for user define widget using JSF.
Thanks in advance.
I tried your tutorial but in my case, setValue method is never called. So value is always null.
ReplyDeleteWhat is wrong ?
Thanks.