IBM® Rational® Application Developer Version 7 introduced several new Java™ Server Faces technology (JSF) components that make it easier to build rich Web applications. Among them is a ProgressBar component that you can use to provide a visual indication that a task is running.
Clicking a button in the browser and not getting any immediate feedback can be very frustrating for the user. Not knowing what is going on, the user would probably try to click the same button again and again, or reload the page, or close the application.
To avoid such problems, it is often advisable to offer visual feedback in form of a progress bar that moves according to the progress of the running task. This component comes in very handy when you have long-lasting tasks, either on the server or in the browser, and you don't want to leave the user wondering whether the application is working.
You could create a progress bar with JavaScript or different images, but a JavaServer Faces component offers all of the functionality that you need. You can simply add it to any of your Web pages without doing any implementation work.
To use the Rational Application Developer ProgressBar component, complete these tasks:
- Create a Dynamic Web project using Faces Project configuration.
- Create a Web page.
- Drag the Progress Bar from the Enhanced Faces Components drawer of the palette onto the Web page.
The component will be visible in the Design view, and its properties will be available in the Properties view (see Figure 1).
Figure 1. Adding the ProgressBar component to a Web page
The ProgressBar requires simple JavaScript code to control its behavior. Therefore, after you drop the component onto the Web page, you also need to add a few lines of JavaScript, depending on how you are going to use the ProgressBar. The rest of this article explains and demonstrates how to do this.
The Rational Application Developer ProgressBar component has two modes of operation: automatic and manual.
- After starting in the automatic mode, the progress bar keeps updating the status of the task until it is stopped by using specified time interval and percentage increment values. The bar can move either from left to right or from center outward. This mode is useful in situations where you know when a task starts and stops but have no way of knowing how far the task has progressed. In this mode, you control the ProgressBar using two JavaScript calls:
start()andstop(). Their names are self-explanatory: You start a progress bar with astart()call and stop it with astop()call. Both methods can use a string parameter as the message text shown above the bar. - In the manual mode, the progress bar does not move independently. Instead, you have to manually update its value by using a JavaScript call,
upDatePercentage(integer). You can provide any value between 0 (zero) and 100 to reflect the percent complete (for instance, 10 means 10% complete). This mode is useful when you know exactly how far the task has progressed and can represent the progress visually ("visualize" the progress).
To get access to the JavaScript object that represents the ProgressBar, you can use the getComponentById(id) helper method that is available in the Rational Application Developer JavaScript library. For example,
if you want the progress bar to start when the user clicks a button, you can add an onclick event to the button, using the code that you see in Listing 1.
Listing 1.Adding an onclick event to the user interface button
onclick="hX.getComponentById('form1:bar1').start('Please wait...');"
|
The ID that you pass to the getComponentById() function is the ProgressBar's client ID as it is emitted by JSF, not the component ID that you assigned in the Java™Server Page (JSP). Depending on where the ProgressBar is on the page, its client ID will change. For example, if the ProgressBar with an ID of bar1 is inside of a form with an ID of form1, its client ID will be form1:bar, as shown in the previous code snippet (Listing 1).
Table 1 lists all available JavaScript methods of the ProgressBar component.
Table 1. JavaScript methods of the ProgressBar component
| Method | Description |
|---|---|
| start(string) | In automatic mode, starts the progress bar running and changes the message text to the value of the string. If you do not want a message, do not pass a parameter. |
| stop(string) | In automatic mode, stops the progress bar running and changes the message text to the value of string. If you do not want a message, do not pass a parameter. |
| reset() | Resets the bar's displayed values to zero. |
| upDatePercentage(integer) | In manual mode, updates the progress bar to the value of the integer. The integer value must be between 0 (zero) and 100. Values outside this range are rounded up or down, respectively. |
| upDateMessage(string) | Changes the message that is displayed above the bar. If you want to clear the message, pass nothing as the parameter. |
| redraw() | Redraws the component, taking into account any changes made to the attributes or properties. Use whenever you change an attribute (disabled, for example) or property (for instance, style:width). Should be used in conjunction with visible(), hide(), reset(), upDatePercentage(), and upDateMessage() methods. |
| hide() | Hides the progress bar. |
| visible() | Makes the progress bar visible. |
| percentageDone | Holds the current progress bar value and is read-only. Use upDatePercentage() to change the value. |
There is a sample project file attached to this article, called ProgressBarSample.zip. It shows use of the ProgressBar in both modes and in different scenarios. The next section describes each example.
The Basic.jsp page in the attached sample project demonstrates the ProgressBar component in both automatic and manual modes. The automatic bar has Start and Stop buttons attached to it, and the manual bar has Advance and Reset buttons. Let's look at how these progress bars are defined and what the buttons do.
Using the ProgressBar component in automatic mode
The automatic progress bar looks like Listing 2 in the JSP source code.
Listing 2. Automatic ProgressBar
<hx:progressBar auto="true" timeInterval="500"
proportion="5" id="bar1"
styleClass="progressBar"
message="Automatic progress bar. Press Start to start." />
|
The attributes of the <hx:progressBar> tag shown in Table 2 define how the bar behaves at run time.
Tip:
You can find the complete list of ProgressBar attributes in How to customize ProgressBar component section at the end of this article.
Table 2. Attributes and runtime actions of the hx:progressBar tag
| Attribute | Runtime action |
|---|---|
| auto="start" | ProgressBar runs in automatic mode |
| timeInterval="500" | Bar updates every 500 ms |
| proportion="5" | Bar moves by 5% every time |
In addition, the styleClass attribute defines how the bar looks to the user, and the message attribute provides the text that shows above the bar.
The Start and Stop buttons below the progress bar are plain JSF buttons that control the bar through their onclick events (see Listing 3).
Listing 3.Start and Stop button controls
<hx:commandExButton type="button" value="Start" id="button1"
styleClass="commandExButton" onclick="startPB()"
/>
<hx:commandExButton type="button" value="Stop" id="button2"
styleClass="commandExButton" onclick="stopPB()"
/>
|
Important:
Notice that the button's type is set to button instead of the default, submit. This is important, because you don't want the button to submit anything to the server; you merely want it to call a JavaScript function in the browser.
Listing 4 shows the JavaScript functions that start and stop the bar.
Listing 4. JavaScript functions
function startPB() {
pb=hX.getComponentById('form1:bar1');
pb.start('Press Stop to stop');
}
function stopPB() {
pb=hX.getComponentById('form1:bar1');
pb.stop('Press Start to restart');
pb.reset();
}
|
Both functions get access to the ProgressBar object by using the getComponentById() call first, and then they perform their corresponding operations on that object.
Using the ProgressBar component in manual mode
The manual progress bar on the page is very similar, as you can see in Listing 5.
Listing 5.Basic code for the manual ProgressBar
<hx:progressBar auto="false" id="bar2"
styleClass="progressBar"
message="Manual progress bar. Press Advance to move by 5%. Press Reset to reset to 0%" />
|
Note:
Notice that the manual bar's auto attribute is set to
false, and it does not use either the timeInterval or proportion attributes that were set on the automatic bar.
The buttons that control the manual progress bar are identical to the buttons used in Listing 5, previously, using the JavaScript code in Listing 6 to control the component:
Listing 6.JavaScript code that controls the ProgressBar component
function advancePB() {
pb=hX.getComponentById('form1:bar2');
pb.upDatePercentage(pb.percentageDone + 5);
pb.redraw();
}
function resetPB() {
pb=hX.getComponentById('form1:bar2');
pb.upDatePercentage(0);
pb.redraw();
}
|
Here again, you follow these three steps:
- First, find the ProgressBar object with a
getComponentById()call. - Then set the progress action by using the
upDatePercentagecall and specifying a new value. TheresetPBfunction uses zero, whereas, in theadvancePBcall, you first get the current state (pb.percentageDone) and then increment it by 5%. - After you have done this, you need to update the manual progress bar on the screen by using the
redraw()call.
Figure 2. The basic.jsp page at this stage
This basic.jsp page does a good job of demonstrating the ProgressBar component, but it's hardly applicable to a real-world Web application, because there is no task to show a progress bar. In the next section, you'll see more realistic examples.
Using an automatic progress bar for a long-running, server-side task
Open the auto.jsp page from the attached sample project. This page has a button that initiates a time-consuming action on the server. When the user clicks the button, the server waits 10 seconds before responding to the browser. In a real-world application, the server may be busy querying a database, computing a route, or performing some similar task that takes a while to complete. Even though you don't know how long it will take the server to respond, you can let the user know that the task is running and that the user should wait.
One way to do so is to show an automatic progress bar that will run until the server responds and the page gets refreshed. The button and the progress bar on this page (see Listing 7) are very similar to those that you saw on the basic.jsp page, previously.
Listing 7. Progress bar configuration for a task that takes the server a while to complete
<hx:progressBar
auto="true" timeInterval="50" proportion="1"
id="bar1" styleClass="progressBar"
initHidden="true" />
|
This tag creates an automatic progress bar that moves by 1% every 50 ms. It is also initially hidden (by using the initHidden attribute) and does not become visible until the user clicks the button.
Listing 8. Button for a task that takes the server a while to complete
<hx:commandExButton type="submit" id="button1"
value="Perform a time consuming action"
styleClass="commandExButton"
onclick="startPB()"
action="#{pc_Auto.doButton1Action}" />
|
The button initiates a task on the server (action attribute) and, at the same time, starts the progress bar in the browser (onclick attribute). It uses the JavaScript function shown in Listing 9 to do so.
Listing 9.Code that starts the task and the progress bar
function startPB() {
pb=hX.getComponentById('form1:bar1');
pb.visible();
pb.start('Please wait while your action is being executed on the server...');
}
|
You are already familiar with the getComponentById() and start() methods. Additionally, the button calls visible() to make the progress bar visible to the user.
Figure 3. The auto.jsp page updated
Using a manual progress bar for a multistep browser operation
Open the manual.jsp page from the attached sample project. This page demonstrates a ProgressBar component used in a pure client-side environment, without any interactions with the server. Such a scenario can often be found on the pages that ask a user to perform a number of operations or steps, such as filling out a large form or taking a test.
As an example, the manual.jsp page asks the user to solve four simple mathematical equations. As soon as one of the answers is modified, the progress bar is updated to reflect how many answers were correct and to show overall progress.
To build this page, you use a ProgressBar component in manual mode, similar to the one used on the basic.jsp page (Listing 10).
Listing10. Creating a manual progress bar
<hx:progressBar auto="false" id="bar1"
styleClass="progressBar"
message="Progress: You completed 0 out of 4 tasks" />
|
Every one of the input fields invokes a JavaScript function to update the progress bar by using the onkeyup event (Listing 11).
Listing11. Updating the progress bar when the onkeyup event occurs
<h:inputText id="text2" styleClass="inputText" size="2"
onkeyup="updatePB()" />
|
The JavaScript code checks the answers and updates the progress bar accordingly by changing the percentage and the message text (see Listing 12). You can see the result in Figure 4.
Listing12. JavaScript that updates the progress percentage and message
function updatePB() {
v1=hX.getElementById('form1:text2').value;
v2=hX.getElementById('form1:text4').value;
v3=hX.getElementById('form1:text6').value;
v4=hX.getElementById('form1:text8').value;
done=0;
if(v1=='4') done=done+1;
if(v2=='56') done=done+1;
if(v3=='9') done=done+1;
if(v4=='12') done=done+1;
pb=hX.getComponentById('bar1');
pb.upDatePercentage(done*25);
pb.upDateMessage('Progress: You completed ' + done + ' out of 4 tasks');
pb.redraw();
}
|
Figure 4. Manual mode after update
Monitoring progress of a server-side task by using Ajax
In the earlier example (auto.jsp, Figure 3), there was a long-running server-side task, and you did not know how long it would take the task to complete or how far the task had progressed. Therefore, it was appropriate to use an automatic ProgressBar, and it just kept running until the server finished processing the task.
Quite often, you can find yourself in a different situation, where your server-side code monitors exactly how things are running, how far along the task is, and how much time it will take to complete the task. For example, you could be processing a database row by row, and you know how many rows there are and how many have already been processed. In such a case, it would be useful if the progress bar in the browser could be updated according to the server-side status, rather than running blindly. That is, if 300 rows out of 1000 have been processed, the progress bar would show progress of exactly 30%.
To make this happen, you need to make the browser communicate with the server by using AJAX technology (asynchronous JavaScript and XML, commonly called Ajax). The ajax.jsp page in the attached sample project shows how you can do this.
First, you need to add a ProgressBar component, using the code that you see in Listing 13.
Listing13. Adding the ProgressBar component to update server activity
<hx:progressBar auto="false" id="bar1"
styleClass="progressBar"
message="Server reports progress..." />
|
You don't want the progress bar to just keep running on its own, so you make it manual by setting the auto attribute to false. This may not be obvious at first -- after all, you are not really going to update it manually every time. However, because the progress is going to be set through a JavaScript function, manual mode is exactly what you need here.
To have the server report the status of the running task, you create a hidden input field that holds the status (current progress percentage), and you put this field into a panel that can be updated via Ajax.
Listing14. Adding a hidden field to the Ajax panel to get server updates
<h:panelGroup id="group1">
<h:inputHidden id="hidden1"
value="#{pc_Ajax.pbValue}" />
</h:panelGroup>
<hx:ajaxRefreshRequest id="ajaxRefreshRequest1"
target="group1"
oncomplete="movePB()" params="text1" />
|
Now the value of the hidden field can be updated by using Ajax. Every time the browser sends an Ajax request to the server, the get method for the pbValue property will be executed and whatever value it returns will be put into the hidden input field in the browser. In the sample application, the get method for pbValue simply keeps a counter in the session and increments it every time the get method is called. There is also a Reset button on the page that resets the counter to zero.
The easiest way to send an Ajax request is to have a button that does that when the user clicks the button (see Listing 15).
Listing 15. Sample code listing at maximum width
<hx:commandExButton type="button" id="button1"
style="display:none"
styleClass="commandExButton">
<hx:behavior event="onclick" id="behavior1"
behaviorAction="get"
targetAction="group1" />
</hx:commandExButton>
|
Remember, the purpose of this button is to automatically trigger the Ajax refresh action on the progress bar. Therefore, you make the button invisible by setting the style attribute to display:none. To automatically kick off the Ajax refresh action, you will set up a JavaScript timer on the button (Listing 16).
Listing16. JavaScript fragment to set up a timer on the user interface button
function poll() {
document.getElementById('form1:button1').click();
}
setInterval("poll();", 1000);
|
This JavaScript fragment makes sure that the poll() function runs every second. All the poll() function does is simulate a click on the button. That click sends the Ajax request to the server, the server returns current progress status, and the hidden field is updated. This all happens without any user interaction.
After you have the current progress updated in the hidden input field, all that's left to do is to update the ProgressBar component accordingly. If you noticed, the Ajax tag also has a JavaScript function associated with itm as Listing 17 shows.
Listing 17. Sample code listing at maximum width
<hx:ajaxRefreshRequest id="ajaxRefreshRequest1"
target="group1"
oncomplete="movePB()" params="text1" />
|
The oncomplete event runs every time the server responds to an Ajax request. As soon as that happens, you take the value of the hidden input field and update the progress bar (see Listing 18). Figure 5 shows the effect on the user interface.
Listing18. Using the value of the hidden field to update the progress bar
function movePB() {
v=hX.getElementById('form1:hidden1').value;
pb=hX.getComponentById('form1:bar1');
pb.upDatePercentage(v);
pb.redraw();
}
|
Figure 5. ajax.jsp
How to customize your ProgressBar component
You can customize the behavior of the ProgressBar component by using the attributes listed in Table 3.
Table 3. Main ProgressBar attributes
| Attribute | Action |
|---|---|
| auto | Automatic mode if true, manual mode if false. Default is
false. |
| initHidden | If true, the progress bar is hidden when the page is initially displayed. Default is false. |
| message | The message to display above the bar. |
| outward | If true, the progress bar draws from the center outward. If false, the bar draws from left to right. Default is false. |
| proportion | In automatic mode, the amount completed that the bar shows (percentage of the width of the progress bar) increments each time it updates. Default is 5. |
| initValue | In manual mode, the amount (percentage) that the bar initially displays. Default is 0 (zero). |
| timeInterval | In automatic mode, interval (how often) the bar is updated. Specified in milliseconds. Default is 1000. |
The presentation of the progress bar is controlled by the CSS classes that Table 4 shows.
Table 4. ProgressBar classes
| CSS class | Purpose |
|---|---|
| <base> | The name of this class can be set in the
styleClass attribute of the ProgressBar component. Default is progressBar. This class styles the entire progress bar control (the containing div). |
| <base>-Table | Styles the table that makes up the progress bar. |
| <base>-Message | Styles the area that holds the message text. |
| <base>-Bar | Styles the moving bar. |
| <base>-Bar_container | Styles the area that contain both the moving bar and the percentage text. |
| <base>-Bar_text | Styles the percentage text. |
For more information on the newest features of Rational Application Developer, using it with Ajax and Java technologies, and related information, see Resources.
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample ProgressBar application for this article | ProgressBarSample1.zip | 4.9MB | HTTP |
Information about download methods
Learn
-
"Improve the usability of Web applications with type-ahead input fields using JSF, AJAX,and Web services in Rational Application Developer V7" (developerWorks, December 2006).
-
"What's new in IBM Rational Application Developer V7.0" (developerWorks, December 2006).
-
" JSF and Ajax: Web 2.0 application made easy with Rational Application Developer V7." Ajax is arguably the most popular technology on the Web today, because it's the
cornerstone of what is often called Web 2.0. Unfortunately, creating an Ajax application is not an easy task, especially when you need to integrate it with another framework, such as JavaServer⢠Framework (JSF). Fortunately, the IBM Rational Application Developer V7 release provides Ajax functionality for the JSF components, which makes the task much easier. This article explains how to use Ajax and JSF together in Rational Application Developer V7 and also walks you through an example of adding Ajax support to an existing application (developerWorks, December 2006).
- For technical resources, visit the developerWorks Rational Application Developer area. You'll find technical documentation, how-to articles, education, downloads, product information, and more.
- Subscribe to the developerWorks Rational zone newsletter. Keep up with developerWorks Rational content. Every other week, you'll receive updates on the latest technical resources and best practices for the Rational Software Delivery Platform.
- Browse the technology bookstore for books on these and other technical topics.
- Stay current with developerWorks technical events and Webcasts.
Get products and technologies
- Download a free trial version of Rational Application Developer.
- Download
IBM product evaluation versions
and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
Discuss
- Check out developerWorks
blogs and get involved in the developerWorks community.
-
Rational Software Architect, Data Architect, Software Modeler, Application Developer and Web Developer forum: Ask questions about Rational Application Developer.





