Using the AJAX Progress Bar Component

December 2006 [Revision number: V1-1]  
This tutorial shows you how to use NetBeans Visual Web Pack 5.5 to build a web application that uses the sample Java BluePrints AJAX Progress Bar component. The tutorial shows several uses of the Progress Bar. First, you configure the Progress Bar for a determinate use case. In this case, the Progress Bar shows the percentage of progress as the task is completed. Next, you configure the Progress Bar for an indeterminate use case. Here, the Progress Bar indicates only that a task is under way, and not the percentage of progress completed, because the extent of the progress is unknown. Finally, you configure the Progress Bar to handle a failed task.

 
Contents
 
Setting Up the Application
Modifying the Session Bean
Creating a Determinate Progress Bar
Adding Code to the Progress Bar
Doing More #1: Adding an Indeterminate Progress Bar
Doing More #2: Simulating a Failed Task
Doing More #3: Changing the Style of the Progress Bar
  Content on this page applies to NetBeans 5.5 Visual Web Pack
 
External code used in this tutorial
pb.js
 

This tutorial works with the following resources

NetBeans Visual Web Pack 5.5 works with all supported servers and works with both the Java EE 1.4 and Java EE 5 platforms. This tutorial illustrates the Visual Web Pack features that work with the resources check marked in the following table. For detailed information about the supported servers and Java EE platform, see NetBeans Visual Web Pack 5.5 Installation Instructions.

Application Server works withSun Java System Application Server 9
works withTomcat
works withJBoss
works withBEA WebLogic
JavaServer Faces Components/
Java EE Platform
works with1.2 with Java EE 5*
works with1.1 with J2EE 1.4
Travel Database requiredNot Required
BluePrints AJAX Component Library not requiredRequired

* Only the Sun Java System Application Server supports Java EE 5

Setting Up the Application

You begin this tutorial by importing the Java BluePrints AJAX components into the IDE. You then create a project and add two files, SimpleTask.java and pb.js. SimpleTask.java simulates a server-side task that is performed in a separate thread. Whenever the user starts (or resumes) the task, the start method in SimpleTask.java spawns a new thread, which alternately sleeps and increments a counter. The file pb.js contains functions that are called by the JavaScript-related properties of the components in the application. These properties include the onComplete and onFail properties of the Progress Bar, the onClick property of the Buttons, and the onSubmit property of the Form.
  1. Download and import the latest version of the AJAX components if you have not already done so.
  2. Download SimpleTask.java and pb.js and save them to your file system.
  3. Create a new visual web application project and name it ProgressBarExample.

    ProgressBarExample's initial Page opens in the Visual Designer.
  4. Add SimpleTask.java to the project as follows:

    1. From the main menu, choose File > Add Existing Item > Java Source. Navigate to the directory in which you saved SimpleTask.java. Select the file and click Add.
    2. In the Projects window, expand Source Packages > progressbarexample. Double-click the SimpleTask.java node to open the file in the Java Editor.

      The following package statement is added at the top of the file:

      package progressbarexample;
  5. Add the pb.js JavaScript file to the project as follows:

    1. Choose File > Add Existing Item > Other (all files). Navigate to and select pb.js, and then click Add.
    2. In the Projects window, drag pb.js from Source Packages > progressbarexample to Web Pages > resources.

Modifying the Session Bean

Next you add and configure a property for the project's Session Bean.
  1. Open Page1 in the Visual Designer.
  2. In the Outline window, right-click SessionBean1 and choose Add > Property.

    Note: If the Add menu is not activated when you first open the pop-up menu, close the menu and right-click the SessionBean1 node a second time to activate the Add submenu.
  3. In the New Property Pattern dialog box, set the Name to taskMap, the Type to HashMap (note that the Name and Type fields are case sensitive), and the Mode to Read Only as shown in the following figure. Click OK.

    Figure 1: New Property Pattern Dialog Box
    Figure 1: New Property Pattern Dialog Box
  4. Right-click the SessionBean1 node and choose Edit Java Source from the pop-up menu.

    Error annotations appear in the code indicating that the HashMap class is not found.
  5. Right-click anywhere in SessionBean1.java and choose Fix Imports from the pop-up menu to automatically add the following import statement:

    import java.util.HashMap;
  6. Append the following lines of code (in bold) to the SessionBean1.init method.

    Code Sample 1: SessionBean1 Property
        public void init() {
            // Perform initializations inherited from our superclass
            super.init();
            // Perform application initialization that must complete
            // *before* managed components are initialized
            // TODO - add your own initialiation code here
            
            Creator-managed Component Initialization       
            // Perform application initialization that must complete
            // *after* managed components are initialized
            // TODO - add your own initialization code here
            taskMap = new HashMap();
            taskMap.put("progressBar1", new SimpleTask("progressBar1",
                    241, 100, false));
        }
     

    This code populates the taskMap property by constructing a HashMap and adding a new SimpleTask instance to the HashMap.

