What You Need for Building Cool Enterprise Applications with JSF

VISoftware and s/w Development

Oct 6, 2011 (1 year and 8 months ago)

856 views

Max Katz Exadel Oct. 4, 2011

What You Need for Building
Cool Enterprise Applications
with JSF
Max Katz
Exadel
Oct. 4, 2011
Max Katz
Senior Systems Engineer
JSF, RichFaces, Java EE consulting,
and training
Developer Relations for Tiggr Mobile
Apps Builder (http://gotiggr.com)

>max@exadel.com
>@maxkatz
>mkblog.exadel.com
Exadel is a global software
engineering company
Founded in 1998, headquarters in
San Francisco Bay Area
7 Development offices in Europe
400+ employees
[Munich, Moscow, Ekaterinburg, Minsk, Homeyl, Kharkov, Donetsk]
The Plan Is Simple
1) Ajax features in JSF 2
2) The new RichFaces 4 – or
what you need to build cool
enterprise applications with
JSF
JavaServer Faces

(JSF) is
the standard component-
based user interface (UI)
framework for the
Java EE (5 & 6) platform
JSF 1.2
Java EE 5
JSF 2
Java EE 6
JSF 2 is a
major
upgrade
over JSF 1.x
Many features, ideas taken
from projects such as Seam,
RichFaces, and others

Facelets

Composite
components

Implicit
navigation

GET support

h:link, h:button

Resource loading
JSF 2 new features

New scopes

Flash, View,
custom

Configuration
via annotations

Bean Validation
support

Basic Ajax
JSF 2 <f:ajax>

Very basic Ajax functionality

Greatly inspired by RichFaces 3
<a4j:support> tag

Ajax in JSF in 3 easy steps:
1.
Sending an Ajax request
2.
Partial view processing
3.
Partial view rendering
<h:form>

<h:input value="#{bean.word}"/>

<h:commandButton>

<f:ajax event="click"

execute="@form"
listener="#{bean.ajaxListener}"

render="out1 out2"/>
</h:commandButton>
</h:form>
<h:form>

<h:input value="#{bean.word}"/>

<h:commandButton>

<f:ajax event="click"

execute="@form"
listener="#{bean.ajaxListener}"

render="out1 out2"/>
</h:commandButton>
</h:form>
1
2
3
<h:form>

<h:input value="#{bean.word}"/>

<h:selectOneMenu value="#{bean.selected}">
<f:selectItems value="#{bean.items}"/>

<f:ajax event="change"

execute="@form"
listener="#{bean.ajaxListener}"

render="@form"/>
</h:commandButton>
</h:form>
<h:form>

<h:input value="#{bean.word}"/>

<h:selectOneMenu value="#{bean.selected}">
<f:selectItems value="#{bean.items}"/>

<f:ajax event="change"

execute="@form"
listener="#{bean.ajaxListener}"

render="@form"/>
</h:commandButton>
</h:form>
1
2
3
Attribute
Value
event
Event on which to fire the
Ajax request
execute
@all
@this (default)
@form
@none
id's
EL
render
@all
@this
@form
@none (default)
id's
EL
Important
<f:ajax>
attributes
That's good, but that's all you get.
Where do you get rich components
and more?
A rich component framework is
still(?)
needed to build real-world
Ajax applications.
RichFaces 4 is a lightweight,
open source framework for
JSF 2
RichFaces 4 – rich JSF framework
UI components

a4j:* tag library (core)

rich:* tag library (UI)
Components' JavaScript API
Skins
Client-side validation (Bean Validation
based)
CDK – Component Development Kit
100% built on top of JSF2,
just extends functionality in
JSF 2
JavaScript is now entirely
based on the popular jQuery
library
All components are reviewed for consistency,
usability
Redesigned following semantic HTML
principles
Server-side and client-side performance
optimization
Strict code clean-up and review
RichFaces 4 is a lot faster, consistent,
and optimized
New client-side validation
based on Bean Validation
(JSR 303)
Quickly and easily validate
input on the client
New, and easy to use CDK
(
Component Development Kit
),
allows quickly to build your
own custom rich components
Pick your server:
Tomcat 6/7, Resin, JBoss AS 6/7,
GlassFish 3.x, WebLogic
[any server where JSF 2 application can be deployed]
Deploy and run in the cloud:
Google App Engine Amazon
EC2, CloudBees, OpenShift
Pick JSF implementations
you like:
Mojarra or MyFaces
Run in any browser
Pick your favorite tooling:
JBoss Tools, IntelliJ,
NetBeans
Easy to start. Zero-configuration,
just drop RichFaces into the
application
RichFaces versions
Version
JSF 1.1
JSF 1.2
JSF 2
RichFaces 3.1.x

