Warning: This entry probably needs hand-editing to deal with unconvertable media file references.
Writing Your Own Facelets Components
I am writing here of components written in the same way as those shipped with JSF are, in Java. There’s plenty out there on how to do the much simpler process of writing so-called composite components strictly in HTML and XML. Composite components have their limitations, however, so they are not complete substitutes for doing things the “hard way.” (Which really isn’t all that hard once one figures it out.)
This is something that there is virtually no decent documentation on anywhere, so I figured I’d write it here.
By “decent documentation,” I mean any series of instructions that is both reasonably complete and correct. By “anywhere” I mean literally anywhere, so far as I have been able to tell. Even in supposedly up-to-date and comprehensive books (which for Java Server Facelets are very rare) end up being less than comprehensive and have significant inaccuracies; there is no way that following the instructions therein will result in successfully implementing even the simplest component. It’s the bane of open-source software: coding is fun, but documenting things isn’t so much fun. So lots of coding gets done, not much documentation, and one ends up with huge complex software systems and only the spottiest of documentation.
But I digress. Onward.
First, there are a minimum of four files you must modify or create in order to create a custom component:
- The file that describes your tag(s) to JSF. The asterisk can be replaced by any sequence of characters, but the file itself should end in
taglib.xml. It’s customary to use hyphens or dots to set off the suffix, e.g.
- This ties the component types referenced in the taglib file to Java classes which implement them.
- This is where JSF is made aware of the taglib file.
- The code that implements your tag.
faces-config.xml files live in the
WEB-INF directory. It is traditional (but not required) to put
*taglib.xml there as well.
For each such file, I will provide an example. Taken together, they will result in a web app which defines and uses a very simple tag which simply outputs a bit of fixed text inside a
*.java file may be found here.)
This must be a subclass of
javax.faces.component.UIComponent; typically this will be a subclass of
javax.faces.component.UIInput (your component will render HTML that accepts input from the end user’s browser within a form) or more commonly
javax.faces.component.UIOutput (your component does not accept any user input).
Output-only tags are by far the most common, so that’s what I’m covering here for now. Not surprisingly, the core of defining a tag is telling JSF what HTML to render in its output when it encounters your tag in the input file. The class library documentation does not explicitly make it clear in any one place, but there are five key methods you need to be concerned with:
- A constructor
- Actually, I’m not 100% sure you need to bother with this; it might be acceptably defined for you by a parent class. But I ended up doing so, based on some examples I found. The trivial constructor I copied should serve most simple tags just fine.
- This method is responsible for outputting whatever HTML is needed when the opening tag for your component is encountered. If you are writing a component that uses no closing tag, you can put all of your rendering code in this method (which is what my example does).
- If your component does involve a starting and an ending tag, and you want to do something other than the standard rendering for what appears between the tags, this method needs to be defined. (See also the next item in this list.)
- If this component is responsible for rendering its children, you must define this method to return
true. If not, define it to return
false. Note that this implies you should always define this to return
true if you’re defining an
encodeChildren method. Note also that a parent class of
UIOutput defines a standard
encodeChildren method, so it is meaningful to have this method return
true even if you are not supplying your own
- This method is responsible for outputting whatever HTML is needed when the closing tag for your component is encountered. If your component has no closing tag (i.e. invoked like
<prefix:tag attribute="value" />), then this method will be called by JSF immediately after
Note that it is not always necessary to (re)define all five methods. For example, if your tag is not going to ever have enclosed content, or separate beginning or ending tags, then you need not implement
encodeEnd; you can put all your rendering into
encodeBegin and be done with it.
The easiest (and safest) way to generate HTML in the rendering methods is to use the
javax.faces.context.ResponseWriter object returned by the
getResponseWriter() method of the passed
javax.faces.context.FacesContext object. (It is also possible to use the stream returned by
getResponseStream(), but this is not so safe or easy as using a
ResponseWriter, because the latter takes pains to ensure that the generated HTML is valid.)
Note that you do not need to explicitly do anything to handle any attributes for your tag. JSF will automatically collect these for you and make them available in a
Map<String,Object> returned by the
getAttributes() method, which is already defined for you by a parent class of
The bad news about attributes is that there doesn’t seem to be any graceful way to make them mandatory or otherwise enforce restrictions about them. The
<attribute> tag should allow one to do this in the taglib file, but it doesn’t seem to be honored very well. At least, it failed to trigger any errors when I attempted to use this feature to make an attribute mandatory (and then deliberately omitted it in a Facelets file) in Apache Myfaces.
Note that your tag will automatically support some attributes common to all Facelets tags, such as the
rendered attribute, which controls if it renders as output at all, because parent classes of
UIOutput already support such attributes.
*taglib.xml file may be found here.)
This file defines one or more Facelets tags by describing the name space for one or more tags and the component type for each tag. (See next section for how the component type is associated with a class.) Note that the arbitrary prefix represented by an asterisk in this name need not match the file name represented by the asterisk in
*.java. Although the example file describes only a single tag, it is possible for a taglib file to describe more than one tag.
Although this file can reside in any web application directory, it is customary to place taglib files in the
faces-config.xml file may be found here.)
<component> entries of this file associate the component types mentioned in the taglib file with Java classes, which must appear in a jar file under
WEB-INF/lib or a class file under
web.xml file may be found here.)
facelets.LIBRARIES context parameter in this file defines a semicolon-delimited list of taglib files. If your taglib file(s) are not mentioned here, JSF will be unaware of your tags and they will not render properly.
The name of this context parameter is not well-standardized and may be different;
facelets.LIBRARIES appears to be the most common value (at least, it’s what both Mojarra and Apache Myfaces use). If that does not work, try
Using Your Tag
There’s at least one more file in the picture, of course, and that’s the Facelets file(s) which contain your tag. If you’ve done everything else in this guide correctly, at this point you’ve managed to create a tag which JSF recognizes just like any other Facelets tag. In other words, to use your tag, all you need to do is include an
xmlns attribute in the
<html> tag to associate a name with the URL name space of your tag, and then use your tag, prefixed with that name.
A sample which uses the tag I’ve defined may be found here. Since the tags in that will actually render in your browser (and moreover, if this blog is migrated to a Facelets-aware web server, the Facelets tag will render to HTML), here is a version as a plain-text file.