Creating a Determinate Progress Bar

You use a determinate Progress Bar in cases where you can determine the percentage of progress of a task as the task completes. In this section, you design a page that includes a determinate Progress Bar and two Buttons. The first Button starts, pauses, and resumes the task associated with the Progress Bar, while the second Button stops the task. The following figure shows how the page looks:
 
Figure 2: Progress Page Design
Figure 2: Progress Page Design
  1. In the Projects window, right-click the ProgressBarExample > Component Libraries node and choose Add Component Library from the pop-up menu. Select BluePrints AJAX Components and click Add Component Library.

    The IDE copies the component library into the project and adds the components to the Palette.
  2. Open Page1 in the Visual Designer.
  3. Open the BluePrints AJAX Components section of the Palette and drag a Progress Bar component onto the page. For this tutorial, use the default id property of progressBar1.

    Note: The Progress Bar should display as shown in Figure 2 above. If the Progress Bar displays incorrectly, right-click in the Visual Designer and choose Refresh from the pop-up menu.
  4. Drag a Grid Panel component from the Layout section of the Palette to the right of the Progress Bar.
  5. Set the id property of the Grid Panel to controlPanel and the columns property to 2.
  6. Drag two Button components from the Basic section of the Palette onto the Grid Panel.

    Make sure the outline of the Grid Layout component is a solid blue line when you drop the Button components.
  7. Set the following properties for the first Button:

    Property     
    Value
    border="0" height="2" width="1">
    id
    variableControl
    text
    Start
    onClick
    handleVariableControlOnClick(this, 'form1:progressBar1', false)
     
    The handleVariableControlOnClick function makes JavaScript calls to start, pause, or resume the Progress Bar when the user clicks the Button.
  8. Set the following properties for the second Button:

    Property     
    Value
    id
    stopControl
    text
    Cancel
    onClick
    handleStopControlOnClick('form1:variableControl', 'form1:progressBar1')
     
    The handleStopControlOnClick function makes a JavaScript call to stop the Progress Bar.
  9. In the Outline window, select form1. In the Properties window, set the form's onSubmit property to return handleFormOnSubmit().

    This JavaScript function prevents the page from being submitted when the user clicks either of the two Buttons.
  10. From the Advanced section of the Palette, drag a Script component onto the page.

    The Outline window shows script1 in the Page1 section. This non-visual component declares a script element in the rendered HTML markup.
  11. In the Properties window, set the Script's url property to /resources/pb.js. Note that this property requires the leading slash (/).

Adding Code to the Progress Bar