RichFaces 3.3.3*


RichFaces 4

* Note: RichFaces 3.3.3 has basic JSF 2 support
RichFaces history
2005: started by Alexander Smirnov
2005-2007: Developed by Exadel
Ajax4jsf - open source, free
RichFaces - commercial
2007: JBoss takes over

Exadel team continues to develop
the framework, project is known as
RichFaces
Let's see what cool
components, and features
you get with RichFaces...
RichFaces <a4j:ajax>

100% based on standard <f:ajax>

Just replace
f:
with a4j: and get
exactly the same functionality

But, you get extra features...
<h:commandButton>

<
f:ajax
execute="@form" render="output"/>
</h:commandButton>


<h:commandButton>

<
f:ajax
execute="@form" render="output"/>
</h:commandButton>


<h:commandButton>

<
a4j:ajax
execute="@form" render="output"/>
</h:commandButton>


<h:commandButton>

<
a4j:ajax
execute="@form" render="output"/>
</h:commandButton>


Feature/Attribute
Description
onbegin
JavaScript to execute before Ajax
request
onbeforedomupdate
JavaScript to execute after response
comes back but before DOM update
oncomplete
JavaScript to execute after DOM update
bypassUpdates
Allows to skip JSF phases when
validating
limitRender
Turns off all auto-rendered panels
status
Status to display during Ajax request
Ajax queue
Advanced RichFaces client queue
<a4j:ajax> attributes
Components to send Ajax
request

<a4j:ajax>

<a4j:commandButton>

<a4j:commandLink>

<a4j:jsFunction>

<a4j:poll>

<a4j:push>
<a4j:commandButton/Link> –
button and link with built-in Ajax
behavior
<a4j:commandButton value="Save"
action="#{bean.action}"
render="output" />


<a4j:commandButton value="Save"
action="#{bean.action}"
render="output" />


<a4j:commandLink value="Save"
action="#{bean.action}"
render="output" />


<a4j:commandLink value="Save"
action="#{bean.action}"
render="output" />


<h:form>

<h:inputText>

<h:selectOneMenu>

<h:commandButton>


<f:ajax execute="@form"/>

</h:commandButton>
<h:form>


<h:form>

<h:inputText>

<h:selectOneMenu>

<h:commandButton>


<f:ajax execute="@form"/>

</h:commandButton>
<h:form>


<h:form>

<h:inputText>

<h:selectOneMenu>

<a4j:commandButton/>
<h:form>


<h:form>

<h:inputText>

<h:selectOneMenu>

<a4j:commandButton/>
<h:form>


Need to set
execute=”@form”
(
or execute=”id1 id2”
)
RichFaces default
value for
button/link
execute=”@form”
When using standard JSF button:
When using RichFaces button:
<table>

...

<td onmouseover="
update('yellow')
"/>
...
</table>
<h:form>

<a4j:jsFunction name="update"
action="#{bean.change}" render="...">

<a4j:param value="param1" assignTo="#{bean.color}"/>
</a4j:jsFunction>
</h:form>
<table>

...

<td onmouseover="
update('yellow')
"/>
...
</table>
<h:form>

<a4j:jsFunction name="update"
action="#{bean.change}" render="...">

<a4j:param value="param1" assignTo="#{bean.color}"/>
</a4j:jsFunction>
</h:form>
<a4j:jsFunction> – fire Ajax request
from any JavaScript function, HTML
event
<h:commandButton action="#{bean.change}">

<a4j:ajax render="id"/>
</h:commandButton>
<h:commandButton action="#{bean.change}">

<a4j:ajax render="id"/>
</h:commandButton>
If you had to pick just one Ajax
control, you would want
<a4j:jsFunction>
<h:commandButton
onclick="sendAjax();"
/>
<a4j:jsFunction name="sendAjax"
action="#{bean.change}" render="id"/>
<h:commandButton
onclick="sendAjax();"
/>
<a4j:jsFunction name="sendAjax"
action="#{bean.change}" render="id"/>
Is the same as:
<a4j:poll> – periodically send an
Ajax request
<a4j:poll interval="1000"
action="#{bean.count}"

