Java Technologies: Java Server Faces (JSF)
Java Technologies: Java Server Faces (JSF)
# key = value
title = Simple JSF Application
greeting = Hello
sayHello.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
"sayHello.xhtml" → "hello"
Define the navigation rules in faces-config.xml
<faces-config>
<navigation-rule>
<from-view-id>/inputName.xhtml</from-view-id>
<navigation-case>
<from-outcome>hello</from-outcome>
<to-view-id>/sayHello.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
Configure JSF Environment in
web.xml
<web-app>
<context-param>
<param-name>javax.faces.application.CONFIG_FILES</param-name>
<param-value>/WEB-INF/faces-config.xml</param-value>
</context-param>
– ValueHolder, EditableValueHolder
– NamingContainer, StateHolder, …
Examples:
UICommand implements ActionSource2, StateHolder
UIOutput implements StateHolder, ValueHolder
UIInput implements EditableValueHolder, StateHolder, ValueHolder
Component Rendering Model
● Renderer class → the view of a component
– define the behavior of a component once
– create multiple renderers (Strategy Design Pattern)
A Render kit defines how component classes
map to component tags that are appropriate for
a particular client. The JavaServer Faces
implementation includes a standard HTML
render kit for rendering to an HTML client.
@ManagedBean(name = "personBean")
@SessionScoped
public class PersonBean implements Serializable {
<h:inputText value="#{personBean.salary}"
converter="javax.faces.convert.BigDecimalConverter"/>
<h:outputText value="#{personBean.birthday}">
<f:convertDateTime pattern = "yyyy-MM-dd"/>
</h:outputText>
@FacesConverter(forClass = Country.class)
public class CountryConverter extends AbstractConverter<Country> {
@Override
protected Object getAsObject(String value) {
return CountryRepository.findByName(value);
}
}
Converter Example (xhtml)
<p:selectOneMenu id="city"
value="#{personEdit.city}"
converter="#{cityConverter}">
<f:selectItems value="#{personEdit.cities}" />
<f:selectItem itemValue="#{null}" itemLabel="-" />
</p:selectOneMenu>
● ValueChangedListener
<h:inputText id="name" size="50"
value="#{personBean.name}"
required="true"
valueChangeListener="#{personBean.nameChanged}">
<f:valueChangeListener type="somepackage.SomeValueChangeListener" />
</h:inputText>
Implementing Event Listeners
Using a class
public class SomeActionListener implements ActionListener {
@Override
public void processAction(ActionEvent ae)
throws AbortProcessingException {
UIComponent ui = ae.getComponent();
System.out.println("Event source is: " +
ui.getClass().getName());
}
}
– Custom validators
● bean methods
● Validator classes
Using Custom Validators
● Using a validation method inside a bean
public void validateEmail(FacesContext context,
UIComponent component, Object value) {
String email = (String) value;
if (email.indexOf(’@’) == -1) {
((UIInput)component).setValid(false);
context.addMessage(component.getClientId(context),
new FacesMessage("Bad email"));
}
}
<h:inputText value="#{user.email}" validator="#{user.validateEmail}"/>
@Pattern(regexp = "^$|[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!
#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-
9](?:[a-z0-9-]*[a-z0-9])?")
@Size(max = 100)
@NotNull
private String email;
…
}
Validation error messages
● Use validatorMessge tag attribute
<p:inputText id="email"
value="#{personEdit.entity.email}"
validatorMessage="#{msg['email.invalid']}">
...
</p:inputText>
● Or override the defaults: Messages.properties
# ===================================================================
# Converter Errors
# ===================================================================
javax.faces.converter.DateTimeConverter.DATE =
{2}: ''{0}'' could not be understood as a date.
javax.faces.converter.DateTimeConverter.DATE_detail =
{2}: ''{0}'' could not be understood as a date. Example: {1}
...
# ====================================================================
# Validator Errors
# ====================================================================
javax.faces.validator.LengthValidator.MAXIMUM=
{1}: Validation Error: Length is greater than allowable maximum of ''{0}''
javax.faces.validator.LengthValidator.MINIMUM=
{1}: Validation Error: Length is less than allowable minimum of ''{0}''
...
The Navigation Model
● Navigation is a set of rules for choosing the
next page or view to be displayed after an
application action, such as when a button or link is clicked.
<h:commandButton id="submit" value="Submit" action="success"/>
ActionEvent → default ActionListener → NavigatorHandler
● Navigation can be
– implicit: “success” → success.xhtml
– user-defined: configured in the application
configuration resource files (faces-configx.xml)
<navigation-rule>
<from-view-id>/greeting.xhtml</from-view-id> /greeting.xhtml
<navigation-case>
<from-outcome>success</from-outcome> success
<to-view-id>/response.xhtml</to-view-id>
</navigation-case> /response.xhtml
</navigation-rule>
The Navigation Model
● Navigation is a set of rules for choosing the
next page or view to be displayed after an
application action, such as when a button or link is clicked.
<h:commandButton id="submit" value="Submit" action="success"/>
ActionEvent → default ActionListener → NavigatorHandler
● Navigation can be
– implicit: “success” → success.xhtml
– user-defined: configured in the application
configuration resource files (faces-configx.xml)
<navigation-rule>
<from-view-id>/greeting.xhtml</from-view-id> /greeting.xhtml
<navigation-case>
<from-outcome>success</from-outcome> success
<to-view-id>/response.xhtml</to-view-id>
</navigation-case> /response.xhtml
</navigation-rule>
The Lifecycle of a JSF Application
● Receive incoming HTTP request made by the client
– initial requests and postbacks
● Decode parameters from the request
– validate and convert the input data
● Modify and save the state
– A page is represented by a tree of components, called a
view. The view is built considering the state saved from a
previous submission of the page.
● Render the response to the client
FacesContext contains all of the per-request state information related to the processing of a
single JavaServer Faces request, and the rendering of the corresponding response. It is
passed to, and potentially modified by, each phase of the request processing lifecycle.
Request – Response in JSF
Builds the view of the page, wires event
handlers and validators to components in the
view, and saves the view in the FacesContext
instance
Each component
each component inin the
the tree
tree extracts
extracts its
its new
new
value from the request parameters by using its
decode (processDecodes())
method. The value ismethod.
then stored
The locally
value
is then
on eachstored
component.
locally on each component.
http://localhost:8080/myapp/hello.jsp
http://localhost:8080/myapp/faces/hello.jsp
What Is Facelets?
● Page declaration language that is used to
build JavaServer Faces views using HTML style
templates and to build component trees.
● Use of XHTML for creating web pages
● Support for Facelets tag libraries in addition to
JavaServer Faces and JSTL tag libraries
● Support for the Expression Language (EL)
● Templating for components and pages
● Composite components
● Faster compilation time, High-performance rendering, etc.
Using Facelets
hello.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Hello JSF - Facelets</title>
</h:head>
<h:body>
<h:outputText value="Hello"/>
</h:body>
</html>
http://localhost:8080/myapp/hello.xhtml
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
Facelets Libraries
URI: http://java.sun.com/ Prefix
JSF Facelets jsf/facelets ui:
JSF Composite jsf/composite composite:
JSF HTML jsf/html h:
JSF Core jsf/core f:
JSTL Core jsp/jstl/core c:
JSTL Functions jstl/functions fn:
Using Facelets Templates
template.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"> Top Section
<h:head>
<title>Facelets Template</title>
Main Content
</h:head>
<composite:interface>
<composite:attribute name="value" required="false"/>
</composite:interface>
<composite:implementation>
<h:outputLabel value="Email id: " />
<h:inputText value="#{cc.attrs.value}" />
</composite:implementation>
</h:body>
</html>
Using a Composite Component
somePage.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ez="http://java.sun.com/jsf/composite/ezcomp/">
<h:head>
<title>Using a sample composite component</title>
</h:head>
<body>
<h:form>
<ez:email value="Enter your email id" />
</h:form>
</body>
</html>
Creating a custom dataTable
<cc:interface>
<cc:attribute name="title" />
<cc:attribute name="dataView" type="somepackage.MyAbstractDataView" />
...
</cc:interface>
<cc:implementation>
<p:dataTable id="dataTable"
value="#{cc.attrs.dataView.items}"
filteredValue="#{cc.attrs.dataView.filtered}"
selectionMode="single"
...>
<p:ajax event="rowDblselect"
listener="#{cc.attrs.dataView.onRowDblClckSelect}" global="false" />
<p:ajax event="rowSelect" listener="#{cc.attrs.dataView.onRowSelect}"
update="addBtn editBtn removeBtn emailBtn"/>
<cc:insertFacet name="header"/>
<cc:insertChildren />
<ui:insert name="dataViewContent">
A view of the data. May be a dataTable, or a list, etc.
</ui:insert>
</h:form>
<ui:insert name="dialogs"/>
</ui:define>
</ui:composition>
Using the dataView
<!-- VIEW items -->
<ui:composition template="/WEB-INF/templates/dataView.xhtml" ...>
<ui:define name="dataViewContent">
<my:dataTable dataView="#{itemsView}"
var="item"
rowKey="#{banca.id}">
<p:column headerText="#{msg['item']}"
sortBy="#{item.name}">
<h:outputText value="#{item.name}" />
</p:column>
</my:dataTable>
</ui:define>
</ui:composition>
Creating a genetic dataEdit
<ui:composition template="/WEB-INF/template.xhtml" ...>
<ui:define name="content">
<p:dialog id="dataEditDialog" header="#{pageTitle}"
modal="true"appendTo="@(body)">
<h:form id="dataEditForm">
<p:messages id="messages" showDetail="false"
autoUpdate="true" closable="true" />
<ui:insert name="dataEditContent">
Data editor
</ui:insert>
<p:focus id="formFocus" context="dataEditForm"/>
<h:panelGrid id="dataEditButtons" columns="2">
<p:commandButton id="saveBtn" value="#{msg['save']}"
action="#{dataEdit.save}" ...>
<p:commandButton id = "cancelBtn" immediate="true" .../>
</h:panelGrid>
</h:form>
<p:ajax event="close" listener="#{dataEdit.onClose}" .../>
</p:dialog>
</ui:define>
</ui:composition>
Using the dataEdit
<!-- EDIT some item -->
<ui:composition template="/WEB-INF/templates/dataEdit.xhtml" … >
<ui:define name="dataEditContent">
<h:panelGrid id="bancaPanel" columns="2" cellpadding="5">
<f:validateLength maximum="100"/>
</p:inputText>
</h:panelGrid>
</ui:define>
</ui:composition>
PrimeFaces SHOWCASE
● PrimeFaces is a popular open source
framework for JavaServer Faces featuring over
100 components, touch optimized mobilekit,
client side validation, theme engine and more.
● Check out:
https://www.primefaces.org/showcase/index.xhtml