BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage Articles Creating dynamic web applications with JSF/DWR/DOJO

Creating dynamic web applications with JSF/DWR/DOJO

This item in japanese

Bookmarks

Abstract

This article gives an approach on how JSF, DWR, DOJO can be integrated to create rich web applications which use Portlets and Facelets. It is assumed that the readers have a basic understanding of these frameworks and the features they provide.

Sample Application

The sample application that is discussed in this article is a product management application. The application provides its users the following features:

  1. The user can search for a product type based on name
  2. When the user selects a product then a new screen is shown to the user with a split pane. The left side of the split pane shows all the product subtypes that belong to that product type, in the form a Tree (as you see in Windows Explorer). It is possible that each product subtype may have its own subtypes. The right side of the pane shows a tabbed pane with tabs labeled:
    • Products - this tab shows the list of products that belong to the selected subtype
    • Add Product Subtype - this tab shows a form that accepts values to add a new product subtype to the selected product subtype
    • At the bottom of the split pane there is a back button provided to go back to the search product type page.
  3. When a list of products associated with a subtype are shown on the right side of the split pane, then it should show only 10 products on a single page. This means it should be possible to do pagination and sorting of results on the screen.
  4. The Tree shown on the left side of the split pane should be expandable/collapsable and it shouldn't result in page refresh and thus enhancing the user experience.
  5. Right clicking any node (representing a product subtype) in the Tree should show the user with a popup menu with options to add a new product subtype as a child of the selected subtype, remove the selected product subtype, refresh the list of child product subtypes of the selected product subtype with latest data from the database, etc.
  6. When a new product subtype is added to a selected product subtype then the new product subtype should immediately show up in the Tree without page refresh.

Figure 1 shows how the screen is expected to look when the user selects a product type/subtype.

Fig 1. The product subtype details screen

DOJO

Creating cross-browser compatible tree structures, tabbed panes, split panes, popup menus, etc is time consuming and at the same time can be best done by an experienced Javascript/DHTML programmer. There are many toolkits that provide these UI widgets and are cross-browser compatible but not many provide a rich event handling model. The following lists some of the user actions that the sample application needs to repond to meet the user requirements:

User Action Application Response
Select a tree node Show the list of product subtypes that belong to this node
Right click a tree node Show a popup menu with options to add a child product subtype, remove the selected product subtype, etc
Select 'Add Product Subtype' tab in the tabbed pane Show form to enter new product subtype information
When user clicks the [+] sign to expand the tree and view the child nodes Loads child nodes information from the database and displays in the tree

The DOJO toolkit is a Javascript/DHTML toolkit which provides a rich set of UI widgets (including but not limited to tree, tabbed pane, popup menu) with a rich event handling model which makes it suitable for use in the sample application.

DWR

DWR ( Direct Web Remoting ) is an AJAX framework that simplifies building AJAX applications in Java. DWR provides many features which includes, but not limited to:

  • Creating Javscript from a Java class (that the developer creates to handle AJAX requests)
  • Allows a JSF managed bean to act as Java class that handles the AJAX requests
  • Conversion of Javascript associative arrays into Java beans and vice-versa using converters
  • Conversion of Javascript arrays to Java Collections and vice-versa using converters

The converters in DWR play a very important role and provide a cleaner programming model. For example, if the user enters the new product subtype information and requests the application to save it then there are two ways to retrieve this information in web layer:

  • Use HttpServletRequest's getParameter method to retrieve all the information about the new product subtype.
  • Create a DTO ProductSubtype which has getters and setters for all the attributes of a product subtype. Configure a converter in dwr.xml file which specifies ProductSubtype as a bean converter. In Javascript, simply create an associative array and pass it to the Java class (which handles the AJAX request) method which accepts ProductSubtype as a parameter. In this case DWR will do the conversion from the Javascript associative array to ProductSubtype because ProductSubtype was declared to use the bean converter in DWR.

The later option provides a cleaner programming model and you don't have to deal with retrieving request parameters and creating a DTO to be used in Java program.