render="output"
enabled="#{bean.pollEnabled}" />
<h:panelGrid id="output">
...
</h:panelGrid>
<a4j:poll interval="1000"
action="#{bean.count}"

render="output"
enabled="#{bean.pollEnabled}" />
<h:panelGrid id="output">
...
</h:panelGrid>
<a4j:push>

Server-side events are pushed to
client using Comet or WebSockets.

Implemented using Atmosphere

Provides excellent integration with
EE containers, and advanced
messaging services
<a4j:push address=
"
topic@chat
"

ondataavailable=
"
alert(event.rf.data)
"
/>
<a4j:push address=
"
topic@chat
"

ondataavailable=
"
alert(event.rf.data)
"
/>
Advanced rendering features

<a4j:outputPanel>

limitRender attribute

render=”{bean.renderList}”
<a4j:outputPanel> – auto rendered
panel
<a4j:commandButton value="Save" action="#{bean.save}">
<a4j:commandButton value="Edit" action="#{bean.edit}">
<a4j:outputPanel ajaxRendered="true">
<h:panelGrid>

...

</h:panelGrid>
</a4j:outputPanel>
<a4j:outputPanel ajaxRendered="true">

<rich:dataTable>

...

</rich:dataTable>
</a4j:outputPanel>
<a4j:commandButton value="Save" action="#{bean.save}">
<a4j:commandButton value="Edit" action="#{bean.edit}">
<a4j:outputPanel ajaxRendered="true">
<h:panelGrid>

...

</h:panelGrid>
</a4j:outputPanel>
<a4j:outputPanel ajaxRendered="true">

<rich:dataTable>

...

</rich:dataTable>
</a4j:outputPanel>
Turning off auto rendered panels
<a4j:commandButton value="Save" action="#{bean.save}">
<a4j:commandButton value="Edit" action="#{bean.edit}"
render="edit"
limitRender="true"
>
<a4j:outputPanel ajaxRendered="true">
<h:panelGrid>

...

</h:panelGrid>
</a4j:outputPanel>
<h:panelGrid id="edit">
<rich:dataTable>

...

</rich:dataTable>
</h:panelGrid>
<a4j:commandButton value="Save" action="#{bean.save}">
<a4j:commandButton value="Edit" action="#{bean.edit}"
render="edit"
limitRender="true"
>
<a4j:outputPanel ajaxRendered="true">
<h:panelGrid>

...

</h:panelGrid>
</a4j:outputPanel>
<h:panelGrid id="edit">
<rich:dataTable>

...

</rich:dataTable>
</h:panelGrid>
render=”#{bean.renderList}”
1)

Ajax request sent
2)

Component id's to be
rendered resolved
3)

Component id's are
rendered into the page
4)

2
nd
Ajax request is sent.
In this request the
components (resolved in
step 2 are sent with
request) will be rendered
1)

Ajax request sent
2)

Component id's to
be rendered
resolved
3)

Component id's
are rendered
JSF
RichFaces
Advanced execute features

<a4j:region>

bypassUpdates attribute
<a4j:region> – defining execute
region declaratively
<h:form>

<a4j:region>


<h:inputText />

<h:inputText />

<h:selectOneMenu />
<a4j:commandButton />

<a4j:region>
</h:form>
<h:form>

<a4j:region>


<h:inputText />

<h:inputText />

<h:selectOneMenu />
<a4j:commandButton />

<a4j:region>
</h:form>
Skipping
phases
when
validating
<h:inputText id=
"name"
value="#{bean.name}"/>

<a4j:ajax event=
"blur"

bypassUpdates="true"
/>
</h:inputText>
<rich:message for=
"name"/>
<h:inputText id=
"name"
value="#{bean.name}"/>

<a4j:ajax event=
"blur"

bypassUpdates="true"
/>
</h:inputText>
<rich:message for=
"name"/>
1.
Restore View
2.
Apply Request Values
3.
Process Validation
4.
Update Model
5.
Invoke Application
6.
Render Response
Even more advanced features
and tags

JavaScript callbacks

Queue

<a4j:status>

<a4j:param>

<a4j:log>
Easily use JavaScript callbacks
during Ajax request
<a4j:commandLink value="Link"

onbegin
="ajaxOnBegin()"

onbeforedomupdate
="ajaxOnBeforeDomUpdate()"

