RichFaces 4Rich Ajax Components For Your JSF Applications
Max KatzExadel
Vienna, Sept. 9, 2011
Max Katz
● Senior Systems Engineer at Exadel
● JSF, RichFaces, Java EE consulting, and training
● Manages exadel.org – Exadel's open source projects and community
● Community manager for gotiggr.com prototypes and mobile apps builder
4
Exadel is a global software engineering company.● Founded in 1998,
headquarters in San Francisco Bay Area
● 7 development offices in Europe
● 350+ employees
5
Minsk
Homyel
Kharkov
Donetsk
Ekaterinburg
Moscow
Munich
Open Source with JBoss
Exadel Products
exadel.org ◦ Flamingo
◦ Fiji
◦ jsf4birt
◦ JavaFX Plug-in for Eclipse
gotiggr.com
Exadel Services
● Professional services
● Rich enterprise application development
● Eclipse development
● Custom rich component development
● Mobile development
● Training
The Plan Is Simple
1) Ajax features in JSF 2
2) The new RichFaces 4
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:input value="#{bean.text}" id="out1"/> <h:input value="#{bean.phrase}" id="out2"/></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:input value="#{bean.text}" id="out1"/> <h:input value="#{bean.phrase}" id="out2"/></h:form>
1
2
3
Attribute Value
eventEvent on which to fire the Ajax request
execute
@all@this (default)@form@noneid'sEL
render
@all@this@form@none (default)id's EL
Important <f:ajax> attributes
That's good, but 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
Official RichFaces logo
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
RichFaces 4
100% built on top of JSF2, just extends functionality in
JSF 2
RichFaces 4
JavaScript is now entirely based on the popular jQuery
library
RichFaces 4
● 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
New client-side validation based on Bean Validation
(JSR 303)
RichFaces 4
New, and easy to use CDK (Component Development Kit),
allows quickly to build your own custom rich components
RichFaces 4
Run on: Tomcat 6/7, Resin, JBoss AS 6/7, GlassFish 3.x,
WebLogic
(run on any server when JSF 2 application
can be deployed)
RichFaces 4
Run on: Google App Engine (GAE), Amazon EC2,
CloudBees
RichFaces 4
JSF implementations: Mojarra or MyFaces
RichFaces 4
Any browser
RichFaces 4
Tooling support through JBoss Tools, IntelliJ,
NetBeans
RichFaces 4
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
RichFaces 4
Let's look at RichFaces features in more detail...
RichFaces 4 core – sending an Ajax request
● <a4j:ajax>
● <a4j:commandButton>
● <a4j:commandLink>
● <a4j:jsFunction>
● <a4j:poll>
● <a4j:push>
RichFaces 4
It's important to say it again, RichFaces only extends and
upgrades JSF 2...
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> <a4j:ajax execute="@form" render="output"/></h:commandButton>
Feature/Attribute Description
onbeginJavaScript to execute before Ajax request
onbeforedomupdateJavaScript to execute after response comes back but before DOM update
oncomplete JavaScript to execute after DOM update
bypassUpdatesAllows 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
<a4j:commandButton/Link> – button and link with built-in Ajax behavior
<a4j:commandButton 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> <a4j:commandButton/><h:form>
Need to set execute=”@form”(or execute=”id1 id2”)
RichFaces defaultvalue for button/linkexecute=”@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>
<a4j:jsFunction> – fire Ajax request from any JavaScript function, HTML event
<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"/>
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: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)" />
RichFace 4 core – 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>
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>
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) 2nd 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
RichFace 4 core – 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>
Skipping phases when validating
<h:inputText id="name" value="#{bean.name}"/> <a4j:ajax event="blur" bypassUpdates="true"/></h:inputText><rich:message for="name"/>
1.Restore View2.Apply Request Values3.Process Validation4.Update Model5.Invoke Application6.Render Response
JavaScript callbacks during Ajax request
<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> – “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>
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> – 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>
RichFace 4 core – more advanced features● <a4j:status>
● <a4j:param>
● <a4j:log>
● JavaScript interactions
<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: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>
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: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:accordionrich: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 withrich: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>
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>
<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="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>
● 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)
public class Bean { @Pattern(regexp="...") private String 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 ValidationValidation is performed on the client. If no client implementation available, validation automatically falls back to standard, server validation
public class Bean { @Pattern(regexp="...") private String email;}
<h:inputText id="email" value="#{bean.email}"> <rich:validator /></h:inputText><rich:message for="email"/>
Bean:
JSF page:
Cross field 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>
@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>
<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
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');" />
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')" />
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'})"/>
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>
RichFaces Skin file
#ColorsheaderBackgroundColor=#900000headerGradientColor=#DF5858headerTextColor=#FFFFFFheaderWeightFont=bold
generalBackgroundColor=#f1f1f1generalTextColor=#000000generalSizeFont=11pxgeneralFamilyFont=Arial, Verdana, sans-serif
controlTextColor=#000000controlBackgroundColor=#ffffffadditionalBackgroundColor=#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>#{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>
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>
Skinning standard JSF tags and HTML tags
<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>
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>
<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 (Fall 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