In this section, you add four methods to the project's Java code. These methods perform the following actions and become Events properties of the Progress Bar component:

  • Start or resume the task indicated in the AJAX request
  • Pause the task indicated in the AJAX request
  • Stop the task indicated in the AJAX request
  • Extract the component id (for example, progressBar1) of the Progress Bar that sent the AJAX request
 
  1. Open Page1 in the Java Editor and add the following code (in bold) after the destroy() method.

    Code Sample 2: Additional Progress Bar Methods
        public void destroy() {
    }
    
        /**
         * Start or resume the task indicated in the AJAX request.
         */
        public void startOrResumeTask(FacesContext context) {
            String taskId = getTaskIdFromAJAXRequest(context);
            SimpleTask task = (SimpleTask)getSessionBean1().getTaskMap().get(taskId);
            Map paramMap = context.getExternalContext().getRequestParameterMap();
            String doomed = (String)paramMap.get("doomed");
            task.start(Boolean.parseBoolean(doomed));
        }
        
        /**
         * Pause the task indicated in the AJAX request.
         */
        public void pauseTask(FacesContext context) {
            String taskId = getTaskIdFromAJAXRequest(context);
            SimpleTask task = (SimpleTask)getSessionBean1().getTaskMap().get(taskId);
            task.pause();
        }
        
        /**
         * Stop the task indicated in the AJAX request.
         */
        public void stopTask(FacesContext context) {
            String taskId = getTaskIdFromAJAXRequest(context);
            SimpleTask task = (SimpleTask)getSessionBean1().getTaskMap().get(taskId);
            task.cancel();
        }
        
        /**
         * Extract the component id (for instance, "progressBar1") of the
         * progress bar that sent the AJAX request.
         */
        private String getTaskIdFromAJAXRequest(FacesContext context) {
            Map paramMap = context.getExternalContext().getRequestParameterMap();
            String progressBarClientId = (String)paramMap.get("bpui_progressbar_clientId");
            if (progressBarClientId == null) {
                throw new NullPointerException();
            }
            //get portion from last colon forward
            int lastColon = progressBarClientId.lastIndexOf(NamingContainer.SEPARATOR_CHAR);
            if (lastColon == -1) {
                return progressBarClientId;
            }
            String taskId = progressBarClientId.substring(lastColon + 1);
            return taskId;
        }
    
     
    When the Progress Bar sends AJAX requests to the server, it includes its client id in the bpui_progressbar_clientId request parameter. AJAX requests to start, pause, resume, or stop the task call the startOrResumeTask, pauseTask, or stopTask method in the application's page bean. These methods call the getTaskIdFromAJAXRequest method, which extracts the component id (such as progressBar1) from the bpui_progressbar_clientId request parameter. The methods use the component id to retrieve a SimpleTask instance from the taskMap and call the task's start, pause, or cancel method.
  2. Right-click in the Page1 source code and choose Fix Imports from the pop-up menu.

    The IDE adds the following import statements to fix Class not found errors:
    import java.util.Map;
    import javax.faces.component.NamingContainer;
    import javax.faces.context.FacesContext;
    
  3. Return to the Design view for Page1 and set the following properties on the Progress Bar component:

    Property     
    Value
    stopOperation
    stopTask()
    resumeOperation
    startOrResumeTask()
    startOperation
    startOrResumeTask()
    pauseOperation   
    pauseTask()
    onComplete
    function() {handleProgressBarOnComplete('form1:variableControl');}
     

    As noted earlier, the handleVariableControlOnClick and handleStopControlOnClick functions make calls to start, pause, resume, or stop the Progress Bar when the user clicks one of the Buttons. When such client-side scripting calls are made on the Progress Bar, an AJAX request is sent to the server. As a result, the method specified for the startOperation, pauseOperation, resumeOperation, or stopOperation is called.

    The handleProgressBarOnComplete function changes the text of the first Button to "Start," in case the user wants to restart the task.

    Note: In some cases, the IDE might insert an extra startOrResumeTask method in the code, which prevents the code from compiling. To fix the error, remove the extra method.
  4. Open the JSP view for Page1 and add the interval, percentage, failed, and percentageText properties of progressBar1 as shown in bold below:

    Code Sample 3: Properties for progressBar1
    <bp:progressBar binding="#{Page1.progressBar1}" id="progressBar1"
        interval="#{SessionBean1.taskMap.progressBar1.interval}" 
        percentage="#{SessionBean1.taskMap.progressBar1.percentage}"
        failed="#{SessionBean1.taskMap.progressBar1.failed}" 
        percentageText="#{SessionBean1.taskMap.progressBar1.percentageText}"
        onComplete="function() ...
        resumeOperation=...
     
    These properties of the Progress Bar are bound to the corresponding properties of the SimpleTask instance keyed on progressBar1 in the taskMap. You add this code directly to the JSP source due to limitations in the Property Editors.
  5. Build and run the application. Click the Start button to start the task.

    The Progress Bar fills as the operation progresses and the text message continually updates to indicate the percentage of progress completed (for example, 25%). The Start button changes to Pause.
  6. Continue exploring the application by clicking the Pause button (which changes to Resume) and the Cancel button.

Doing More #1: Adding an Indeterminate Progress Bar

In this section, you add an indeterminate Progress Bar, which uses motion to show that a task is under way instead of filling the bar to show the percentage of the progress completed. An indeterminate Progress Bar is good for providing feedback in cases where you cannot determine the amount of progress being made as the task completes. The page you build in this section should look like the following figure:

Figure 3: Adding an Indeterminate Progress Bar
Figure 3: Adding an Indeterminate Progress Bar
  1. Open the Design view of Page 1. Copy the Progress Bar and Grid Panel components and paste the copies below the original components.

    Note: This section of the tutorial uses the default id properties of progressBar2, controlPanel1, variableControl1, and stopControl1 for these components.
  2. Select the new Progress Bar component and change the onComplete property so that it points to variableControl1:

    function() {handleProgressBarOnComplete('form1:variableControl1');}
  3. Select the new Start button and change the onClick property so that it points to progressBar2:

    handleVariableControlOnClick(this, 'form1:progressBar2', false)
  4. Select the new Cancel button and change the onClick property to point to variableControl1 and progressBar2:

    handleStopControlOnClick('form1:variableControl1', 'form1:progressBar2')
  5. Open the JSP view for Page1. Find the code for progressBar2, which appears after the occurrence of the line </h:panelGrid>. Modify the four properties of progressBar2 (shown in bold) so that they refer to progressBar2.

    Code Sample 4: Properties for progressBar2
    </h:panelGrid>
    <bp:progressBar binding="#{Page1.progressBar2}" 
    failed="#{SessionBean1.taskMap.progressBar2.failed}" id="progressBar2"
    interval="#{SessionBean1.taskMap.progressBar2.interval}"
    onComplete="function() ...
    percentage="#{SessionBean1.taskMap.progressBar2.percentage}" 
    percentageText="#{SessionBean1.taskMap.progressBar2.percentageText}"
    resumeOperation=...
       
    Due to space constraints, several lines in the code above have been split into two lines.
  6. Open the SessionBean1.java file and append the following line to the SessionBean1.init method.

    taskMap.put("progressBar2", new SimpleTask("progressBar2", 241, 100, true));

    This code adds a new SimpleTask instance to the taskMap. The second Progress Bar monitors this task. The parameter true, which is passed to the SimpleTask constructor, establishes that the task is indeterminate.
  7. Build and run the project. Click the Start button you added in this section to start the indeterminate task.

    A small rectangle moves left to right and a text messages displays "(time remaining unknown)"until the task completes.
  8. Continue exploring the application by clicking the Pause, Resume, and Cancel buttons. The following figure shows the two Progress Bars in action.

    Figure 4: Progress Bars in Action
    Figure 4: Progress Bars in Action

Doing More #2: Simulating a Failed Task

Here you modify the Progress Bar components to display a failed task.
  1. Open the Design view of Page1.
  2. Change the onClick property for the variableControl button (the first Start button) so that it uses true instead of false:

    handleVariableControlOnClick(this, 'form1:progressBar1', true)

    This code causes a request parameter called doomed to be sent in the AJAX request with a value of true. The startOrResumeTask method in the page bean retrieves this parameter and passes it as an argument to SimpleTask's start method.
  3. Change the onClick property for the variableControl1 button (the second Start button) so that it uses true instead of false:

    handleVariableControlOnClick(this, 'form1:progressBar2', true)
  4. Set the onFail property for progressBar1 to:

    function() {handleProgressBarOnFail('form1:variableControl');}

    The handleProgressBarOnFail function changes the first Button's text to "Start" when the task fails, in case the user wants to restart the task.
  5. Set the onFail property for progressBar2 to:

    function() {handleProgressBarOnFail('form1:variableControl1');}
  6. Build and run the project.

    This time the first Progress Bar fails at 25%. The second Progress Bar also fails, although the text message does not show a percentage, because the task is indeterminate.

Doing More #3: Changing the Style of the Progress Bar

Finally, you change the style of the Progress Bar in your project's stylesheet.css file.
  1. Open the style sheet from the Projects window by double-clicking the ProgressBarExample > Web Pages > resources > stylesheet.css node.
  2. Add the following code in bold, which changes the color and font of the Progress Bar, and then save the file.

    Code Sample 5: Style Sheet Code to Set Progress Bar Color
    .bpui_progressbar_portionComplete {
    background: blue !important;
    }
    .bpui_progressbar_portionRemaining {
    background: lightgrey !important;
    }
    .bpui_progressbar_percentageText {
    color: blue;
    font-size: 14px;
    font-weight: bold;
    }
    .bpui_progressbar_barArea {
    height: 9px !important;
    }
  3. Open the Design view of Page1 to see the changes to the Progress Bar, shown in the following figure.

    Figure 5: Stylized Progress Bars in Action
    Figure 5: Stylized Progress Bar

Summary

Following are the highlights of the Progress Bar component:

  • The Progress Bar supports both determinate and indeterminate use cases. The Progress Bar interprets a percentage of -1 as indeterminate.
  • The Progress Bar supports start, pause, resume, and stop functionality through the startOperation, pauseOperation, resumeOperation, and stopOperation events, which can be bound to methods in the page bean.
  • The Progress Bar supports task failure with a boolean failed property that can be bound.
  • The Progress Bar supports custom scripting through several advanced properties, including onComplete and onFail. You can consolidate custom JavaScript into a .js file and include a Script component that refers to the file.
  • The Progress Bar supports custom styling.
 

Here are some tips for using the Progress Bar component, which are shown in this tutorial:

  • Maintain a Map of task objects in session scope, with a different Progress Bar monitoring each task.
  • Support long-running tasks in a separate thread. You can write a class that represents a particular task using SimpleTask.java as a model. SimpleTask.java maintains a reference to a Thread, exposes methods to start (or resume), pause, or cancel the task, and has properties indicating the polling interval, percentage, text, and whether the task has failed.
 
See Also:
 


Copyright and Trademark Notice