oncomplete
="ajaxOnComplete()">
</a4j:commandLink>
<a4j:commandLink value="Link"

onbegin
="ajaxOnBegin()"

onbeforedomupdate
="ajaxOnBeforeDomUpdate()"

oncomplete
="ajaxOnComplete()">
</a4j:commandLink>
JSF 2 queue

JSF 2 has very basic queue
functionality

Events are queued and fired one at a
time

Only one request is processed on the
server at a time
<a4j:queue> – “combining” events
from the same component
While a request is executing
on the server, all requests
from
button A or button
B
will be combined
(merged) if the last event in
the queue is of the same
type.
<a4j:queue />
...
<a4j:commandButton id="buttonA" value="Button A"/>
<a4j:commandButton id="buttonB" value="Button B"/>
<a4j:queue />
...
<a4j:commandButton id="buttonA" value="Button A"/>
<a4j:commandButton id="buttonB" value="Button B"/>
<a4j:queue> – “combining” events
from different components
<a4j:queue />
<a4j:commandButton id="buttonA" value="Button A">

<a4j:attachdQueue requestGroupingId="ajaxGroup"/>
</a4j:commandButton>
<a4j:commandButton id="buttonB" value="Button B">

<a4j:attachdQueue requestGroupingId="ajaxGroup"/>
</a4j:commandButton>
<a4j:queue />
<a4j:commandButton id="buttonA" value="Button A">

<a4j:attachdQueue requestGroupingId="ajaxGroup"/>
</a4j:commandButton>
<a4j:commandButton id="buttonB" value="Button B">

<a4j:attachdQueue requestGroupingId="ajaxGroup"/>
</a4j:commandButton>
While a request is executing
on the server, all requests
from
button A or button
B
will be combined
(merged).
<a4j:queue> – setting request delay
allows “waiting” for requests from
same component in order to merge
events
<a4j:queue requestDelay="1000"/>
<a4j:commandButton id="buttonA" value="Button A">

<a4j:attachdQueue requestDelay="2000"/>
</a4j:commandButton>
<a4j:commandButton id="buttonB" value="Button B"/>
<a4j:queue requestDelay="1000"/>
<a4j:commandButton id="buttonA" value="Button A">

<a4j:attachdQueue requestDelay="2000"/>
</a4j:commandButton>
<a4j:commandButton id="buttonB" value="Button B"/>
<a4j:queue> – ignoring “stale”
responses
<a4j:queue requestDelay="2000

ingoreDupResponses="true"/>
<h:inputText value="#{bean.state}
"
>

<a4j:ajax event=
"
keyup
"
listener=
"
#{bean.load}
"

render=
"
states
"
/>
</h:inputText>
<a4j:queue requestDelay="2000

ingoreDupResponses="true"/>
<h:inputText value="#{bean.state}
"
>

<a4j:ajax event=
"
keyup
"
listener=
"
#{bean.load}
"

render=
"
states
"
/>
</h:inputText>
<a4j:status> – Ajax request
status
<a4j:status name="ajaxStatus">

<f:facet name="start">

<h:graphicImage value="ajaxStatus.jpg"/>

</f:facet>
</a4j:status>
<h:form>

<a4j:commandButton status="ajaxStatus"/>
</h:form>
<a4j:status name="ajaxStatus">

<f:facet name="start">

<h:graphicImage value="ajaxStatus.jpg"/>

</f:facet>
</a4j:status>
<h:form>

<a4j:commandButton status="ajaxStatus"/>
</h:form>
<a4j:param> - like <f:param>, but
simpler as it also assigns the value to
a bean property automatically
<a4j:commandButton value="Save">

<a4j:param value="1009" assignTo="#{bean.product}"/>
</a4j:commandButton>


<a4j:commandButton value="Save">

<a4j:param value="1009" assignTo="#{bean.product}"/>
</a4j:commandButton>


public class Bean {

private String product;
public void setProduct (String product) {...}
}
public class Bean {

private String product;
public void setProduct (String product) {...}
}
Another great feature is that
<a4j:param> value can contain any
JavaScript expression or JavaScript
function, when noEscape="true"
<a4j:param name="width"

value="
(jQuery(window).width()/2)
"

assignTo="#{bean.screenWidth}"

noEscape="true"
/>


<a4j:param name="width"

value="
(jQuery(window).width()/2)
"

assignTo="#{bean.screenWidth}"

