Custom Tags as an Alternative to Composite Components in JSF

Composite components are well known and the concept is widely adopted by JSF developers today. Regrettably, another powerful concept seems to be ousted by the popularity of composite components: Custom (Facelet)-Tags. This article is about how to use them.

The basic idea is to have a piece of XHTML code residing in an own document. This snippet can be included in a page using a tag with with custom name. The following example shows a custom “quote” tag that acts as decorator by wrapping its content with a div-element. This is what the rendered output may look like:



The custom tag is used to wrap text, but any content, including JSF components (with respect to the limitations mentioned later on), may be used with the custom tag.

Example 1 – Usage of a custom tag

<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:ta="http://thomasasel.de/jsf-examples/customtags">
...
<ta:quote>The Web does not just connect machines, it connects people.</ta:quote>
...

The next snippet shows the tags implementation. As you can see, ui:insert is used to mark where the tags content will be placed.

Example 2 – Implementation of a simple custom tag

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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">
<ui:composition>
	<div class="quotation">
		<ui:insert />
	</div>
</ui:composition>
</html>

The “quote” tag could be further improved with a “source” attribute to emphasize the source of the quote. The additional attribute is therefore added:

Example 3 – Usage of a custom tag with additional attribute

<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:ta="http://thomasasel.de/jsf-examples/customtags">
...
<ta:paramQuote source="Tim Berners Lee">
	The Web does not just connect machines, it connects people.
</ta:paramQuote>
...

The following example shows the implementation of the tag. As you can see, the value of the source can be accessed using the EL expression #{source}. No further configuration is neccessary, every attribute defined on the tag in the using page will be accessible by its name via EL.

Example 4 – Accessing tag attributes through EL

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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">

<ui:composition>

	<div class="quotation">
		<ui:insert />
		<div class="source">#{source}</div>
	</div>

</ui:composition>

</html>

Tags are defined in a Facelet taglibarary. Here is an example of a taglibrary defining the tags for aboves examples:

Example 5 – Example of a custom taglib

<facelet-taglib version="2.0" 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">

 <namespace>http://thomasasel.de/jsf-examples/customtags</namespace>

 	<tag>
 		<tag-name>quote</tag-name>
 		<source>tags/quote.xhtml</source>
 	</tag>

 	<tag>
 		<tag-name>paramQuote</tag-name>
 		<source>tags/paramQuote.xhtml</source>

 		<attribute>
 			<name>source</name>
 		</attribute>
 	</tag>

 </facelet-taglib>

The tags name and source need to be defined as you can see in the example. contains the relative path to the tags source file. In this example the tags source files are located in WEB-INF/tags, the taglib resides in WEB-INF.

Attributes do not have to be defiend in the taglib but you may do so, as shown the shown example. This is helpful for IDE’s offering type-ahead functionality (Eclipse WTP for example). Additionally, attributes can be made mandatory by defining them as required or by requiring a certain type for them.

To use tags defined in a taglib you simply have to import the namespace defined in the taglib (see line 4) of the previous example.

Taglibs are usually named following this convention: .taglib.xhtml
It is possible to define multiple taglibs using the context parameter javax.faces.FACELETS_LIBRARIES as you can see the in the following example. Multiple libraries need to be seperated using “;”

Example 6 – web.xml context parameter to define custom taglibs

  <context-param>
  	<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
  	<param-value>/WEB-INF/examples.taglib.xml</param-value>
  </context-param>

Finally, it is totally valid to use JSF components in a tag implementation as you can see here:

Example 7 – Nesting JSF components within a tag implementation

<ui:composition>

	<div class="quotation">
		<ui:insert />
		<div class="source">#{source}</div>
		<hr />
		<h2>Post a comment:</h2>
		<h:inputText value="#{flash&#91;'input'&#93;}" /> <h:commandButton action="/example3.xhtml" value="submit" />
	</div>

</ui:composition>

The tag contains an input component bound to the EL-Flash (just for the sake of simplicity, normally a @ManagedBean should be used instead) and a command button to submit the form. This is what the rendered result may look like:

Limitations:

Tags can be used as placeholders for xhtml-snipptes. Those may include large amounts of (X)HTML and even jsf components.
Tags should never encapsulate any logic! Unlike composit components, there is no Java class backing the tag. Thus, custom tags will not be
represented as nodes in the component tree (their content will be, of course). Thus tags wont participate in state saving, validation or any other
component-related functionality. Create a composite component if you need this functionality.

Tags especially do not take care of clientId creation, so the following example will lead to an exception due to duplicate ids if the custom tag is used more than once within the same naming container:

Example 8 – This may cause duplicated id’s

	<div class="quotation">
		<ui:insert />
		<div class="source">#{source}</div>
		<hr />
		<h2>Post a comment:</h2>
		<h:inputText id="input" value="#{flash&#91;'input'&#93;}" />
		<h:commandButton action="/example3.xhtml" value="submit" />
	</div>

Since the input components id is static, it will be the same for every usage of the tag. Thus you need to rely on dynamicly created id’s when using JSF components in custom tags. This is perfectly reasonable, since you would also not expect ordinary HTML tags like to take care of nested components id’s, would you? ;-)

Conclusion

Tags may be used as structure elements or to combine larger xhtml snippets in a single tag. While you could also do this with composite components, custom tags will put less burden to the component tree and thus help to improve performance and memory usage.

Short URL for this post: http://wp.me/p4nxik-Xn
This entry was posted in Did you know?, Java Web Frameworks and tagged , , , . Bookmark the permalink.

3 Responses to Custom Tags as an Alternative to Composite Components in JSF

  1. henk53 says:

    Great article! :) Custom tags can definitely be useful, despite the existence of composite components.

    They get even more useful when combined with the methodParam tag from OmniFaces (see http://showcase-omnifaces.rhcloud.com/showcase/taghandlers/methodParam.xhtml ), which lets you pass method expressions into a custom tag (normally this is not really possible),

  2. Pingback: JSF Performance Tuning | techscouting through the java news

  3. guest says:

    BTW. In jfs/facelets custom tags are older than composite components

Leave a Reply