10 min read

Facelets templating

To implement the layout design, we use the Facelets templating that is officially a part of the JSF specification since release 2.0. This article will only have a look at certain parts of the Facelets technology. So, we will not discuss how to configure a web project to use Facelets. You can study the source code examples of this article, or have a look at the developer documentation (https://facelets.dev.java.net/nonav/docs/dev/docbook.html) and the articles section of the Facelets wiki (http://wiki.java.net/bin/view/Projects/FaceletsArticles)for further details.

The page template

First of all, we define a page template that follows our mockup design. For this, we reuse the HelloWorld(Facelets) application. You can import the WAR file now if you did not create a Facelets project.

For importing a WAR file, use the menu File | Import | Web | WAR file. In the dialog box, click on the Browse button and select the corresponding WAR file. Click on the Finish button to start the import. The run configuration is done. However, you do not have to configure the Jetty server again. Instead, it can be simply selected as your target.

We start coding with a new XHTML file in the WebContent folder. Use the menu File | New | Other | Web | HTML Page and click on the Next button. Use page-template.xhtml for File name in the next dialog. Click on the Next button again and choose New ICEfaces Facelets.xhtml File (.xhtml). Click on the Finish button to create the file.

The ICEfaces plugin creates this code:

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

>
<head>
<title>
<ui:insert name=”title”>
Default title
</ui:insert>
</title>
</head>
<body>
<div id=”header”>
<ui:include src=”/header.xhtml”>
<ui:param name=”param_name” value=”param_value”/>
</ui:include>
</div>
<div id=”content”>
<ice:form>
</ice:form>
</div>
</body>
</html>

The structure of the page is almost pure HTML. This is an advantage when using Facelets. The handling of pages is easier and can even be done with a standard HTML editor.

The generated code is not what we need. If you try to run this, you will get an error because the header.xhtml file is missing in the project. So, we delete the code between the <body> tags and add the basic structure for the templating. The changed code looks like this:

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

>
<head>
<title>
<ui:insert name=”title”>
Default title
</ui:insert>
</title>
</head>
<body>
<table align=”center” cellpadding=”0″ cellspacing=”0″>
<tr><td><!– header –></td></tr>
<tr><td><!– main navigation –></td></tr>
<tr><td><!– content –></td></tr>
<tr><td><!– footer –></td></tr>
</table>
</body>
</html>

We change the <body> part to a table structure. You may wonder why we use a <table> for the layout, and even the align attribute, when there is a <div> tag and CSS. The answer is pragmatism. We do not follow the doctrine because we want to get a clean code and keep things simple. If you have a look at the insufficient CSS support of the Internet Explorer family and the necessary waste of time to get things running, it makes no sense to do so. The CSS support in Internet Explorer is a good example of the violation of user expectations.

We define four rows in the table to follow our layout design. You may have recognized that the <title> tag still has its <ui:insert> definition. This is the Facelets tag we use to tell the templating where we want to insert our page-specific code. To separate the different insert areas from each other, the <ui:insert> has a name attribute.

We substitute the comments with the <ui:insert> definitions, so that the templating can do the replacements:

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

>
<head>
<title>
<ui:insert name=”title”>
Default title
</ui:insert>
</title>
</head>
<body>
<table align=”center” cellpadding=”0″ cellspacing=”0″>
<tr><td><ui:insert name=”header”/></td></tr>
<tr><td><ui:insert name=”mainNavigation”/></td></tr>
<tr><td><ui:insert name=”content”/></td></tr>
<tr><td><ui:insert name=”footer”/></td></tr>
</table>
</body>
</html>

The <ui:insert> tag allows us to set defaults that are used if we do not define something for replacement. Everything defined between <ui:insert> and </ui:insert> will then be shown instead. We will use this to define a standard behavior of a page that can be overwritten, if necessary. Additionally, this allows us to give hints in the rendering output if something that should be defined in a page is missing.

Here is the code showing both aspects:

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

>
<head>
<ice:outputStyle href=”/xmlhttp/css/royale/royale.css” />
<title>
<ui:insert name=”title”>
Please, define a title.
</ui:insert>
</title>
</head>
<body>
<table align=”center” cellpadding=”0″ cellspacing=”0″>
<tr><td>
<ui:insert name=”header”>
<ice:graphicImage url=”/logo.png” />
</ui:insert>
</td></tr>
<tr><td>
<ui:insert name=”mainNavigation”>
<ice:form>
<ice:menuBar noIcons=”true”>
<ice:menuItem value=”Menu 1″/>
<ice:menuItem value=”Menu 2″/>
<ice:menuItem value=”Menu 3″/>
</ice:menuBar>
</ice:form>
</ui:insert>
</td></tr>
<tr><td>
<ui:insert name=”content”>
Please, define some content.
</ui:insert>
</td></tr>
<tr><td>
<ui:insert name=”footer”>
<ice:outputText
value=”&#169; 2009 by The ICEcubes.” />
</ui:insert>
</td></tr>
</table>
</body>
</html>

The header, the main navigation, and the footer now have defaults. For the page title and the page content, there are messages that ask for an explicit definition. The header has a reference to an image. Add any image you like to the WebContent and adapt the url attribute of the <ice:graphicImage> tag, if necessary. The example project for this article will show the ICEcube logo. It is the logo that is shown in the mockup above. The <ice:menuBar> tag has to be surrounded by a <ice:form> tag, so that the JSF actions of the menu entries can be processed. Additionally, we need a reference to one of the ICEfaces default skins in the <head> tag to get a correct menu presentation. We take the Royale skin here.

If you do not know what the Royale skin looks like, you can have a look at the ICEfaces Component Showcase (http://component-showcase.icefaces.org) and select it in the combo box on the top left. After your selection, all components present themselves in this skin definition.

Using the template

A productive page template has a lot more to define and is also different in its structure. References to your own CSS, JavaScript, or FavIcon files are missing here. The page template would be unmaintainable soon if we were to manage the pull-down menu this way.

However, we will primarily look at the basics here. So, we keep the page template for now. Next, we adapt the existing ICEfacesPage1.xhtml to use the page template for its rendering.

Here is the original code:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC
  "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html

>
<head>
<title>
<ui:insert name=”title”>
Default title
</ui:insert>
</title>
</head>
<body>
<div id=”header”>
<!–
<ui:include src=”/header.xhtml” >
<ui:param name=”param_name” value=”param_value” />
</ui:include>
–>
</div>
<div id=”content”>
<ice:form>
<ice:outputText value=”Hello World!”/>
<!–
drop ICEfaces components here
–>
</ice:form>
</div>
</body>
</html>

We keep the Hello World! output and use the new page template to give some decoration to it. First of all, we need a reference to the page template so that the templating knows that it has to manage the page. As the page template defines the page structure, we no longer need a <head> tag definition.

You may recognize <ui:insert> in the <title> tag. This is indeed the code we normally use in a page template. Facelets has rendered the content in between because it did not find a replacement tag. Theoretically, you are free to define such statements in any location of your code. However, this is not recommended. Facelets has a look at the complete code base and matches pairs of corresponding name attribute definitions between <ui:insert name=”…”> and <ui:define name=”…”> tags.

Here is the adapted code:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC
  "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html

>
<body>
<ui:composition template=”/page-template.xhtml”>
<div id=”content”>
<ice:form>
<ice:outputText value=”Hello World!”/>
</ice:form>
</div>
</ui:composition>
</body>
</html>

This code creates the following output:

ICEfaces 1.8: Next Generation Enterprise Web Development

We can see our friendly reminders for the missing title and the missing content. The header, the main navigation, and the footer are rendered as expected. The structure of the template seems to be valid, although we recognize that a CSS fle is necessary to define some space between the rows of our layout table.

However, something is wrong. Any idea what it is? If you have a look at the hello-world.xhtml again, you can find our Hello World! output; but this cannot be found in the rendering result. As we use the page template, we have to tell the templating where something has to be rendered in the page. However, we did not do this for our Hello World! output.

The following code defines the missing <ui:define> tag and skips the <div> and <ice:form> tags that are not really necessary here:

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

>
<body>
<ui:composition template=”/page-template.xhtml”>
<ui:define name=”title”>
Hello World on Facelets
</ui:define>
<ui:define name=”content”>
<ice:outputText value=”Hello World!”/>
</ui:define>
</ui:composition>
</body>
</html>

LEAVE A REPLY

Please enter your comment!
Please enter your name here