noEscape="true"
/>


<a4j:log> – Ajax request/response
information, logging
RichFaces UI components

Output, panels

Input

Menu

Data iteration

Tree

Drag and drop

Client side validation

Miscellaneous
rich:tab
rich:accordion
rich:accordion
rich:progressBar
More rich output, panels

rich:panel

rich:togglePanel

rich:popupPanel

rich:collapsiblePanel

rich:toolTip
<rich:popupPanel> can be modal and
non-modal
<rich:popupPanel
modal="false"
>

<f:facet name="header">

Edit User

</f:facet>

...

...
</rich:popupPanel>
rich:calendar
rich:inplaceInput
rich:inputNumberSlider
rich:autocomplete
More rich input

rich:inputNumberSpinner

rich:inplaceSelect

rich:select

rich:fileUpload
rich:panelMenu
rich:toolBar
rich:dropDownMenu
rich:dataTable
rich:dataTable with
rich:collapsibleSubTable
rich:dataScroller
RichFaces data iteration components
support partial updates
render="@column"
render="@header"
render="@footer"
render="@body"
render="cellId"
To render from outside the table:
render="tableId@header"
render="tableId@body"
render="tableId@footer"
Deciding what rows/cell to update in
run-time
render="tableId:rows(bean.rowsSet)"
render="tableId:rows(bean.rowsSet):cellId"
New collapsible sub table component
<rich:dataTable> supports column
and row spanning
<rich:extendedDataTable> provides
lazy loading, column resizing, reorder
and more
More rich data iteration

a4j:repeat

rich:extendedDataTable

rich:collapsibleSubTable

rich:list

list | ordered | definition

rich:dataGrid

rich:column

Column and row spanning

Filtering, sorting
rich:tree
Drag and drop
Many RichFaces components
provide client-side JavaScript API
Method name
Description
getTop()
Return the top co-ordinate for the position of
the pop-up panel.
getLeft()
Return the left co-ordinate for the position of
the pop-up panel.
moveTo(top,left)
Move the pop-up panel to the co-ordinates
specified with the top and left parameters.
resize(width,height)
Resize the pop-up panel to the size specified
with the width and height parameters.
show()
Show the pop-up panel.
hide()
Hide the pop-up panel.
<rich:popupPanel> JavaScript API
Invoking component JavaScript API
using #{rich:component(id)}
function
<input type="button"
onclick="
#{rich:component('popup')}.show();"

value="Open" />
<rich:popupPanel id="popup">

<h:outputLink value="#"
onclick="
#{rich:component('popup')}.hide();

return false;">

<h:outputText value=
"
Close
"
/>

</h:outputLink>
</rich:popupPanel>
<input type="button"
onclick="
#{rich:component('popup')}.show();"

value="Open" />
<rich:popupPanel id="popup">

<h:outputLink value="#"
onclick="
#{rich:component('popup')}.hide();

return false;">

<h:outputText value=
"
Close
"
/>

</h:outputLink>
</rich:popupPanel>
Invoking component JavaScript API
using <rich:componentControl>
component
<h:outputLink value="#">

<h:outputText value="Open" />

<rich:componentControl event="click"
target="popup" operation="show" />
</h:outputLink>
<rich:popupPanel header="RichFaces" id="popup">

<h:outputLink
value="#"
>

<h:outputText value="Close" />

<rich:componentControl event="click"
target="popup" operation="hide" />

</h:outputLink>
</rich:popupPanel>
<h:outputLink value="#">

<h:outputText value="Open" />

<rich:componentControl event="click"
target="popup" operation="show" />
</h:outputLink>
<rich:popupPanel header="RichFaces" id="popup">

<h:outputLink
value="#"
>

<h:outputText value="Close" />

<rich:componentControl event="click"
target="popup" operation="hide" />

</h:outputLink>
</rich:popupPanel>
<rich:accordion id="c">

<rich:accordionItem header="New York" name="nyc">

<h:outputText value="You selected New York"/>

</rich:accordionItem>

<rich:accordionItem header="San Francisco" name="sf">

<h:outputText value="You selected San Francisco"/>

</rich:accordionItem>

...
</rich:accordion>
<rich:accordion id="c">

<rich:accordionItem header="New York" name="nyc">

<h:outputText value="You selected New York"/>

</rich:accordionItem>

<rich:accordionItem header="San Francisco" name="sf">

<h:outputText value="You selected San Francisco"/>