When an AJAX request is processed, most of the times its required to receive a status code, message or some data in the Javascript callback method, to decide on what to show or what not to show to the user. The bean converter comes very handy in such scenarios.

DOJO's rich event model coupled with DWR's clean approach towards handling AJAX requests in Java application provides a way to create highly interactive web applications (like the sample application) in which the events generated by the DOJO components are passed to DWR for processing.

Problem Description

  1. In a Portal environment, the developer is not responsible for generating the HTML for the user interface, its generated by parsing the XHTML files that correspond to the Facelets. Even if a JSF managed bean's property contains HTML string as its value, it is not parsed by the Portal and is shown as is to the user on the user interface. How to generate DOJO specific HTML that can be executed by the web browser to create the UI widgets ?
  2. DOJO provides rich event model and it is possible to intercept these events in Javascript. The DWR framework can be used to receive these events on the server side but where the conversational state needs to be maintained on the server side ?
  3. The Javascript takes time to create DOJO tree nodes in IE or Mozilla when the number of nodes in the Tree is more than a few hundreds. So does it mean that applications can't use DOJO tree widgets in browsers if the number of nodes is more than a few hundreds ?
  4. When using AJAX in a web application then how to generate the HTML or HTML fragment when a user event occurs on the screen ? This should be coded in the Java code or picked from an external file ? Can the application show a complex user interface in response to a AJAX request ?
  5. When using AJAX the code may get clutterred with getParameter("fieldName") method of HttpServletRequest and thus it will not be easily maintainable

Solution Approach

Custom JSF component

Custom JSF components were used to generate the necessary HTML for the Tree and Split Container components of DOJO. The HTML generated by JSF components is always parsed by the browser and is not output as a text by the Portal. The following portion of XHTML file shows how the custom JSF compoenent was used to generate the DOJO's tree and tabbed pane widgets.

<div xmlns="http://www.w3.org/1999/xhtml"
...
...
xmlns:dojo="http://dojotoolkit.org/"
xmlns:mytree="http://mytree.com/tree"
xmlns:mytab="http://mypane.com/tabPane">
<ui:composition>
<ui:define name="body">
<f:view>
<h:form styleClass="form" id="formId">
<div dojoType="SplitContainer" orientation="horizontal" sizerWidth="5" activeSizing="false" style="overflow:
auto; whitespace: nowrap; height: 550px; background: transparent; padding: 5px;" >
<div dojoType="ContentPane" sizeShare="20"
style="overflow: auto; whitespace: nowrap;">
<mytree:treeComponent backingBeanName="treeBackingBean"></mytree:treeComponent>
</div>
<div dojoType="ContentPane" sizeShare="80" style="overflow: auto; white-space nowrap;">
<mytab:tabPaneComponent/>
</div>
</div>
...
...

If the number of tree nodes is large ( more than 200 ) then the custom JSF component must not generate code for more than 200 nodes. If the number of nodes is more than 200 then its seen that IE takes substantial time to create these widgets when loading the page. The sample application's custom JSF component created only 100 tree nodes ( at the root level ) and showed the option 'Show more...' in the end. When the user selected the 'Show More..' option then it becomes the responsibility of DWR to fetch the information about remaining nodes from the database. This information was then passed to the Javascript callback method to programmatically create the TreeNode widgets.

MyFaces also provides components that generate DOJO Tree but the MyFaces component creates all the nodes in one go, which is not a good approach because the component becomes useless in web applications when the number of tree nodes runs into thousands.

DWR and JSF

DWR requires that you create a Java class and configure that class in the dwr.xml configuration file. DWR creates a Javascript file (.js file extension) with a name that is configured in dwr.xml.

The following configuration information from dwr.xml shows how a Java class is configured:

<create creator="jsf" javascript="AjaxBean" scope="request">
<param name="managedBeanName" value="ajaxBean" />
<param name="class"
value="com.somebean.AjaxBean" />
</create>

creator="jsf"

This means that the Java class is configured as a JSF managed bean. This Java class will contain all the AJAX methods that will be invoked by the Javascript.

<param name="managedBeanName" value="ajaxBean" />

This means that the name of the managed bean in faces-config.xml configuration file is ajaxBean.

