By Deepak Vohra
Published August 2011
Downloads:
: Oracle WebLogic Server 11g Rel 1 (10.3.4) Installer
: Apache Jakarta Standard 1.1 Taglib
In JavaServer Faces (JSF) 2.0, Facelets is the default view declaration language (VDL) instead of JavaServer Pages (JSP). With Facelets, you don’t need to configure a view handler as you used to do in JSF 1.2. Facelets is a JSF-centric view technology.
Facelets is based on compositions. A composition defines a JSF UIComponents structure in a Facelets page. A Facelets application may consist of compositions defined in different Facelets pages and run as an application.
Facelets is a templating framework similar to Tiles. The advantage of Facelets over Tiles is that JSF UIComponents are pre-integrated with Facelets, and Facelets does not require a Facelets configuration file, unlike Tiles, which requires a Tiles configuration file.
JSF Validators and Converters may be added to Facelets. Facelets provides a complete expression language (EL) and JavaServer Pages Standard Tag Library (JSTL) support. Templating, re-use, and ease of development are some of the advantages of using Facelets in a Web application.
In this article, we develop a Facelets Web application in Oracle Enterprise Pack for Eclipse 11g and deploy the application to Oracle WebLogic Server 11g. In the Facelets application, an input text UIComponent will be added to an input Facelets page. With JSF navigation, the input Facelets page is navigated to another Facelets page, which displays the JSF data table generated from the SQL query specified in the input Facelets page. We will use Oracle Database 11g Express Edition for the data source. Templating is demonstrated by including graphics for the header and the footer in the input and the output; the graphics have to be specified only once in the template.
Note: The source code for the Facelets Web application developed in this article can be downloaded here.
Before we develop the application, let’s review the Facelets technology. Facelets tags are used with the JSF Core and JSF HTML tag libraries to develop a JSF Facelets application. Some of the Facelets tags are discussed in Table 1.
Table 1. Facelets Tags
|
Facelets Tag |
Description |
Attributes |
|
ui:composition |
Defines a composition of UIComponents. A composition may consist of multiple UIComponents. Text not within ui:composition tags is not compiled in a Facelets page. |
template: Optional attribute that specifies the template to use for adding UIComponents within a composition. |
|
ui:define |
Used in a Facelets page to add content with a template. |
name: A required attribute; matches the name attribute in ui:insert. |
|
ui:decorate |
Similar to ui:composition except that text not within the ui:decorate tags is included in the Facelets page. |
template: A required attribute that specifies the template to use for adding UIComponents in ui:decorate tags. |
|
ui:component |
Similar to ui:composition except adds a new UIComponent as the root component in the UIComponents structure. |
id: If not specified, Facelets assigns an ID. |
|
ui:fragment |
A nontrimming tag for ui:component, similar to the ui:decorate tag for ui:composition. |
id: If not specified, Facelets assigns an ID. |
|
ui:include |
Includes a Facelets page that defines a composition or a component in a Facelets page or the template page. |
src: A required attribute that specifies the target Facelets page to include with an EL expression or a string literal. |
|
ui:insert |
Used in a template to define the layout of Facelets pages that use the template for defining UIComponents. A template client adds UIComponents to a Facelets page with corresponding ui:define tags. If a Facelets page specifies a template and it does not specify ui:define tags corresponding to ui:insert tags, the default ui:insert tags are used in the Facelets page. |
name: An attribute that has a corresponding name attribute in a Facelets page’s ui:define tag for matching a template with a Facelets page. |
|
ui:param |
Specifies a variable when a Facelets page is included within a template or a Facelets page. |
name: Required attribute that specifies the variable name. |
Facelets pages are XHTML pages by default. A Facelets application consists of the following configuration and templating files.
The template file defines the layout in Facelets and consists of <ui:insert/> tags to specify the structure of a Facelets composition that uses the template for defining UIComponents.
The JSF configuration file is the only configuration file required; a Facelets configuration file is not required. A Facelets page is an XHTML page that includes tags in the Facelets namespace.
In the following sections, we create a Facelets application in Oracle Enterprise Pack for Eclipse 11g, Oracle WebLogic Server 11g, and Oracle Database 11g Express Edition.
The following prerequisites are required:
First, we need to create a database table in Oracle Database Express Edition.
CREATE USER OE IDENTIFIED BY OE; GRANT CONNECT, RESOURCE to OE;
CREATE TABLE OE.Catalog(CatalogId INTEGER
PRIMARY KEY, Journal VARCHAR(25), Publisher VARCHAR(25),
Edition VARCHAR(25), Title Varchar(45), Author Varchar(25));
INSERT INTO OE.Catalog VALUES('1', 'Oracle Magazine',
'Oracle Publishing', 'Nov-Dec 2004', 'Database Resource
Manager', 'Kimberly Floss');
INSERT INTO OE.Catalog VALUES('2', 'Oracle Magazine',
'Oracle Publishing', 'Nov-Dec 2004', 'From ADF UIX to JSF',
'Jonas Jacobi');
INSERT INTO OE.Catalog VALUES('3', 'Oracle Magazine',
'Oracle Publishing', 'March-April 2005', 'Starting with
Oracle ADF ', 'Steve Muench');
C:\JSTL\jakarta-taglibs-standard-1.1.2\lib\standard.jar;C:\JSTL\jakarta-taglibs-standard-1.1.2\lib\jstl.jar
JSF 2.0 support is not configured in Oracle WebLogic Server 11g by default. To configure JSF 2.0 support, do the following:



A deployment configuration for JSF 2.0 is added to Deployments.

The JSF 2.0 library gets configured in the configuration file, C:\Oracle\Middleware\user_projects\domains\wls_base_domain\config\config.xml.
<library> <name>jsf#[email protected]_2-0-2</name> <target>AdminServer</target> <module-type>war</module-type> <source-path>C:\Oracle\Middleware\wlserver_10.3\common\deployable-libraries\jsf-2.0.2.war</source-path> <deployment-order>100</deployment-order> <security-dd-model>DDOnly</security-dd-model> </library>
Create a Facelets project by performing the following steps:





<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>

<wls:library-ref> <wls:library-name>jsf</wls:library-name> <wls:specification-version>2.0</wls:specification-version> <wls:implementation-version>1.0.0.0_2-0-2</wls:implementation-version> <wls:exact-match>true</wls:exact-match> </wls:library-ref>
Create a managed bean by performing the following steps:


Create a Facelets Template by performing the following steps:
templates directory in the WEB-INF directory.templates directory.


BasicTemplate.xhtml with a header, content, and footer is added to the templates directory. 
html, which includes the namespace declaration for the Facelets namespace.ui:insert tags enclosed in <div/> tags for the different sections of a Facelets composition: a title, a header, a content section, and a footer.header.xhtml and footer.xhtml Facelets pages using the ui:include tag. BasicTemplate.xhtml is listed below.<!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="#"> <head> <title><ui:insert name="title">JSF Facelets</ui:insert></title> </head> <body> <div id="header"> <ui:insert name="header"> <ui:include src="/WEB-INF/templates/header.xhtml" /> </ui:insert> </div> <div id="content"> <ui:insert name="content">
<!-- include your content file or uncomment the include below and create content.xhtml in this directory --> <!-- <div> --> <!-- <ui:include src="content.xhtml"/> --> <!-- </div> --> </ui:insert> </div> <div id="footer"> <ui:insert name="footer"> <ui:include src="/WEB-INF/templates/footer.xhtml" /> </ui:insert> </div> </body> </html>
Create Facelets pages by performing the following steps:

<?xml version="1.0" encoding="ISO-8859-1" ?> <!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="#" xmlns:h="#" xmlns:f="#"> <f:view> <h:form> <h:panelGrid columns="1"> <h:graphicImage value="FaceletsHeader.jpg" /> </h:panelGrid> </h:form> </f:view> </html>
footer.xhtml page, specify a .jpg file for the footer using the h:graphicImage tag enclosed in an h:panelGrid tag. The footer.xhtml page is listed below.<?xml version="1.0" encoding="ISO-8859-1" ?> <!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="#" xmlns:h="#" xmlns:f="#"> <f:view> <h:form> <h:panelGrid columns="1"> <h:graphicImage value="FaceletsFooter.jpg" /> </h:panelGrid> </h:form> </f:view> </html>
The h:commandButton has its binding specified as the commandButton1 component in the managed bean catalog. The action attribute of the command button is set to the catalog.commandButton1_action method in the managed bean.
The Facelets page input.xhtml consists of a ui:composition tag for defining the composition of the Facelets page, and ui:define tags within the ui:composition tag for defining UIComponents for the different sections of the Facelets composition, header, content, and footer.
The template name is specified in the template attribute of the ui:composition tag. The ui:define tags correspond to ui:insert tags in the template. If a ui:define tag is not specified for a corresponding ui:insert tag, the default ui:insert tag in the BasicTemplate.xhtml page is used in the Facelet Composition page. Only the ui:define tag for the content is defined in the input.xhtml page; the header and footer .jpg files specified in the header.xhtml and footer.xhtml and included in BasicTemplate.xhtml with ui:insert and ui:include are used for the header and footer sections.
<!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="#"
xmlns:h="#"
xmlns:f="#">
<ui:composition template="/WEB-INF/templates/BasicTemplate.xhtml">
<ui:define name="content">
<h:form>
<h:panelGrid columns="2">
<h:outputLabel binding="#{catalog.outputLabel1}" value="SQL Query:" />
<h:inputText binding="#{catalog.inputText1}" />
<h:commandButton value="Submit" binding="#{catalog.commandButton1}"
action="#{catalog.commandButton1_action}" />
</h:panelGrid>
</h:form>
</ui:define>
</ui:composition>
</html>
The output.xhtml Facelets Composition page consists of an h:dataTable UI component in the content section to output the JSF data table for the SQL query in the input.xhtml Facelet Composition page. The ui:define tag for content defines the composition of the Facelets page. The h:dataTable has a binding to the dataTable1 property in the managed bean, and the h:column components have bindings to the column1, column2…column6 properties in the managed bean. The Facelet Composition page output.xhtml file is listed below.
<!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="#" xmlns:h="#" xmlns:f="#">
<ui:composition template="/WEB-INF/templates/BasicTemplate.xhtml">
<ui:define name="content">
<h:form>
<h:dataTable binding="#{catalog.dataTable1}" border="1" rows="5">
<h:column binding="#{catalog.column1}"></h:column>
<h:column binding="#{catalog.column2}"></h:column>
<h:column binding="#{catalog.column3}"></h:column>
<h:column binding="#{catalog.column4}"></h:column>
<h:column binding="#{catalog.column5}"></h:column>
<h:column binding="#{catalog.column6}"></h:column>
</h:dataTable>
</h:form>
</ui:define>
</ui:composition>
</html>
Next, we add navigation to the Facelets application by adding navigation rules to faces-config.xml.
error.xhtml, for navigating to if an error is generated.



<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/index.html" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/index.html http://bit.ly/17U4sqz" version="2.0"> <application> <message-bundle>resources.application</message-bundle> <locale-config> <default-locale>en</default-locale> </locale-config> </application> <managed-bean> <managed-bean-name>catalog</managed-bean-name> <managed-bean-class>catalog.backing.Catalog</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> <navigation-rule> <display-name>input.xhtml</display-name> <from-view-id>/input.xhtml</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/output.xhtml</to-view-id> </navigation-case> </navigation-rule> <navigation-rule> <display-name>input.xhtml</display-name> <from-view-id>/input.xhtml</from-view-id> <navigation-case> <from-outcome>failure</from-outcome> <to-view-id>/error.xhtml</to-view-id> </navigation-case> </navigation-rule> </faces-config>
Catalog.java, the Java class for the managed bean, add the required import statements for the HTML and UI components. Add an HtmlDataTable variable for a data table and add UIColumn component variables for the data table columns. Also add HTML component variables for a form, input text to specify an SQL query, and a command button to submit the SQL query
private HtmlDataTable dataTable1;
private UIColumn column1;
private UIColumn column2;
private UIColumn column3;
private UIColumn column4;
private UIColumn column5;
private UIColumn column6;
public String commandButton1_action() { }
rs = stmt.executeQuery((String) inputText1.getValue());
dataTable1.setBorder(5);
dataTable1.setCellpadding("1");
dataTable1.setVar("catalog");
HtmlOutputText headerComponent = new HtmlOutputText();
headerComponent.setValue("CatalogId");
column1.setHeader(headerComponent);
HtmlOutputText column1Text = new HtmlOutputText();
FacesContext fCtx = FacesContext.getCurrentInstance();
ELContext elCtx = fCtx.getELContext();
ExpressionFactory ef = fCtx.getApplication().getExpressionFactory();
ValueExpression ve = ef.createValueExpression(elCtx,
"#{catalog.catalogid}", String.class);
column1Text.setValueExpression("value", ve);
column1.getChildren().add(column1Text);
ResultSetDataModel dataModel=new ResultSetDataModel(); dataModel.setWrappedData(rs);
dataTable1.setValue(dataModel);
The managed bean Java class Catalog.java is listed below.
package catalog.backing;
import javax.faces.component.html.HtmlCommandButton; import javax.faces.component.html.HtmlDataTable; import javax.faces.component.html.HtmlForm; import javax.faces.component.html.HtmlInputText; import javax.faces.component.html.HtmlOutputLabel; import javax.faces.component.UIColumn; import javax.faces.component.html.HtmlOutputText; import javax.faces.context.FacesContext; import javax.el.*; import javax.faces.model.ResultSetDataModel; import java.sql.*;
public class Catalog {
private HtmlForm form1;
private HtmlInputText inputText1;
private HtmlOutputLabel outputLabel1;
private HtmlCommandButton commandButton1;
private HtmlDataTable dataTable1;
private UIColumn column1;
private UIColumn column2;
private UIColumn column3;
private UIColumn column4;
private UIColumn column5;
private UIColumn column6;
private Statement stmt;
private Connection connection;
private ResultSet rs;
public void setForm1(HtmlForm form1) {
this.form1 = form1;
}
public HtmlForm getForm1() {
return form1;
}
public void setInputText1(HtmlInputText inputText1) {
this.inputText1 = inputText1;
}
public HtmlInputText getInputText1() {
return inputText1;
}
public void setOutputLabel1(HtmlOutputLabel outputLabel1) {
this.outputLabel1 = outputLabel1;
}
public HtmlOutputLabel getOutputLabel1() {
return outputLabel1;
}
public void setCommandButton1(HtmlCommandButton commandButton1) {
this.commandButton1 = commandButton1;
}
public HtmlCommandButton getCommandButton1() {
return commandButton1;
}
public void setDataTable1(HtmlDataTable dataTable1) {
this.dataTable1 = dataTable1;
}
public HtmlDataTable getDataTable1() {
return dataTable1;
}
public void setColumn1(UIColumn column1) {
this.column1 = column1;
}
public UIColumn getColumn1() {
return column1;
}
public void setColumn2(UIColumn column2) {
this.column2 = column2;
}
public UIColumn getColumn2() {
return column2;
}
public void setColumn3(UIColumn column3) {
this.column3 = column3;
}
public UIColumn getColumn3() {
return column3;
}
public void setColumn4(UIColumn column4) {
this.column4 = column4;
}
public UIColumn getColumn4() {
return column4;
}
public void setColumn5(UIColumn column5) {
this.column5 = column5;
}
public UIColumn getColumn5() {
return column5;
}
public void setColumn6(UIColumn column6) {
this.column6 = column6;
}
public UIColumn getColumn6() {
return column6;
}
public String commandButton1_action() {
// Add event code here...
try {
Class.forName("oracle.jdbc.OracleDriver");
String url = "jdbc:oracle:thin:@localhost:1521:XE";
connection = DriverManager.getConnection(url, "OE", "OE");
stmt = connection.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
rs = stmt.executeQuery((String) inputText1.getValue());
HtmlDataTable dataTable1 = new HtmlDataTable();
dataTable1.setBorder(5);
dataTable1.setCellpadding("1");
dataTable1.setVar("journalcatalog");
ResultSetDataModel dataModel = new ResultSetDataModel();
dataModel.setWrappedData(rs);
this.setDataTable1(dataTable1);
UIColumn column1 = new UIColumn(); UIColumn column2 = new UIColumn(); UIColumn column3 = new UIColumn(); UIColumn column4 = new UIColumn(); UIColumn column5 = new UIColumn(); UIColumn column6 = new UIColumn();
this.setColumn1(column1); this.setColumn2(column2); this.setColumn3(column3); this.setColumn4(column4); this.setColumn5(column5); this.setColumn6(column6);
HtmlOutputText headerComponent = new HtmlOutputText();
headerComponent.setValue("CatalogId");
column1.setHeader(headerComponent);
headerComponent = new HtmlOutputText();
headerComponent.setValue("Journal");
column2.setHeader(headerComponent);
headerComponent = new HtmlOutputText();
headerComponent.setValue("Publisher");
column3.setHeader(headerComponent);
headerComponent = new HtmlOutputText();
headerComponent.setValue("Edition");
column4.setHeader(headerComponent);
headerComponent = new HtmlOutputText();
headerComponent.setValue("Title");
column5.setHeader(headerComponent);
headerComponent = new HtmlOutputText();
headerComponent.setValue("Author");
column6.setHeader(headerComponent);
HtmlOutputText column1Text = new HtmlOutputText();
FacesContext fCtx = FacesContext.getCurrentInstance();
ELContext elCtx = fCtx.getELContext();
ExpressionFactory ef = fCtx.getApplication().getExpressionFactory();
ValueExpression ve = ef.createValueExpression(elCtx,
"#{journalcatalog.catalogid}", String.class);
column1Text.setValueExpression("value", ve);
column1.getChildren().add(column1Text);
HtmlOutputText column2Text = new HtmlOutputText();
fCtx = FacesContext.getCurrentInstance();
elCtx = fCtx.getELContext();
ef = fCtx.getApplication().getExpressionFactory();
ve = ef.createValueExpression(elCtx, "#{journalcatalog.journal}",
String.class);
column2Text.setValueExpression("value", ve);
column2.getChildren().add(column2Text); HtmlOutputText column3Text = new HtmlOutputText();
fCtx = FacesContext.getCurrentInstance();
elCtx = fCtx.getELContext();
ef = fCtx.getApplication().getExpressionFactory();
ve = ef.createValueExpression(elCtx, "#{journalcatalog.publisher}",
String.class);
column3Text.setValueExpression("value", ve);
column3.getChildren().add(column3Text);
HtmlOutputText column4Text = new HtmlOutputText();
fCtx = FacesContext.getCurrentInstance();
elCtx = fCtx.getELContext();
ef = fCtx.getApplication().getExpressionFactory();
ve = ef.createValueExpression(elCtx, "#{journalcatalog.edition}",
String.class);
column4Text.setValueExpression("value", ve);
column4.getChildren().add(column4Text);
HtmlOutputText column5Text = new HtmlOutputText();
fCtx = FacesContext.getCurrentInstance();
elCtx = fCtx.getELContext();
ef = fCtx.getApplication().getExpressionFactory();
ve = ef.createValueExpression(elCtx, "#{journalcatalog.title}",
String.class);
column5Text.setValueExpression("value", ve);
column5.getChildren().add(column5Text);
HtmlOutputText column6Text = new HtmlOutputText();
fCtx = FacesContext.getCurrentInstance();
elCtx = fCtx.getELContext();
ef = fCtx.getApplication().getExpressionFactory();
ve = ef.createValueExpression(elCtx, "#{journalcatalog.author}",
String.class);
column6Text.setValueExpression("value", ve);
column6.getChildren().add(column6Text);
dataTable1.setValue(dataModel);
} catch (SQLException e) {
System.out.println(e.getMessage());
return "failure";
} catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
return "failure";
} finally {
} return "success"; } }
Next, we need to specify some factory classes for the Facelets application before we run the application.
javax.faces.application.ApplicationFactory Class name: com.sun.faces.application.ApplicationFactoryImpl
javax.faces.context.FacesContextFactory Class name: com.sun.faces.context.FacesContextFactoryImpl
javax.faces.lifecycle.LifecycleFactory Class name: com.sun.faces.lifecycle.LifecycleFactoryImpl
javax.faces.render.RenderKitFactory Class name: com.sun.faces.renderkit.RenderKitFactoryImpl
The directory structure of the Facelets application is shown in the following figure.

input.xhtml and select Run As>Run on Server.
An EAR application is created and deployed to the Oracle WebLogic server.

input.xhtml Facelet Composition page that we configured earlier for JSF 2.0 using the URL http://localhost:7001/Facelets/faces/input.xhtml.The three sections of the input Facelets page are the header, content, and the footer. The different sections of the Facelet Composition page correspond to the different ui:define tags in the input.xhtml Facelet Composition page. The header.xhtml and footer.xhtml files from the BasicTemplate.xhtml template get included in the composition.
SELECT * FROM OE.CATALOG, and click Submit.
The output.xhtml Facelet Composition page is displayed with a JSF data table generated by the SQL query.
Templating has been demonstrated by including the same header.xhtml and footer.xhtml in the composition pages. The same header and footer .jpg files are displayed.

Deepak Vohra is a Sun Certified Java Programmer, Sun Certified Web Component Developer, and Oracle Certified Associate.