</rich:accordionItem>

...
</rich:accordion>
<input type="button" value="New York City"

onclick="#{rich:component('c')}.
switchToItem('nyc')
"/>
<input type="button" value="San Francisco"

onclick="#{rich:component('c')}.
switchToItem('sf')
"/>
<input type="button" value="Los Angeles"

onclick="#{rich:component('c')}.
switchToItem('la')
"/>
<input type="button" value="New York City"

onclick="#{rich:component('c')}.
switchToItem('nyc')
"/>
<input type="button" value="San Francisco"

onclick="#{rich:component('c')}.
switchToItem('sf')
"/>
<input type="button" value="Los Angeles"

onclick="#{rich:component('c')}.
switchToItem('la')
"/>
<input type="button" value="First"

onclick="#{rich:component('c')}.
switchToItem('@first')
"/>
<input type="button" value="Next"

onclick="#{rich:component('c')}.
switchToItem('@next')
"/>
<input type="button" value="Previous"

onclick="#{rich:component('c')}.
switchToItem('@prev')
"/>
<input type="button" value="Last"

onclick="#{rich:component('c')}.
switchToItem('@last')
"/>
<input type="button" value="First"

onclick="#{rich:component('c')}.
switchToItem('@first')
"/>
<input type="button" value="Next"

onclick="#{rich:component('c')}.
switchToItem('@next')
"/>
<input type="button" value="Previous"

onclick="#{rich:component('c')}.
switchToItem('@prev')
"/>
<input type="button" value="Last"

onclick="#{rich:component('c')}.
switchToItem('@last')
"/>
RichFaces client functions
Function
Description
rich:client(id)
Returns component client id
rich:element(id)
Returns DOM element
rich:component(id)
Returns RichFaces client component
instance to call JS API method
rich:isUserInRole(role)
Returns if the user has specified role
rich:findComponent(id)
Returns component instance for given
short id
Standard Java EE security with
#{rich:isUserInRole(role)} function
<rich:panel header="Admin panel"

rendered="#{rich:isUserInRole('admin')}"
>

Very sensitive information
</rich:panel>

<rich:panel header="User panel">

General information
</rich:panel>
<rich:panel header="Admin panel"

rendered="#{rich:isUserInRole('admin')}"
>

Very sensitive information
</rich:panel>

<rich:panel header="User panel">

General information
</rich:panel>

Calls facesContext.getExternalContext.getUserInRole(role)

What's good is that security roles can be defined anywhere
Client-side validation based
on Bean Validation
(JSR 303)
New in RichFaces 4
Bean Validation (JSR 303)
JSF 2 has support for Bean Validation
(validation done on server)
p
ublic class Bean {

@Pattern(regexp="...")

private String email;
}
p
ublic class Bean {

@Pattern(regexp="...")

private String email;
}
<h:inputText id="email" value="#{bean.email}">

<a4j:ajax event="blur"/>
</h:inputText>
<rich:message for="email"/>
<h:inputText id="email" value="#{bean.email}">

<a4j:ajax event="blur"/>
</h:inputText>
<rich:message for="email"/>
Bean:
JSF page:
Client-Validation Based on Bean
Validation
Validation is performed on the client. If no client
implementation available, validation automatically falls
back to standard, server validation
p
ublic class Bean {

@Pattern(regexp="...")

private String email;
}
p
ublic class Bean {

@Pattern(regexp="...")

private String email;
}
<h:inputText id="email" value="#{bean.email}">

<rich:validator />
</h:inputText>
<rich:message for="email"/>
<h:inputText id="email" value="#{bean.email}">

<rich:validator />
</h:inputText>
<rich:message for="email"/>
Bean:
JSF page:
Object validation with
<rich:graphValidator>
<rich:graphValidator value="#{bean}" id="crossField">
<h:inputText value="#{bean.password1}"/>

<h:inputText value="#{bean.password2}"/>

<rich:message for="email" for="crossField"/>
</rich:graphValidator>
<rich:graphValidator value="#{bean}" id="crossField">
<h:inputText value="#{bean.password1}"/>

<h:inputText value="#{bean.password2}"/>

<rich:message for="email" for="crossField"/>
</rich:graphValidator>
@Size(min=5,max=15)
private String password1;
@Size(min=5,max=15)
private String password2;
@AssertTrue(message="Passwords don't match")
public boolean checkPassword() {

return password1.equals(password1);
}
@Size(min=5,max=15)
private String password1;
@Size(min=5,max=15)
private String password2;
@AssertTrue(message="Passwords don't match")
public boolean checkPassword() {

return password1.equals(password1);
}
Rich miscellaneous

