This is the second tutorial about creating JSF custom tags. In this one we will show how to create Java based JSF custom tags.
Creating a custom Java based JSF tag in the early JSF 1.2 specification required pretty a lot of work and several configuration files to be handled. We will now show how simpler is now with the JSF 2.1 specifications and how (even!) simpler is with the JSF 2.2 specifications.
Creating a JSF 2.1 compliant (Java based) custom tag requires just three simple steps:
Step # 1 Define your Java class extending the UIComponentBase which renders your tag:
package com.sample; import java.io.IOException; import java.util.Hashtable; import javax.faces.component.FacesComponent; import javax.faces.component.UIComponentBase; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; @FacesComponent(value = "dictionary") public class TranslatorComponent extends UIComponentBase { Hashtable dictionary = new Hashtable(); @Override public String getFamily() { return "translatorComponent"; } public TranslatorComponent() { dictionary.put("dog", "cane"); dictionary.put("cat", "gatto"); dictionary.put("mouse", "topo"); } @Override public void encodeBegin(FacesContext context) throws IOException { String value = (String) getAttributes().get("value"); if (value != null) { ResponseWriter writer = context.getResponseWriter(); Object translation = dictionary.get(value); if (translation == null) { writer.write("Sorry word not found!"); } else { writer.write((String)translation); } } } }
The above tag can be used to translate some words from one dictionary into another (in our example some words from English to Italian).
Two things to notice:
The @FacesComponent(value = “dictionary”) which can be used to declare the Java class as Faces Component (instead of declaring it into a TLD configuration file)
Next, Since our component only displays a message, and the tag doesn’t contain any children, we only need to override the encodeBegin method, which renders the tag.
For advanced components, which have a body, we should have three overridden methods:
- encodeBegin: This starts the element for the root component
- encodeChildren: This would cause all of the children to be encoded
- encodeEnd: This closes the element
Step #2 Define your tag within a tag lib file:
Add the following custom.taglib.xml to your WEB-INF folder:
<facelet-taglib 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-facelettaglibrary_2_0.xsd" version="2.0"> <namespace>https://www.mastertheboss.com/custom-taglib</namespace> <tag> <tag-name>mydictionary</tag-name> <component> <component-type>dictionary</component-type> </component> </tag> </facelet-taglib>
As you can see, we are referencing the source XHTML contained in tags/form.xhtml and associating it with the “form” tag name.
Step #3 Add a reference to your tag lib in web.xml
<context-param> <param-name>javax.faces.FACELETS_LIBRARIES</param-name> <param-value>/WEB-INF/custom.taglib.xml</param-value> </context-param>
(Please note that the older facelets.LIBRARIES property has been deprecated and might not work in some Java EE servers. So use the above javax.faces.FACELETS_LIBRARIES for JSF 2 compliant servers)
Now that everything is in place you can just reference your tag within your XHTML pages as shown:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ct="https://www.mastertheboss.com/custom-taglib"> <h:body> <h:form> Translation: Dog is <ct:mydictionary value="dog" /> </h:form> </h:body> </html>
Using Custom JSF 2.2 tags
If you are planning to use JSF 2.2 then creating custom tags is even simpler! In JSF 2.2 declaring the tag into an XML file is not required anymore an the tag declaration can be done via the component’s annotation. For this the @FacesComponent annotation introduces 3 new attributes:
- createTag : If set to true the component will be directly useable via a tag on a Facelet.
- tagName: Optional explicit name for the tag. If omitted, the class’ simple name with the first character in lowercase will be used.
- namespace: Optional explicit namespace for the tag. If omitted the namespace http://java.sun.com/jsf/component will be used.
Here’s your custom tag based on the JSF 2.2 implementation
package com.sample; import java.io.IOException; import java.util.Hashtable; import javax.faces.component.FacesComponent; import javax.faces.component.UIComponentBase; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; @FacesComponent(value = "dictionary", createTag=true) public class TranslatorComponent extends UIComponentBase { . . . . }
And here’s how to reference it from within your XHTML page:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ct="https://www.mastertheboss.com/custom-taglib"> <h:body> <h:form> Translation: Dog is <ct:translatorComponent value="dog" /> </h:form> </h:body> </html>