Sometimes in a web2.0 projects we would hit upon a road block where the component that we use is so difficult to customize that we had to resort to the use of a similar-but-highly-customizable component from another component library. In those cases, we would also want this exotic component to interact with the rest of the components from a different component library. One scenario that we had to face in our project is to use a rich widget provided by extJS along with the other Richfaces specific widgets on the same JSF page. So, this blog post is about how to integrate richfaces and extJS and pass data back and forth between them.
At the time of this writing I am using the below IDE's and library versions.
1) IDE - Eclipse Ganymede Version: 3.4.2 2.
2) JBoss Tools plug-in for Eclipse.
3) JSF Sun Reference Implementation 1.2_08-b06-FCS and Richfaces 3.2.0.GA.
4) Oracle Weblogic Server 10.3.1.0. 2) JBoss Tools plug-in for Eclipse.
3) JSF Sun Reference Implementation 1.2_08-b06-FCS and Richfaces 3.2.0.GA.
5) Eclipse server adaptor for Oracle Weblogic Server 11gR1.
6) extJS 3.0.3.
6) extJS 3.0.3.
Assmption:
This tutorial assumes the reader would know how to develop a simple JSF web application using Richfaces along with the use of any Javascript library like extJS (See References for preliminary study links on the same).
General behaviour of the screen:
The extJSRichfaces.xhtml will have two widgets, one from Richfaces called rich:dataTable and another from extJS GridPanel. Onload, the rich:dataTable will be populated from a dataSource within the page's Managed Bean. The dataTable has 2 columns, namely, "Account Number" and "Account Name". The "Account Number" column in each row will have a link, if clicked it should render an extJS GridPanel (if not already rendered) and must add the clicked row inside the GridPanel. Similarly, when any row in extJS GridPanel is clicked, then the corresponding row in rich:dataTable must be highlighted with yellow color.
(*Note: This screen behaviour is hardly can be a business requirement but was created to show how to exchange data between two different 'class' of widgets and therefore for demonstration purpose only.)
(*Note: This screen behaviour is hardly can be a business requirement but was created to show how to exchange data between two different 'class' of widgets and therefore for demonstration purpose only.)
Steps:
1. Open Eclipse and go to Window > Show Perspective > Other and choose Web Development and press OK.
2. Along with the default web application views, the "jboss plugin tools" view will be shown.
3. Go to Package Explorer and right click New > JSF Project with
Project Name : extRichPOC,
JSF Environment : JSF 1.2 with Facelets,
Template : FaceletsKickStartWithRILibs,
and click "Next".
JSF Environment : JSF 1.2 with Facelets,
Template : FaceletsKickStartWithRILibs,
and click "Next".
4. Select
Servlet Version : 2.4,
Runtime : Oracle Weblogic Server 11gR1 or if not already present click New Server Runtime and point to the installed Oracle Weblogic home location.
Target Server: Select the Oracle Weblogic Server 11gR1 at localhost or if not already present click New Server and create a Target Server.
(*Note: If Oracle Weblogic Server 11gR1 is not present in the "New Server" panel, then click the "Download additional server adapters" link and download the same.)
Servlet Version : 2.4,
Runtime : Oracle Weblogic Server 11gR1 or if not already present click New Server Runtime and point to the installed Oracle Weblogic home location.
Target Server: Select the Oracle Weblogic Server 11gR1 at localhost or if not already present click New Server and create a Target Server.
(*Note: If Oracle Weblogic Server 11gR1 is not present in the "New Server" panel, then click the "Download additional server adapters" link and download the same.)
5. Add the below 3 richfaces jars to the build path:
richfaces-ui-3.2.0.GA.jar,
richfaces-impl-3.2.0.GA.jar,
richfaces-api-3.2.0.GA.jar
richfaces-ui-3.2.0.GA.jar,
richfaces-impl-3.2.0.GA.jar,
richfaces-api-3.2.0.GA.jar
6. Create a new Java file ExtJSRichfaces.java inside JavaSource folder with a default package.
7. Create a new xhtml file extJSRichfaces.xhtml.
8. Add the below entry in faces-config.xml:
<managed-bean>
< managed-bean-name >extJSRichfaces</managed-bean-name >
< managed-bean-class >ExtJSRichfaces </managed-bean-class >
< managed-bean-scope >request </managed-bean-scope >
< /managed-bean >
9. The below given code snippet in the extJSRichfaces.xhtml needs a little
bit explanation:
. . .
<managed-bean>
9. The below given code snippet in the extJSRichfaces.xhtml needs a little
bit explanation:
. . .
<rich:column styleClass="activitycell" id="col1">
<a4j:commandLink value="#{account.accountNumber}"
data="#{extJSRichfaces.jsonData}"
actionListener="#{extJSRichfaces.accNumClickListener}"
oncomplete="__extJSRichfaces.processJSON(data);">
<f:setPropertyActionListener
value="#{account}"
target="#{extJSRichfaces.selectedAccount}" />
</a4j:commandLink>
</rich:column>
a.
onClick of the link, the actionListener is called, which will create a JSON String.For eg. If link “1” is clicked then the JSON String “[[1,"Account1"]]” is created and set in a property in the MBean called “jsonData”.
(Note*: A very handy class “JSONWriter” from Richfaces library is used to create the JSON String.
This value is assigned to “data” attribute of the a4j:commandLink, which, according to Richfaces documentation, means that there will be a javascript variable called “data” that holds the JSON string as same as in the “jsonData” property in the MBean. onComplete of Ajax response, this “data” variable is passed to the javascript function processJSON().)
b. This value is assigned to “data” attribute of the a4j:commandLink, which, according to Richfaces documentation, means that there will be a javascript variable called “data” that holds the JSON string as same as in the “jsonData” property in the MBean. onComplete of Ajax response, this “data” variable is passed to the javascript function processJSON().)
processJSON() contains the code to create an extJS GridPanel and populate it with the data from the “data” variable. The way that a GridPanel is created inside processJSON() function, is taken from the extJS tutorial for creating stateful Array Grid(http://www.extjs.com/deploy/dev/examples/grid/array-grid.html), with few modification for the sake of this POC.
c.
/* The Richfaces framework attaches a function called ”parseJSON” to the String prototype so that all String instances have this function at their disposal. The parseJSON function converts a “Stringfied” JSON to JSON Object */
if (data)
jsonObj = data.parseJSON();
. . .
jsonObj = data.parseJSON();
. . .
d.
. . .
/*
onClick of any row in the GridPanel will invoke the updateAccountRow
function with an Hashmap containing the column name of the clicked row
as key and column value of the clicked row as its value.
updateAccountRow is tied to the a4j:jsFunction and its parameters to the
a4j:actionparam. So calling updateAccountRow will immediately triggers
the a4j:jsFunction and it updates the MBean’s property tied to
a4j:actionParam. So, onComplete of the Ajax call, the highlightRow
function is called with the “data” variable that will return
whatever value that we initially set in a4j:actionParam. The highlight
of a row in a rich:dataTable can also be done using JavaScript but the
update will happen only on the client side. Here we are using
a4j:jsFunction to demonstrate how we can use JavaScript to call a Java
method of an MBean at server side so the server side component tree is
updated before we update the client side DOM inside highlightRow
function.
*/
__extJSRichfaces.callToJSFBackingBean = function (obj) {
updateAccountRow (obj['accntNumber'], obj['accntName']); onClick of any row in the GridPanel will invoke the updateAccountRow
function with an Hashmap containing the column name of the clicked row
as key and column value of the clicked row as its value.
updateAccountRow is tied to the a4j:jsFunction and its parameters to the
a4j:actionparam. So calling updateAccountRow will immediately triggers
the a4j:jsFunction and it updates the MBean’s property tied to
a4j:actionParam. So, onComplete of the Ajax call, the highlightRow
function is called with the “data” variable that will return
whatever value that we initially set in a4j:actionParam. The highlight
of a row in a rich:dataTable can also be done using JavaScript but the
update will happen only on the client side. Here we are using
a4j:jsFunction to demonstrate how we can use JavaScript to call a Java
method of an MBean at server side so the server side component tree is
updated before we update the client side DOM inside highlightRow
function.
*/
__extJSRichfaces.callToJSFBackingBean = function (obj) {
}
. . .
. . .
References
1) http://java.dzone.com/articles/an-introduction-to-jboss-richf (A good introduction to using Richfaces component library with JSF application)
2 comments:
Hi I'm testing your code but It doesn't work for me at all. I debugged and it fails in js code here jsonObj = data.parseJSON ();
Because richfaces doesn't recongnize parseJSON function. I'm using the same versions of libraries you mention in this article
richfaces 3.2.0 and ext 3.03.
Any idea?
thanks
Nacho
Hi I'm trying your code but I didn't work properly. It fails in js code
jsonObj = data.parseJSON ();
Because richfaces doesn't recognize parseJSON function.
I'm working with the same version of libraries richfaces 3.2.0 and extjs3.0.3.
Any idea?
thanks
Nacho
Post a Comment