<rich:componentControl>

<rich:hashParam>

<rich:jQuery>
<rich:componentControl>

Allows to call JS API on a component
in declarative fashion
<h:outputLink id="openLink" value="#">
<h:outputText value="Open" />
<rich:componentControl event="click"

operation="show"

target="popup" />
</h:outputLink>
<rich:popupPanel id="popup">
...
</rich:popupPanel>
<h:outputLink id="openLink" value="#">
<h:outputText value="Open" />
<rich:componentControl event="click"

operation="show"

target="popup" />
</h:outputLink>
<rich:popupPanel id="popup">
...
</rich:popupPanel>
<rich:hashParam> - creates
JavaScript hash, can be passed to
another client function.
<h:commandButton value="Show popup">

<rich:componentControl target="pp" operation="show">

<rich:hashParam>

<f:param name="width" value="500" />

<f:param name="height" value="300" />

<f:param name="minWidth" value="300" />

<f:param name="minHeight" value="150" />

</rich:hashParam>

</rich:componentControl>
</h:commandButton
<h:commandButton value="Show popup">

<rich:componentControl target="pp" operation="show">

<rich:hashParam>

<f:param name="width" value="500" />

<f:param name="height" value="300" />

<f:param name="minWidth" value="300" />

<f:param name="minHeight" value="150" />

</rich:hashParam>

</rich:componentControl>
</h:commandButton
Using jQuery with <rich:jQuery>
<input type="button" id=" value="Update panel"/>
<rich:jQuery selector="#changeButton" event="click"

query="$('#nycInfo .rf-p-hdr').text('New York City');

$('.rf-p-b').css('color', 'blue');" />
<input type="button" id=" value="Update panel"/>
<rich:jQuery selector="#changeButton" event="click"

query="$('#nycInfo .rf-p-hdr').text('New York City');

$('.rf-p-b').css('color', 'blue');" />
Using jQuery when page rendered to
create zebra-like styling for table
<style>

.even-row {

background-color: #FCFFFE;

}

.odd-row {

background-color: #ECF3FE;

}
</style>
<rich:dataTable id="gamesTable">

// columns
</rich:dataTable>
<rich:jQuery selector="#gamesTable tr:odd"
query="addClass('odd-row')" />
<rich:jQuery selector="#gamesTable tr:even"
query="addClass('even-row')" />
<style>

.even-row {

background-color: #FCFFFE;

}

.odd-row {

background-color: #ECF3FE;

}
</style>
<rich:dataTable id="gamesTable">

// columns
</rich:dataTable>
<rich:jQuery selector="#gamesTable tr:odd"
query="addClass('odd-row')" />
<rich:jQuery selector="#gamesTable tr:even"
query="addClass('even-row')" />
Invoking <rich:jQuery> as a regular
JavaScript function
<h:graphicImage width="100" value="/images/venice.png"

onmouseover="
larger(this, {})
"
onmouseout="
normal(this, {})
" />
<rich:jQuery name="
larger
"
query="animate({width:'241px'})" />
<rich:jQuery name="
normal
"
query="animate({width:'100px'})"/>
<h:graphicImage width="100" value="/images/venice.png"

onmouseover="
larger(this, {})
"
onmouseout="
normal(this, {})
" />
<rich:jQuery name="
larger
"
query="animate({width:'241px'})" />
<rich:jQuery name="
normal
"
query="animate({width:'100px'})"/>
with mouse over
Skins
Skins

Lightweight extension on top of CSS

Change look and feel of all rich
component with a few minor changes

Can be applied to standard JSF and
HTML tags as well
Ready-to-use skins

classic

wine

blueSky

ruby

emeraldTown

deepMarine

plain

japanCherry
<context-param>

<param-name>org.richfaces.skin</param-name>

<param-value>ruby</param-value>
</context-param>
<context-param>

<param-name>org.richfaces.skin</param-name>