<param name="class"
value="com. somebean.AjaxBean" />

This refers to the actual Java class.

javascript="AjaxBean"

This is the name with which the Java class is referred by the Javascript code.

To make use of the AjaxBean in the Javascript code, it is required to import this Javascript using the <script> tag.

DWR Java classes (DWR Java classes are nothing but plain Java classes. These classes don't implement any DWR specific interfaces or classes.) are instantiated evertime an AJAX request is received. This means that if the application has to maintain state in AjaxBean class then it will be erased when a new request comes. The methods in the AjaxBean are expected to be stateless in nature and the conversational state must be maintained somewhere else.

The AJAX request is not a PortletRequest, which means that the DWR Java classes don't have access to PortletSession object. AJAX requests are simple HTTP requests, therefore, DWR Java classes can access HttpSession object. According to the Portal Specification, it is required that the HttpSession and PortletSession objects should be in sync, i.e., if an attribute is added to a PortletSession object then it should also be added to HttpSession object (not necessarily with the same name).

For example, in case of JBoss AS, when a managed bean is added to the PortalSession with the name someManagedBean then the same object is available through HttpSession with the attribute name javax.portlet.p.<portletInstanceName>?someManagedBean.

In the sample application, the conversational state is maintained in the someManagedBean. The DWR Java classes obtain the instance of someManagedBean from the HttpSession object and set its properties to reflect the current conversational state of the user.

To access the business services ( lets say in the Spring layer ), the AjaxBean can make use of Service Locator pattern to interact with the business services.

NOTE: A JSF managed bean is instantiated only after it receives a faces request. So make sure that the JSF managed bean that you are going to use for storing the conversational state has already received a faces request. The scope of this managed bean should be 'session'.

HTML templates

One of the problems that is faced in working with AJAX is creation of complex HTML fragments based on user actions. This normally results in high-maintenance applications and sometimes its very difficult to even change the user interface as the application requirements are refined over a period of time. HTML doesn't have a concept of tiles, but something similar to tiles can be done in the sample application.

<table style="height: 80%; width: 100%; padding-bottom: 100px; visibility: {0};">
<tr valign="top">
<td>
<table align="left" valign="top">
<tr>
<td class="formLabel">Product Category:</td>
<td class="formField">{1}</td>
</tr>
<tr>
<td class="formLabel"><span class="required">*</span>Description:</td>
<td class="formField"><textarea rows="2" id="desc_field" cols="80"
name="desc_field"></textarea></td>
</tr>
<table>
<tr>
<td>{dataTable}</td>
</tr>
<tr>
<td>{dataScroller}</td>
</tr>
</table>
<tr valign="bottom">
<td align="right" style="padding-right: 50px;">
<table>
<tr>
<td><input type="button" class="inputButton" onclick="saveDetails('{2}');" value="Save"/></td>
</tr>
</table>
</td>
</tr>
...
...

The above HTML template file shows the two types of placeholders:

  1. Data placeholders
  2. HTML placeholders

The placholders {0}, {1} and {2} represent data placeholders, and are easily filled by having a static method like:

public static String getStringWithValues(String template, Object[] values) throws IncorrectNumberOfValues {
for(int i = 0; i < values.length; i++) {
int index = template.indexOf("{" + i + "}");
if(index == -1) {
throw new IncorrectNumberOfValues("The number of values passed is : " + values.length + "
which doens't match the number of placeholders in : " + template);
} else {
if(values[i] != null) {
template = StringUtils.replace(template, "{" + i + "}", values[i].toString());
} else {
template = StringUtils.replace(template, "{" + i + "}", "");
}
}
}
return template;
}

where, template is the html template that needs to be parsed and placeholders removed with the value in the values array. So, the data placeholder {0} is removed by the 1st element in the values array, the data placeholder {1} is removed by the 2nd element in the values array, and so on.

The placholders {dataTable} and {dataScroller} represent HTML placeholders and are expected to be replaced by an HTML fragment. The {dataTable} placholder is supposed to be replaced by a data table which shows records corresponding to each product that is part of the product category. The HTML corresponding to {dataTable} is in another HTML template. There are a couple of approaches in which the HTML placeholders can be replaced by the corresponding HTML templates:

  1. Programmatically: Inside the ajax beans the placeholders can be replaced by the HTMLs. This approach doesn't require creating any kind of a framework.
  2. Creating a mapping between a placeholder and HTML template in a properties file or an XML document. For example, a properties file may be created to contain the following mapping: {dataTable} = /WEB-INF/classes/templates/dataTableTemplate.html {dataScroller} = /WEB-INF/classes/templates/dataScroller.html

At runtime these placeholders can be replaced by the corresponding templates. This approach requires creating a small framework which reads in the properties file and parses the HTML templates to replace HTML placeholders by corresponding HTML files.

DWR bean converter

Web applications normally use DTOs to pass information from Web layer to the Service layer. The sample application uses another level of DTOs which pass information from Javascript to the Web layer. For example, when searching for product a user can enter the following information: product name, product code, product id and also the corresponding type of search (LIKE or EQUALS). These parameters are passed to the Web layer of sample application using the DTOs. The concept of associative arrays (i.e., named arrays) in Javascript is used to set these parameters and then DWR does the conversion from these associative arrays to corresponding DTO. The names in the associative array must match with the properties in the DTO.

The following configuration in dwr.xml shows how to configure a DTO:

<convert match="com.search.product.SearchCriteria" converter="bean"/>

Use of this approach makes the Java code cleaner on the server side because no longer you have to explicitly obtain values corresponding to each request parameter that came with the AJAX request.

JSF's rendered attribute

All JSF HTML tags have a rendered attribute, the boolean value of which decides whether the HTML widget will be shown to the user or not. This same functionality can be achieved when working with HTML templates. This will require creating an expression framework which parses the expressions in HTML and show/hide an HTML fragment.

<exp:if value="someManagedBean.permissions.save">
<td><input type="button" class="inputButton" onclick="removeProduct('{0}');" value="Remove" /></td>
</exp:if>

FacesRequest or HttpServletRequest for navigation

When the user clicks the back button on the product details page then the product search page needs to be shown. If clicking the back button is handled using an AJAX request then the application isn't taking the advantage of the navigation rules defined in the faces-config.xml file. So, it's a good idea to use the HTML button component of JSF on the product details page rather than using an HTML button which sends an HttpServletRequest (or AJAX request) to the server to navigate to another page.

Alternatives considered

Ajax4jsf

Ajax4jsf provides way for JSF components to use AJAX, but the Portlet support came with version 1.1.1. At the time of creation of sample application the ajax4jsf didn't support Portlets.

HTML and CSS based trees

It's possible to use a combination of <li> HTML element and CSS to create a tree structure. But these tree structures lack any kind of event handling model and therefore can't meet the requirements of a highly interactive tree widget.

RichFaces

RichFaces provides rich JSF components with AJAX functionality. RichFaces use Ajax4jsf for achieving AJAX functionality.

About the Author

Ashish Sarin has over 8 years of experience in developing / designing Java based web applications.

References

Dojo
Dojo is an open source DHTML toolkit written in Javascript. For more info please refer to http://www.dojotoolkit.org/about.

DWR
DWR or Direct Web Reporting allows easy use of Ajax in Java applications. For more info please refer to http://getahead.org/dwr/documentation.

RichFaces
http://labs.jboss.com/jbossrichfaces/.

Ajax4jsf
http://labs.jboss.com/jbossajax4jsf/.

Facelets
https://facelets.dev.java.net/.

Rate this Article

Adoption
Style

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Community comments

  • Checkout IceFaces

    by Hisham Ghazouli,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    Ice Faces provides JSF/AJAX support with lots of nice widgets. Much more the Rich Faces provides.

  • Re: Checkout IceFaces

    by Kito Mann,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    Hmm.. There are lots of JSF component libraries out there with portlet support and Ajax these days.. Seems like it'd be less work.

    ~~~
    Kito D. Mann - Author, JavaServer Faces in Action
    www.virtua.com - JSF/Java EE consulting, training, and mentoring
    www.JSFCentral.com - JavaServer Faces FAQ, news, and info

  • Re: Checkout IceFaces

    by prassee sathian,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    Yes, but ice faces uses a jsp xml but rich faces can be integrated on the fly with little effort

  • Re: Checkout IceFaces

    by Ric Smtih,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    I agree with Kito. This seems like way too much work when I could use an existing component set, whether it be ICEFaces, BackBase, RichFaces, or ADF Faces (sorry if I missed any others).

    -------
    Ric Smith - Principal Product Manager, Oracle USA

  • Re: Checkout IceFaces

    by Ashish Sarin,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    AJAX-JSF components that are available these days can meet most of the requirements of rich web applications.
    The rich component model that comes with DOJO can make things a bit complex from programming perspective but it provides maximum flexibility. I can give some more scenarios that some of the available AJAX-JSF components may not be able to address(without screen refreshes):
    - right clicking a tree node should show a popup menu with options to refresh its content or add a subnode to the selected node
    - selecting a node should show details of the description in one of the panes in the tabbed pane.
    - Editing the node details should reflect the changes in the tree node immediately

    Apart from this, there are no AJAX-JSF components that can help a developer show complex HTML page as a response to an AJAX request. The response lacks the power that comes with web technology like JSP. To show a complex page it is therefore required to have some expression evaluation mechanism and tiles feature to dynamically construct the page.

  • source code

    by bill dussler,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    Is the source code for this example application available?

  • same thing doing using icefaces, sample code utterly needed

    by Ashok Kumar,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    hi ashish,

    Plz send the code for above dojo,jsf implementation, as i utterly needed it in my development, grate ful to u.

    regds
    Ashok

  • Re: Checkout IceFaces

    by Ashok Kumar,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    hi hisham,

    how can i get popup menu on right click in icefaces.kindly send the code

    Thank you.

    Ashok

  • Source Code

    by ah md,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    Is Source code available for the sample project?
    Thanks,
    Ahmed

  • Re: Checkout IceFaces

    by Georges Goebel,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    Hi,

    It's quite simple to integrate third party libraries in the ICefaces JSF framework.
    I did it once with the spinner and fisheye components from dojo. You can easily integrate them as custom components in icefaces. You will have (in quite a short periode of time) custom JSF components. All the dojo (or other library) configuration or handling is transparent to the developper who uses the components.

    You find my examples in the icefaces forum :

    Hi,

    There is hope for your wishes :-)

    I integrated the spinner component form dojo in icefaces. So basicly the spinner component is available.

    The tab slider (accordion) component is also available in dojo (dijit) and other fancy components (dojocampus.org/explorer/#Dijit). So, integrating all the dojo components is possible but takes some time.

    I also integrated the fiseye component (www.dojotoolkit.org/demos/fisheye-demo) from dojo. Yes I know it's not so usefull an mostly eyecandy but it's quite impressive for demos :-)

    I have no idea if the Icefaces guys will integrate the dojo/dijit components or if they will do their own components but it is possible to do so.

    So you can take the code and improve it (mostly my JS, I hate JS (there was even funny TS which I missed at the JavaOne "JavaScript Programming Language: The Language That Everybody Loves to Hate") )


    www.icefaces.org/JForum/posts/list/8506.page
    www.icefaces.org/JForum/posts/list/8450.page
    jira.icefaces.org/browse/ICE-1786

    Georges Goebel


    Georges Goebel

  • Re: Checkout IceFaces

    by Georges Goebel,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    Sorry I made a copy/paste error from the forum :-(

    Hi, It's quite simple to integrate third party libraries in the ICefaces JSF framework. I did it once with the spinner and fisheye components from dojo. You can easily integrate them as custom components in icefaces. You will have (in quite a short periode of time) custom JSF components. All the dojo (or other library) configuration or handling is transparent to the developper who uses the components. You find my examples in the icefaces forum

    Georges Goebel

    www.icefaces.org/JForum/posts/list/8506.page www.icefaces.org/JForum/posts/list/8450.page jira.icefaces.org/browse/ICE-1786

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

BT