JSF is a popular Web framework that is quite stable and has been widely used in the Java™ Platform, Enterprise Edition (Java EE) domain. Dojo is one of the most powerful Web 2.0 libraries and gives you the ability to create rich interfaces for your Web applications.
By leveraging both technologies, you gain the strengths of both technologies. On the server side, the benefits include end-to-end lifecycle management for components, back-end bean data binding, and event handling. On the client side, you can utilize Dojo's rich widgets, live animations (such as fade and slide), and drag-and-drop. Additionally, with the Dojo framework's API support you can improve performance by putting more logic on the client side.
This article introduces the following approaches for leveraging JSF and Dojo technologies:
- Deferred binding of JSF components and Dojo widgets on the client side
- Building a customized JSF component to enable Dojo widgets
- Lazy injection and parsing of JSF components as Dojo widgets
The sample JSF application in this article is composed of two pages: Create Project and Project Result. Figure 1 and Figure 2 show these two pages. To make it simple and easy to understand, the samples shown in these figures are used in all the approaches described in this article to demonstrate how to combine Dojo with a JSF application. (You can also view a larger version of Figure 1.)
Figure 1. Create project

Figure 2. Project result

The scenario is really quite simple. The user can enter some information to create a project, and when they click the submit button, the project information is displayed. So your task is to convert the input box, text area, and other JSF components into Dojo widgets.
Approach 1: Deferred binding of a JSF component and a Dojo widget on the client side
This approach is the simplest way to apply the Dojo style to the JSF component. We just use JavaScript to bind the JSF component and Dojo widget together on the client side. By using JavaScript, the data can be transferred and will be consistent between the JSF component and the Dojo widget.
First, take a look at the original JSF page. Listing 1 shows the JSF code. (The code in Listing 1 has been formatted to fit the article. Click here to see the entire code listing.)
Listing 1. Original Create Project JSF page
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://www.ibm.com/jsf/html_extended" prefix="hx"%>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<body>
<f:view>
<h2>Make your JSF application Dojoable</h2>
<h3>Create Project</h3>
<h:form id="project">
<table>
<tbody>
<tr>
<td>Project Name:</td>
<td><h:inputText id="projectName"
value="#{projectFormBean.projectName}" size="5"/></td>
</tr>
<tr>
<td>Project description:</td>
<td><h:inputTextarea id="projectDescription"
value="#{projectFormBean.projectDescription}" rows="2"
cols="15"/></td>
</tr>
<tr>
<td colspan=2>
<h:commandButton id="button_submit" action="success"
value="Submit" type="submit"></h:commandButton>
</td>
</tr>
</tbody>
</table>
</h:form>
</f:view>
</body> |
There
are two input fields: project name and project description. These two fields are all bound with the
back-end form bean projectFormBean.
Let's begin to convert this page with a Dojo style.
Step 1. Hide the JSF component and add the Dojo widget
You need to hide the original JSF components and change them to invisible, and then add the related Dojo widgets in this page. Your first step is to import the Dojo library and declare which widgets are needed, as shown in Listing 2. (The code in Listing 2 has been formatted to fit the article. For the complete code, click here.)
Listing 2. Import Dojo library and declare the widgets
<style type="text/css">
@import url("${pageContext.request.contextPath}/script/
dojo_lib/dijit/themes/tundra/tundra.css");
@import url("${pageContext.request.contextPath}/script/dojo_lib/
dojo/resources/dojo.css");
</style>
<script type="text/javascript" src="${pageContext.request.contextPath}/script/
dojo_lib/dojo/dojo.js"
djConfig="parseOnLoad: true, isDebug:false"></script>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.form.ValidationTextBox");
dojo.require("dijit.form.Textarea");
</script> |
In
this sample, we use the tundra theme as the default style, so you must
first import the tundra.css and the dojo.css. Next, you need to import the
dojo.js
file, which is the main js script file for Dojo. Finally, you must
declare which widgets you want to use. In this case, we'll use validationTextBox and Textarea. Dojo uses the on-demand mechanism. It will only
load the required files according to the declaration. Therefore, it can improve
the application's performance and reduce the network transfer.
The next step is to change the JSF components to be invisible and add the Dojo widgets for display. The modified jsp is shown in Listing 3.
Listing 3. Change the JSF components to invisible and add the Dojo widget
<tr>
<td>Project name:</td>
<td><h:inputHidden value="#{projectFormBean.projectName}"/><f:verbatim>
<input type="text" name="projectName"
dojoType="dijit.form.ValidationTextBox"
regExp="[\w]+"
required="true"
invalidMessage="Invalid project name."/></f:verbatim>
</td>
</tr>
<tr>
<td>Project description: </td>
<td><h:inputHidden value="#{projectFormBean.projectDescription}"/><f:verbatim>
<textarea dojoType="dijit.form.Textarea" style="width:80%">
</textarea></f:verbatim>
</td>
</tr> |
We
change the original JSF components to inputHidden, but still bind with the back-end projectFormBean data. After this hidden
component, we add the corresponding Dojo widgets. For the "project name"
field, we use a validationTextBox to validate
the input box on the client side, and for the "project description" field, we
the use dojo textarea, which can be auto-expanded
without a scroll bar.
Step 2. Copy data from the JSF components to the Dojo widgets during the page render phase
Earlier, we replaced the JSF components with Dojo widgets in the page, but the data in the page is not shown in the Dojo widgets. Next we will show you how to copy the data from the JSF components to the Dojo widgets.
In the render phase, we use JavaScript to extract the data from the JSF components and set it to the related Dojo widgets. Listing 4 shows the JavaScript codes.
Listing 4. Copy data from JSF components to Dojo widgets during the render phase
<script type="text/javascript">
function dojoInit(){
dijit.registry.byClass('dijit.form.ValidationTextBox').forEach(function(pane){
pane.setValue(pane.domNode.previousSibling.value);
});
dijit.registry.byClass('dijit.form.Textarea').forEach(function(pane){
pane.setValue(pane.domNode.previousSibling.value);
});
}
dojo.addOnLoad(dojoInit);
</script> |
In
the dojoInit function you will find all the Dojo
widgets queried by the class name. For each widget, you find its
previous sibling node in the Dom tree, which is the JSF component. Then
you extract the data from the JSF component and set it to the queried
Dojo widget. In this way, you can synchronize the data between the JSF
components and Dojo widgets. Finally, you use the dojo.addOnLoad function to make sure the dojoInit function is called during the render
phase.
Note: When using the Dojo Toolkit, you should avoid using
<body onload="..."> or window.onload because Dojo has its own initialization mechanism that uses window.onload. Using this mechanism yourself will
interfere with Dojo's initialization routines. Dojo has provided dojo.addOnLoad, which lets you load
functions after Dojo has finished its own initialization.
Step 3. Copy data from the Dojo widgets to the JSF components during the page submit phase
Currently, the dojo widgets can be shown with correct data in the page. But if a user changes the data, how can these changes be reflected to the corresponding back-end form bean? In this step, we show how to synchronize the data between Dojo widgets and JSF components during the page submit phase.
First, you must create a JavaScript function to copy the data from the Dojo widgets to JSF components. The code is shown in Listing 5.
Listing 5. Copy data from the Dojo widgets to JSF components
function setDojoValue(){
dijit.registry.byClass('dijit.form.ValidationTextBox').forEach(function(pane){
pane.domNode.previousSibling.value = pane.getValue();
});
dijit.registry.byClass('dijit.form.Textarea').forEach(function(pane){
pane.domNode.previousSibling.value = pane.getValue();
});
} |
This
function is similar to the dojoInit
function shown in Step 2. We still use the dojo query method to find all
dojo widgets by a specified class name. Then, we extract the data from
these Dojo widgets and set it to corresponding JSF components.
Next, we must invoke the setDojoValue
function when the page submits, so we change the original submit
button as shown in Listing 6.
Listing 6. Submit button combined with JavaScript function
<h:commandButton id="button_submit" action="success"
value="Submit" type="submit" onclick="setDojoValue();"></h:commandButton> |
We
add the onclick attribute in the JSF commandButton, so when a user clicks on this
button the JavaScript function will be invoked first, then the page will
be submitted. In this way, we can copy all data in the Dojo widgets to JSF
components before the page is submitted, and the data changes will be
reflected to back-end form beans.
That is all you need to do using this approach. Figure 3 shows the new Create Project page.
Figure 3. Create project using Approach 1

As you can see, we use a validated input box that can support client-side
validation. We also use the dojo textarea, which
can be auto-expanded without a scroll bar.
Approach 2: Build customized JSF component to enable the Dojo widget
JSF is a powerful Web framework. It not only provides standard user interface components for Web applications, but it is also a very flexible API that allows for user customization. In this section, we explain how to develop your own JSF components combined with a Dojo style.
Typically, the JSF component will contain the following parts:
- UIComponent Class: A class derived from either
UIComponentBaseor other existing JSF components such asoutputText. This class represents the core logic of the entire JSF component. - Render Class: This class is used for rendering the component. Typically, it will deal with how to generate the HTML codes for rendering, so it is critical for this section. We need to change this class and let it generate the Dojo-style HTML code.
- UI Component Tag Class: This is a JSP tag handler class that lets the UI Component be used in a JSP page. It can also associate a separate render class with a UIComponent class.
- Tag Library Descriptor File: This is a standard JavaEE JSP tag library descriptor (tld) file that associates the tag handler class with a usable tag in a JSP page.
We'll continue to use the create project scenario as an example, and we will show how to create an input text JSF component with dojo validation functionality.
First, take a look at the customized JSF tag. Listing 7 shows how to use the customized JSF tag in a Web application:
Listing 7. Using a customized JSF tag
<h:form id="project">
<table>
<tbody>
<tr>
<td>Project Name:</td>
<td>
<jsfdojo:input id="projectName" type="text"
invalidMessage="Invalid project name."
dojoType="dijit.form.ValidationTextBox"
dojoRequired="true"
regExp="[\w]+"
value="#{projectFormBean.projectName}"/>
</td>
</tr> |
Figure 4 shows the Web page using this approach. (You can also view a larger image of Figure 4.)
Figure 4. Create project – Approach 2

To develop your own JSF input box with a Dojo style, you can use the existing JSF input box as a guide, so you do not need to implement your own UIComponent class; you can reuse the existing one. You do need to implement the render and tag classes, but that's not very difficult. You can inherit the existing JSF APIs and will only need to override a few functions.
Listing 8 shows the code of the tag class that is used for handling the tag in the JSP page. It also associates the UIComponent and Render class.
Listing 8. Tag class
public class InputTag extends InputTextTag {
@Override
public String getComponentType() {
return "javax.faces.HtmlInputText";
}
@Override
public String getRendererType() {
return "jsfdojo.input.render";
}
private String dojoType;
private String invalidMessage;
private String regExp;
private String type;
private String dojoRequired;
public String getDojoRequired() {
return dojoRequired;
}
public void setDojoRequired(String dojoRequired) {
this.dojoRequired = dojoRequired;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getRegExp() {
return regExp;
}
public void setRegExp(String regExp) {
this.regExp = regExp;
}
public String getDojoType() {
return dojoType;
}
public void setDojoType(String dojoType) {
this.dojoType = dojoType;
}
public String getInvalidMessage() {
return invalidMessage;
}
public void setInvalidMessage(String invalidMessage) {
this.invalidMessage = invalidMessage;
}
@Override
protected void setProperties(UIComponent component) {
super.setProperties(component);
component.getAttributes().put("dojoType", dojoType);
component.getAttributes().put("dojoRequired", dojoRequired);
component.getAttributes().put("invalidMessage", invalidMessage);
component.getAttributes().put("regExp", regExp);
component.getAttributes().put("type", type);
}
} |
The
tag class is inherited from InputTextTag. You
need to override some functions and add some new fields for the new
attributes used in this tag.
The getComponentType function specifies the UIComponent class and the
getRendererType function specifies the Render
class. Therefore, if the JSF component has separated the render class, in the tag
class these two functions are used to link them together.
The
fields in the tag class represent the attributes that are used in the JSP
tag. The setProperties function is used to
store these attributes in the attribute's map of this component. This map
will be used in the render class.
As described above, we will implement a separated render class. This class is responsible for generating the HTML codes for rendering in the Web page. Listing 9 shows the code of this render class.
Listing 9. The separated render class
public class InputRender extends TextRenderer {
@Override
public void encodeEnd(FacesContext context, UIComponent component)
throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.startElement("input", component);
String id = (String) component.getClientId(context);
writer.writeAttribute("id", id, "id");
writer.writeAttribute("name", id, "id");
writer.writeAttribute("value", getValue(component), "value");
writer.writeAttribute("type", (String)
component.getAttributes().get("type"), null);
writer.writeAttribute("dojoType", (String)
component.getAttributes().get("dojoType"), null);
writer.writeAttribute("required", (String)
component.getAttributes().get("dojoRequired"), null);
writer.writeAttribute("invalidMessage", (String)
component.getAttributes().get("invalidMessage"), null);
writer.writeAttribute("regExp", (String) component.getAttributes().get("regExp"), null);
writer.endElement("input");
}
protected Object getValue(UIComponent component) {
Object value = null;
if (component instanceof UIInput) {
value = ((UIInput) component).getSubmittedValue();
}
if (null == value && component instanceof ValueHolder) {
value = ((ValueHolder) component).getValue();
}
if (value == null) {
value = "";
}
return value;
}
} |
The
tag class is inherited from TextRenderer, so
you don't need to worry about the decoding issue. All you need to do is
implement the encoding output, which is implemented by the
encodeEnd function. In this function, the
ResponseWrite object makes it easy to
generate the HTML codes. For the new adding attributes such as type, dojoType,
required, invalidMessage and regExp, the
value for these attributes are retrieved from the component's attribute
map, which is set in the tag class.
The value of the value attribute is retrieved
from the UIComponent, which is implemented in the getValue function.
After implementing the tag and render class, you also need to define the tag library descriptor file (tld file) for this JSF component. Listing 10 shows the contents of this tld file.
Listing 10. The tag library descriptor file – tld file
<taglib>
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>jsfdojo</short-name>
<uri>http://jsfdojo.ibm.com</uri>
<tag>
<name>input</name>
<tag-class>jsf.input.InputTag</tag-class>
<body-content>empty</body-content>
<description>
</description>
<attribute>
<name>dojoType</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<description>
</description>
</attribute>
<attribute>
<name>dojoRequired</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<description>
</description>
</attribute>
<attribute>
<name>type</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<description>
</description>
</attribute>
<attribute>
<name>invalidMessage</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<description>
</description>
</attribute>
<attribute>
<name>regExp</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<description>
</description>
</attribute>
<attribute>
<name>value</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<description>
Value reference expression pointing the attribute that
will have the credit card number.
</description>
</attribute>
……
</tag>
</taglib> |
In
this tld file, the "tag class" field specifies the implemented tag class.
It also describes the attributes that will be used in this tag. In this
case, we add several new attributes: dojoType,
dojoRequired, type, invalidMessage, and regExp. There are also many super class
attributes such as id, value, and so on.
Finally, you need to register the new component in the faces-config.xml file. Listing 11 shows the register section of this component.
Listing 11. Register the JSF component in faces-config.xml
<render-kit>
<renderer>
<description>
Renderer customized input with dojo style
</description>
<component-family>javax.faces.Input</component-family>
<renderer-type>jsfdojo.input.render</renderer-type>
<renderer-class>
jsf.input.InputRender
</renderer-class>
</renderer>
</render-kit> |
The component family and renderer type fields are mapped exactly with the functions in the tag class. Listing 12 shows these functions.
Listing 12. Overriding component and renderer fields
@Override
public String getComponentType() {
return "javax.faces.HtmlInputText";
}
@Override
public String getRendererType() {
return "jsfdojo.input.render";
} |
That is all you need to do to implement your own JSF component. It involves a few different classes and xml implementations, but it is quite straightforward and not complicated, especially when based on the existing component. In this case, we just add some new attributes and override the encoding function to generate Dojo HTML codes.
Approach 3: Lazy injection (Post-parse the JSF component into a Dojo widget)
This approach is performed completely on the client side using JavaScript, but it's quite different from the first approach in this article. Lazy injection means injecting Dojo widget information into the JSF component after the whole page is loaded. Then, the Dojo parser is used to parse the JSF component and convert it into a Dojo widget. During the injection process, a handler may be registered, which will be invoked later when the JSF form is submitted. In this way, the precise data can be transferred back to a corresponding JSF listener on the server side. Figure 5 shows the detail workflow of this approach. (You can also view a larger image of Figure 5.)
Figure 5. Workflow of the Lazy injection approach

Step 1: Inject Dojo widget information into the JSF component.
You may have already
noticed that a JSF component is translated to HTML tags after the
entire page finishes loading. For example, Listing 13 is the syntax of the
JSF inputText component. After the page is
loaded, the inputText component is
translated to HTML tags, as shown in Listing
14.
Listing 13. Syntax of the JSF inputText component
<td>
<h:inputText id="projectName" value="#{projectFormBean.projectName}" size="5"/>
</td> |
List 14. Generated HTML tags for the JSF inputText component
<td>
<input type="text" name="project:projectName" id="project:projectName" size="5"/>
</td> |
So, the idea is quite straightforward. Add the necessary widget information to the
generated HTML tags so the Dojo parser can recognize and parse it to
a Dojo widget. Additionally, to differentiate normal HTML tags and those
generated from the JSF component, a special attribute, jsf2dojo='true', is marked on the wrapper node of the JSF
component. Listing 15 shows the updated JSF page for the Create Project
sample. You can see more details in the NewProject_lazy_inject.jsp file.
Listing 15. Updated JSF page with jsf2dojo='true' attribute
<tr>
<td jsf2dojo='true'>
<h:inputText id="projectName" value="#{projectFormBean.projectName}"
size="5"/>
</td>
</tr>
<tr>
<td jsf2dojo='true'>
<h:inputTextarea id="projectDescription"
value="#{projectFormBean.projectDescription}" rows="2" cols="15"/>
</td>
</tr> |
In
this way, we can mark part of the JSF components in a page and convert
them into Dojo widgets; the other JSF components will remain unchanged.
Please note the jsf2dojo='true' attribute is
added to the wrapper node rather than the JSF component itself, because
otherwise, the JSF compiler will treat it as an invalid attribute with
compilation errors.
Step 2: Parse injected JSF components into Dojo widgets
After the Dojo
injection is finished, the next step is to parse the JSF components
into Dojo widgets. The Dojo parser is the most vital foundation for all widgets. By
default, after a page is loaded the Dojo parser scans the whole page for tags
with Dojo markup (for example, dojoType='xxx') and parses them into widgets.
Another use of the Dojo parser is parsing tags dynamically or, as we say,
lazy parsing. Here is how we do it.
All the parsing logic is encapsulated in the jsf2dojo.js file, so the first step is to include it in the JSF page, as shown in Listing 16.
Listing 16. import jsf2dojo.js
<script type="text/javascript" src="script/jsf2dojo.js"></script> |
Next, add all the parsing steps to jsf2dojo.js. The first step is the widget declaration, as shown in Listing 17.
Listing 17. Widget class declarations and page onload handler
dojo.require("dijit.form.ValidationTextBox");
dojo.require("dijit.form.Textarea");
dojo.require("dojo.parser");
var TYPE_MAP = {
text : 'dijit.form.ValidationTextBox',
textarea : 'dijit.form.Textarea'
};
dojo.addOnLoad(init); |
The widget
classes are declared for the Create Project sample. Here, Dojo ValidationTextBox and Textarea widgets are used. The Dojo parser is also included.
The TYPE_MAP constant defines the class mappings that
we'll use later. The dojo.addOnLoad(init)
function registers
a callback function that will be invoked after the whole page is loaded
and Dojo finishes initialization.
Listing 18 shows the content of
function init.
Listing 18. Parse the JSF component to a Dojo widget
function init(){
var jsfContainerList = dojo.query("[jsf2dojo='true']");
for(var i = 0 ; i < jsfContainerList.length; i++){
var jsfWidget = _getJsfWidget(jsfContainerList[i]);//get JSF component node
if(!jsfWidget) continue;
if('input' == jsfWidget.tagName.toLowerCase()
&& 'text' == jsfWidget.type.toLowerCase()){ // input
jsfWidget.setAttribute('dojoType',
TYPE_MAP[jsfWidget.type.toLowerCase()]);
jsfWidget.setAttribute('promptMessage',
"Please Enter your information");
jsfWidget.setAttribute('required',"true");
}else{
jsfWidget.setAttribute('dojoType',
TYPE_MAP[jsfWidget.tagName.toLowerCase()]);
}
dojo.parser.parse(jsfContainerList[i]);//parse wrapper node
}
} |
The init function contains all the parsing
logic. First
dojo.query("[jsf2dojo='true']") is used to
fetch all the wrappers that contain the JSF components we defined
previously (<td>). Then _getJsfWidget()
is used to get the exact HTML tag generated from the JSF component. For the JSF inputText component, we add dojoType=' dijit.form.ValidationTextBox' and other specific
attributes, including a prompt message and whether the attribute is required. For the
JSF inputTextarea component, we add dojoType=' dijit.form.Textarea'. Because
everything is ready, dojo.parser.parse() is
invoked to generate the Dojo widgets. Here the wrapper node (<td>)
of the JSF component is used for parsing.
You can verify the result by accessing http://[server ip]:[server port]/JSFSampleEarWeb/faces/NewProject_lazy_inject.jsp. You should see the Dojo widgets on the page as shown in Figure 6.
Figure 6. Create project – Approach 3

After you click Submit, the Project name and description fields are transferred to the JSF listener on the server side and displayed on another JSF page named Project_result.jsp.
You may have noticed that the steps listed above only deal with a simple case where the JSF component has a close mapping with the Dojo widget. What if the mapping is not so simple? As mentioned previously, some extra tips are required.
First, we'll add more JSF components to the page, as shown in Listing 19.
Listing 19. JSF page with more components added
<tr>
<td jsf2dojo='true'>
<h:selectOneMenu id="projectOption" value="location">
<f:selectItem id="select1" itemValue="Shanghai" itemLabel="Shanghai"/>
<f:selectItem id="select2" itemValue="London" itemLabel="London"/>
<f:selectItem id="select3" itemValue="New York" itemLabel="New York"/>
</h:selectOneMenu>
</td>
</tr>
<tr>
<td jsf2dojo='true' jsfType='radio'>
<h:selectOneRadio id="newPrjRadio" value="NYPrj">
<f:selectItem id="rd1" itemLabel="Yes" itemValue="y" />
<f:selectItem id="rd2" itemLabel="No" itemValue="n" />
</h:selectOneRadio>
</td>
</tr>
<tr>
<td jsf2dojo='true'>
<h:selectBooleanCheckbox id="ck1" value="manager" />Project Manager
<h:selectBooleanCheckbox id="ck2" value="technical leader"/>Techinal Leader
<h:selectBooleanCheckbox id="ck3" value="member" /> Developer&Tester
</td>
</tr>
<tr>
<td jsf2dojo='true'>
<h:commandButton id="btnSubmit" action="success" value="Submit"
type="submit"></h:commandButton>
</td>
<td><input id='btnSubmit_mock' type='text' style='display:none'/></td>
</tr> |
Here,
a new attribute, jsfType='radio', is added for
the JSF selectOneRadio component, and a hidden
input text is also added for the JSF commandButton component. These attributes are used later during the
parsing process. For more details of the updated page, refer to the
NewProject_lazy_inject_advanced.jsp file.
Next, you'll parse the new JSF components.
In some cases, the HTML source will become totally different after the JSF
component is converted to a Dojo widget. For example, Listing 20 shows the
HTML source for the JSF selectOneMenu
component, and Listing 21 shows the source after selectOneMenu is converted to the Dojo ComboBox
widget.
Listing 20. HTML source for the JSF selectOneMenu component
<select id="project:projectOption" size="1" name="project:projectOption">
<option value="Shanghai">Shanghai</option>
<option value="London">London</option>
<option value="New York">New York</option>
</select> |
Listing 21. HTML source for the Dojo ComboBox widget
<div id="widget_project:projectOption" class="dijit ..." value="Shanghai"
widgetid="project:projectOption" ...>
<div style="overflow: hidden;">
...
<div class="dijitReset dijitInputField">
<input id="project:projectOption" class="dijitReset" type="text"/>
</div>
</div>
</div> |
To make these differences transparent to the JSF listener on the server side, a handler will be registered and invoked when the JSF form is submitted. Listing 22 shows the updated logic to parse more JSF components to Dojo widgets.
Listing 22. Parse more JSF components to Dojo widgets
for(var n = 0; n < jsfWidgets.length; n++){
var jsfWidget = jsfWidgets[n];
if ('select' == jsfWidget.tagName.toLowerCase()){
jsfWidget.setAttribute(DOJO_TYPE,
TYPE_MAP[jsfWidget.tagName.toLowerCase()]);
mockFunc = _mockSelect;
}else if('textarea' == jsfWidget.tagName.toLowerCase()){
jsfWidget.setAttribute(DOJO_TYPE,
TYPE_MAP[jsfWidget.tagName.toLowerCase()]);
}else if('input' == jsfWidget.tagName.toLowerCase()){
var type = jsfWidget.type.toLowerCase();
if('submit' == type){
var params = {label: jsfWidget.value};
var dojoWidget = new dijit.form.Button(params, jsfWidget);
dojo.connect(dojoWidget, 'onClick', window, 'formSubmit');
mockFunc = _mockSubmitInput;
}else if('text' == type){
jsfWidget.setAttribute(DOJO_TYPE, TYPE_MAP[type]);
jsfWidget.setAttribute('promptMessage',
"Please Enter your information");
jsfWidget.setAttribute('required',"true");
}else if ('checkbox' == type || 'radio' == type){
jsfWidget.setAttribute(DOJO_TYPE, TYPE_MAP[type]);
}
}
if(!dojoWidget){
dojoWidget = dojo.parser.parse(jsfList[j])[0];//parse wrapper node
}
if(dojoWidget && mockFunc){
mockFuncMap.push({'dojoWidget': dojoWidget, 'mockFunc': mockFunc});
}
} |
Callback
handlers, _mockSelect and _
mockSubmitInput, are registered for the JSF selectOneMenu and
commandButton. As shown in Listing 23, these handlers bind data to
corresponding fields to make sure the form information remains the same in
HTTPRequest. In this way, the JSF listener
on the server side is unaware of any changes. Note that the Dojo Button is created for commandButton specifically.
Listing 23. Sample callback handler for JSF selectOneMenu
Function _mockSelect(dojoWidget){
var mockedSelect = dojo.byId(dojoWidget.id);
mockedSelect.value = (dojoWidget.item) ? dojoWidget.item.value :
dojoWidget.store.root.value;
} |
Basically,
all callback handlers have two steps: first find the corresponding field
and then add necessary values. As shown in Listing 22, by using the dojo.connect(dojoWidget, 'onClick', window,
'formSubmit') function, formSubmit is
called when the JSF form is submitted. Listing 24 shows the details of formSubmit.
Listing 24. formSubmit function called before JSF form submitted.
function formSubmit(event){
for(var i = 0 ; i < mockFuncMap.length; i++){
mockFuncMap[i]['mockFunc']( mockFuncMap[i]['dojoWidget'] );
}
event.target.form.submit(); //event.target - submit button
} |
The
only thing formSubmit does is invoke all the
registered callback handlers so that the form information is correct. Everything is transparent to the JSF listener on the server
side.
Now, verify the result by accessing http://[server ip]:[server port]/JSFSampleEarWeb/faces/NewProject_lazy_inject_advanced.jsp. You will see all the JSF components have now been converted to Dojo widgets, as shown in Figure 7.
Figure 7. Create project with more widgets – Approach 3

In the previous sections, we listed three approaches to make the combine a JSF application with Dojo. Each approach has its advantages and weaknesses. This section compares these three approaches from following aspects:
- Complexity—Is it easy or hard to implement? Does it need to revise many files or need to modify the configuration files?
- Applicability—Is it applicable for all JSF components? Does it have any limitations?
- Reusability—Is it easy to reuse? Is it possible to become a stand-alone component that can be used directly by other projects?
Table 1 shows the comparison of these three approaches.
Table 1. Comparison of these three approaches
| Approach | Complexity | Applicability | Reusability |
|---|---|---|---|
| Approach 1 | 1 | 2 | 2 |
| Approach 2 | 3 | 3 | 3 |
| Approach 3 | 2 | 3 | 2 |
Note: We just use numbers from 1 to 3 to indicate the degree of each aspect. 1 means the lowest level while 3 means the highest level.
As you can see from this table, approach 1 is the easiest to be
implemented, but it has limitations. This approach is not applicable for
every JSF component, such as Checkbox.
Therefore,
approach 1 is a good way to quickly convert some JSF components (input box, textarea,
and so on) to Dojo widgets.
Approach 2 is a little more complex, because building your own JSF component is not very simple. But this approach is applicable for many JSF components, and is very easy to reuse. The JSF components with Dojo can be used directly by other projects. So, approach 2 is a good choice for enterprise development, because many projects may have the same requirements.
Approach 3 is mid-level. It is not as complex as approach 2 and is applicable for many JSF components, but it is not very easy to reuse. It requires more knowledge about the Dojo widget framework. Therefore, this approach is suitable for single project development. If there is only one project that needs JSF components with Dojo, and you don't want to spend much time to implement it, approach 3 is your best choice.
Integrating JSF and Dojo is very useful. It leverages the JSF's server-side abilities and Dojo's powerful widgets, allowing you to easily build Web applications with better user experiences. This article provides three approaches to modify a JSF application with Dojo. Each approach has its own advantages and weaknesses, so you can choose the one most suited to your project requirements.
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample code | JSFSampleEarWeb.war | 17KB | HTTP |
Information about download methods
Learn
- Dojo Home is the official home
for the Dojo open source foundation. There you can get the latest news, project
status, and so on.
- Dojo Book
provides a detailed introduction for the whole Dojo library, including
common usage, complete features, and customization options.
- Dojo online is an API document
that provides detailed API introductions.
- Dojo Spotlight and demo page provide many
live demos constructed on Dojo.
- Visit the JSF project page to
learn more about the JSF technology.
- The article "JSF for
nonbelievers: JSF component development" (developerworks , July
2005) is a good tutorial to guide developer to build JSF
component.
Get products and technologies
- Dojo download center
provides both the latest and all previous releases of Dojo.
- You can also get
answers for any problems related with Dojo on the Dojo
Forum.
Comments (Undergoing maintenance)