<param-value>ruby</param-value>
</context-param>
RichFaces Skin file
#Colors
headerBackgroundColor=#900000
headerGradientColor=#DF5858
headerTextColor=#FFFFFF
headerWeightFont=bold
generalBackgroundColor=#f1f1f1
generalTextColor=#000000
generalSizeFont=11px
generalFamilyFont=Arial, Verdana, sans-serif
controlTextColor=#000000
controlBackgroundColor=#ffffff
additionalBackgroundColor=#F9E4E4
#Colors
headerBackgroundColor=#900000
headerGradientColor=#DF5858
headerTextColor=#FFFFFF
headerWeightFont=bold
generalBackgroundColor=#f1f1f1
generalTextColor=#000000
generalSizeFont=11px
generalFamilyFont=Arial, Verdana, sans-serif
controlTextColor=#000000
controlBackgroundColor=#ffffff
additionalBackgroundColor=#F9E4E4
Skins

Modify existing or create your own

Change skins in runtime
<context-param>

<param-name>org.richfaces.skin</param-name>

<param-value>
myCoolSkin
</param-value>
</context-param>
<context-param>

<param-name>org.richfaces.skin</param-name>

<param-value>
myCoolSkin
</param-value>
</context-param>
<context-param>

<param-name>org.richfaces.skin</param-name>

<param-value>
#{bean.skin}
</param-value>
</context-param>
<context-param>

<param-name>org.richfaces.skin</param-name>

<param-value>
#{bean.skin}
</param-value>
</context-param>
Overwriting Skin CSS
<style>
.rf-p-hdr {
color: …

font-size: …

font-weight: …

font-family: …
}
</style>
<rich:panel>...</rich:panel>
<style>
.rf-p-hdr {
color: …

font-size: …

font-weight: …

font-family: …
}
</style>
<rich:panel>...</rich:panel>
Overwriting Skin CSS
<style>
.rf-p-hdr {

// overwrite skin CSS properties
}
.specialHeader {

// define custom CSS for specific panel
}
</style>
<rich:panel id="panel1">
...
<rich:panel>
<rich:panel id="panel2"
headerClass="specialHeader"
>
...
<rich:panel>
<style>
.rf-p-hdr {

// overwrite skin CSS properties
}
.specialHeader {

// define custom CSS for specific panel
}
</style>
<rich:panel id="panel1">
...
<rich:panel>
<rich:panel id="panel2"
headerClass="specialHeader"
>
...
<rich:panel>
Skinning standard JSF tags and
HTML tags
<h:button style="background-color:
'
#{richSkin.tableBackgroundColor}
'"/>
<h:button style="background-color:
'
#{richSkin.tableBackgroundColor}
'"/>
Apply to each control:
Skinning standard JSF tags and
HTML tags automatically
<context-param>

<param-name>

org.richfaces.enableControlSkinning

</param-name>

<param-value>true</param-value>
</context-param>
<context-param>

<param-name>

org.richfaces.enableControlSkinning

</param-name>

<param-value>true</param-value>
</context-param>
Apply to all standard controls (JSF and HTML):
Skinning standard JSF tags and
HTML tags only when special CSS
class is applied to parent container
<context-param>

<param-name>

org.richfaces.enableControlSkinningClasses

</param-name>

<param-value>true</param-value>
</context-param>
<context-param>

<param-name>

org.richfaces.enableControlSkinningClasses

</param-name>

<param-value>true</param-value>
</context-param>
<div class="
rfs-ctn
">

<h:outputText />

<h:inputText />

<h:commandButton />
</div>
<div class="
rfs-ctn
">

<h:outputText />

<h:inputText />

<h:commandButton />
</div>
Where can I try the new
RichFaces 4?
http://richfaces.org/showcase
RichFaces 4.1 (Late 2011)
Mobile support
New components:
Pick list
Ordering list
Rich text editor
How can we help with RichFaces

Web development
with RichFaces

Version 3 to 4 migration

Performance tune-up

Custom component
development

On-site training
Training
Days
JSF 1.2, 2
1-2
RichFaces 3, 4
1-2
JSF and RichFaces
2-3
RichFaces 3 to 4
1-2
RichFaces
Rich, flexible, robust, and
proven enterprise-level
framework to JSF 2
Tiggr is a Web-based mobile apps builder.
Super fast, and easy to build mobile Web and
native apps
Build your mobile app at
http://gotiggr.com
Export or build the app as mobile Web or
generate native app (for Android, iOS)
>max@exadel.com
>@maxkatz
>mkblog.exadel.com
Build your mobile app in the
cloud: http://gotiggr.com
Thank you!
How to get in touch with me: