Understanding Scope and Managed Beans

Contributed by the NetBeans Tutorials Team
December, 2007 [Revision number: 6.0]    

In this tutorial, you use the NetBeans IDE with Visual Web JSF application development functionality to create an application that demonstrates how to use application, session, and request scopes to manage your application's objects. Scope is the availability (or context) of an object and its intended life span in a web application.

The web application that you create in this tutorial uses an object in application scope to tally votes, and uses an object in session scope to ensure that a user votes only once per session. The application uses a request scope object to display the time that the user submitted the vote. The time is stored in request scope, because the application does not need the value after the response is sent to the client browser.

Expected duration: 45 minutes

Contents

About Scopes
Adding Properties to Managed Beans
Creating the Start Page
Creating the Results Page
Specifying Page Navigation
Running the Application
Doing More
  Content on this page applies to the NetBeans 6.0 IDE
 

This tutorial works with the following technologies and resources

JavaServer Faces Components/
Java EE Platform
works with1.2 with Java EE 5*
works with1.1 with J2EE 1.4
Travel Database not requiredNot required

* In order to take advantage of NetBeans IDE 6.0's Java EE 5 capabilities, use an application server that is fully compliant with the Java EE 5 specification such as the Sun Java Application Server 9/GlassFish.

This tutorial has been tailored for use with the GlassFish v2 Application Server. If you are using a different server, consult the Release Notes and FAQs for known problems and workarounds. For detailed information about the supported servers and Java EE platform, see the Release Notes.

About Scopes

As long as a user stays on a page, the component values are remembered even when the page redisplays, such as when the user clicks a button that returns null. However, when the user leaves the page, the component values disappear.

To make values available to other pages, or to make values available to the same page, should the user return to it, you need to store the values. When you create a project from the IDE, the IDE creates three managed beans for storing values:

The following figure shows the Navigator window with the default managed beans.

Figure 1: Default Classes and Scopes Figure 1: Default Managed Beans

A managed bean is a JavaBeans object that a JavaServer Faces web application instantiates and stores in either request scope, session scope, or application scope. The web application stores RequestBean1 in request scope, SessionBean1 in session scope, and ApplicationBean1 in application scope.

To add a property to one of these managed beans, you double-click the bean in the Navigator window and type the property declaration in the source code. Right-click anywhere in the Java editor and choose Refactor > Encapsulate Fields. Then select the property from the list, select which methods to add, and click Refactor.

Before you create a bean property to store a value, you must determine the appropriate scope for the property's value. Because many users can access a web application at the same time, you need to use the smallest scope possible to make the best use of server resources. The following figure illustrates the duration of each type of scope.

Figure 2: Web Application Scopes Figure 2: Web Application Scopes

For example, your web application has a drop-down list of measurement types (pixels, centimeters, and inches). You might want to store the list of choices in ApplicationBean1 so that all concurrent user sessions can share the list. On the other hand, you might store the user's login name in SessionBean1, so that the name is available for all the pages that the user accesses in that session. If you don't need the information beyond the lifetime of the current request, you can save space by putting the property in RequestBean1.

Warning: You cannot use a request bean if you have included the <redirect> element inside the <navigation-case> element of a navigation rule. (You see these rules when you click the XML button in the Page Navigation editor.) When the page is submitted, the <redirect> element redirects the page and ends the request before a subsequent page can use any of the values stored in the Request Bean.

When you create a page from the IDE, the Java source code for the page bean contains methods for accessing the RequestBean1, SessionBean1, and ApplicationBean1 objects. To access properties of these managed beans, you use code similar to the statements in the following code snippet.

Code Sample 1: Accessing an Application Bean Property
ApplicationBean1 appBean = getApplicationBean1();
Option[] choices = appBean.BallotOptions();

The web application instantiates a managed bean the first time within that bean's scope that a page accesses a property in the managed bean. For example, an instance of a SessionBean1 object does not exist for the user's session until the user accesses a page that references a SessionBean1 property. An instance of an ApplicationBean1 object is created the first time a page from any session accesses the application bean, and it persists as long as the web application is running.

Tip: To add additional managed beans:

  1. In the Projects window, expand the Source Packages node, right-click the package node.
  2. Choose New > Other, select JavaServer Faces category and scope under File Types, and click Next.
  3. Type the File Name of the new managed mean and click Finish.

    The new managed bean appears in the Projects window under the Source Packages node.

Adding Properties to Managed Beans

The pages in this web application require access to the following values, which you create in this section:

Complete the following steps to add the properties to the managed beans.
  1. From the main menu, choose File > New Project.
  2. In the New Project Wizard, select Web from the Categories list and Web Application from the Projects list, and click Next.
  3. Name the project Scopes and click Next.
  4. In the Frameworks panel, check Visual Web JavaServer Faces and click Finish.

    The Scopes project's Page1.jsp opens in the Visual Designer.
  5. In the Navigator window, double-click ApplicationBean1.

    This opens ApplicationBean1.java for editing.
  6. Next you add the Application bean properties. Under the constructor public class ApplicationBean1 extends AbstractApplicationBean, add the following declarations:
    private Option[] ballotOptions;
    private HashMap tally;
  7. Right-click in the Java editor and choose Fix Imports. Because there is more than one package that contains the Option class, the Fix Imports dialog appears.

  8. Right-click in the Java editor and select Refactor > Encapsulate Fields.
  9. In the Encapsulate Fields dialog, check the boxes to create both getter and setter methods for both the ballotOptions and tally properties, as shown in the figure below.

    Figure 1: Encapsulate Fields Dialog Figure 1: Encapsulate Fields Dialog
  10. Scroll to the init method and add the following code shown in bold to the bottom of the method.

    Code Sample 2: Code to Add to the Application Bean's init Method
            // TODO - add your own initialization code here
            // populate ballot items
            ballotOptions = new Option[] {
                new Option("java", "Java Programming Language"),
                new Option("cpp", "C++"),
                new Option("fortran", "Fortran")
            };
            
            // initialize counters for ballot choices
            tally = new HashMap();
            for (int i=0; i < ballotOptions.length; i++) {
                this.tally.put(ballotOptions[i].getValue(), "0");
            }
  11. Add the following methods at the end of the file, just before the last end brace.

    Code Sample 3: Application Bean Vote Counting Methods
        /**
         * Vote counter for property tally.
         */
        public void incrementTallyFor(String category) {
            int count = getTallyFor(category);
            count++;
            this.tally.put(category, Integer.toString(count));
        }
            
        /**
         * Getter for value in property tally.
         * @param category HashMap key
         * @return Value to which the specified key is mapped
         */
        public int getTallyFor(String category) {
            String stringCount = (String) this.tally.get(category);
            if (stringCount == null) {
                return 0;
            } else {            
                int count = Integer.valueOf(stringCount).intValue();
                return count;
            }
        }   
    
  12. Press Ctrl-S to save your changes, and press Ctrl-F4 to close the file.
  13. In the Navigator window, double-click SessionBean1. This opens SessionBean1.java for editing.

    Note: If the Navigator window is not open, click the Page1 tab in the editing area and click Design in the editing toolbar. The Navigator window appears when the IDE is in design mode.
  14. Next you add the Session bean properties. Under the constructor public class SessionBean1 extends AbstractSessionBean, add the following declaration:
    private boolean hasVoted;
  15. Right-click in the Java editor and select Refactor > Encapsulate Fields.
  16. In the Encapsulate Fields dialog, check the boxes to create both getter and setter methods for the hasVoted property and click Refactor.
  17. Scroll to the init method and add the following code shown in bold to the bottom of the method.

    Code Sample 4: Code to Add to the Session Bean's init Method
            // TODO - add your own initialization code here
            setHasVoted(false);
  18. Press Ctrl-S to save your changes, and press Ctrl-F4 to close the file.
  19. In the Navigator window, double-click RequestBean1. This opens RequestBean1.java for editing.
  20. Add the Request bean properties. Under the constructor public class RequestBean1 extends AbstractRequestBean, add the following declaration:
    private java.util.Date timestamp;
  21. Right-click in the Java editor and select Refactor > Encapsulate Fields.
  22. In the Encapsulate Fields dialog, check the boxes to create both getter and setter methods for the timestamp property and click Refactor.
  23. Click on Page1 tab and then Design button for Page1. Check the Navigator window to ensure that the properties in the request bean, session bean, and application bean match the following figure.

    Figure 4: Request, Session, and Application Bean Properties Figure 4: Request, Session, and Application Bean Properties

Creating the Start Page

Follow the steps in this section to create the page shown running in a browser in the following figure. If the user clicks the Submit Vote button, the page submits the user's vote. Once the user has voted, the button is disabled to prevent the user from voting again in that session.

Figure 5: Page1 Figure 5: Page1
  1. Click Page1 in the editing toolbar.
  2. Drag a Label component from the Basic section of the Palette, drop it onto the top center of the page, and set the label's text to Reader's Poll: What Is Your Favorite Programming Language?.
  3. Drop a Radio Button Group component beneath the Label component.
  4. In the Properties window, set the component's id to voteRBGroup.
  5. Right-click the Radio Button Group component and choose Bind to Data from the pop-up menu.

    A Bind to Data dialog box appears.
  6. In the Bind to an Object tab of the dialog box, select ApplicationBean1 > ballotOptions, and click OK.
  7. Drop a Button under the Radio Button Group component, and set its text to View Results.
  8. In the Properties window, set the id to viewButton.
  9. Click the ellipsis button ellipsis button for the action property, select viewButton_action from the drop-down list, and click OK.

    The IDE adds the viewButton_action event handler, which returns null.
  10. Drop a Button component to the right of the View Results button, and set its text to Submit Vote.
  11. In the Properties window, set the id to voteButton.
  12. Click the ellipsis button ellipsis button for the disabled property.

    This opens the property binding dialog box for the property.
  13. In the dialog box, select Use Binding, click Bind to an Object, and select SessionBean1 > hasVoted, as shown in the following figure, and then click OK.

    Figure 6: Binding the disabled Property Figure 6: Binding the disabled Property
  14. Double-click the Submit Vote button.

    The IDE adds the voteButton_action action handler, opens the Java source for the page, and displays the method.
  15. Replace the body of the method with the following code shown in bold.

    Code Sample 5: voteButton_action Method
        public String voteButton_action() {        
            
            if (voteRBGroup.getSelected() == null) {
                return null;
            }
            
            // Tallies are kept across all user sessions
            String votedFor = voteRBGroup.getSelected().toString();
            getApplicationBean1().incrementTallyFor(votedFor);
            
            // User can only vote one time per session
            getSessionBean1().setHasVoted(true);
            
            // Don't need the timestamp after the next request ends
            Date now = new Date();
            getRequestBean1().setTimestamp(now);
            
            return null;
        }
  16. Right-click in the source and choose Fix Imports from the pop-up menu.
  17. Select java.util.Date from the Date drop-down list, and click OK.

Creating the Results Page

Follow these steps to create the page that is shown running in a browser in the following figure. This page displays the current tally. The user can click the Refresh Results button to get the latest tally, which includes the votes that have been submitted by other users since the page was last displayed.

Figure 7: Results Figure 7: Results
  1. In the Projects window, right-click the Web Pages node under your Scopes project, choose New > Visual Web JSF Page, name the page Results, and click Finish to create the page.
  2. Drop a Label component on the top center of the Results page and set the text to Results.
  3. Drop a Button component to the left of the Label component and set its text to Home.
  4. Set the Button component's id to homeButton.
  5. Click the ellipsis button ellipsis button for the action property, select homeButton_action from the Handler drop-down list, and click OK.
  6. Drop a Button component to the right of the Label component and set its text to Refresh Results.
  7. Set the Button component's id to refreshButton.
  8. Click the ellipsis button ellipsis button for the action property, select refreshButton_action from the Handler drop-down list, and click OK.
  9. Drag a Grid Panel component from the Layout section of the Palette and drop it under the Label Component.
  10. In the Properties window, set the cellspacing property to 10 and the columns property to 1.
  11. Drag a Static Text component inside the Grid Layout component. When the outline of the Grid Layout component becomes a solid blue line, drop the Static Text component, as shown in the following figure.

    Figure 8: Dropping a Component Into a Grid Panel Component Figure 8: Dropping a Component Into a Grid Panel Component
  12. In the Properties window, set the Static Text component's id to resultsST. Leave its text property blank.
  13. Clear the checkbox for the escape property.

    Later, you add code to put HTML in the component's text property. By setting the escape property to false, the HTML code will be passed to the browser unaltered.
  14. Drag another Static Text component onto the Grid Panel component, and, when the outline of the Grid Layout component becomes a solid blue line, drop the Static Text component.
  15. Set the Static Text component's id to messageST. Leave its text property blank.
  16. Click Java in the editing toolbar to view the Java source for the page.
  17. In the Navigator window, double-click the prerender method to open it in the Java editor, and then add the following code shown in bold.

    Code Sample 6: prerender Method
        public void prerender() {
          // Display latest poll results
          ApplicationBean1 appBean = getApplicationBean1();
          Option[] choices = appBean.getBallotOptions();
          String str = "<table border=\"0\" cellpadding=\"5\">";
          for (int i = 0; i < choices.length; i++) {
            int count = 
              appBean.getTallyFor(choices[i].getValue().toString());
            str = str + "<tr><td>" + 
              choices[i].getLabel() +
              "</td><td>" + 
              count + 
              "</td></tr>";
          }
          str = str + "</table>";
          resultsST.setText(str);
          
          RequestBean1 reqBean = getRequestBean1();
          Date timestamp = (Date) reqBean.getTimestamp();
          if (timestamp != null) {
            messageST.setText("Your vote was recorded at " +
              (String)DateFormat.getTimeInstance(DateFormat.LONG).format(
              timestamp));
          }
        }

    This code creates an HTML table that contains the tally for each vote and puts the HTML table in the text property for the first Static Text component. If the user just voted, the second Static Text component displays the date and time the vote was registered.
  18. Right-click in the source and choose Fix Imports from the pop-up menu.
  19. From the Date drop-down list, select java.util.Date.
  20. Select from the Option drop-down list according to the version of Java EE you are using for your project:

Specifying Page Navigation

Follow these steps to specify the page navigation for the buttons, as shown in the following figure.

Figure 9: Page Flow Editor Figure 9 : Page Flow Editor
  1. In the editing area, click the Results tab and click Design to view the page in the Visual Designer.
  2. Right-click on a blank spot in the page and choose Page Navigation from the pop-up menu.

    This displays the faces-config.xml in the Page Flow Editor
  3. Click the + sign in the Page1.jsp icon to enlarge the icon.
  4. Click and drag from the viewButton to Results.jsp to create a connector between the button and the Results page.
  5. Double-click the connector's label to change to edit mode, type view results and press Enter.
  6. Click and drag from the voteButton to Results.jsp.
  7. Double-click the connector's label to change to edit mode, type vote and press Enter.
  8. Click the + sign in the Results.jsp icon to enlarge the icon.
  9. Click and drag from the homeButton to Page1.jsp.
  10. Double-click the connector's label to change to edit mode, type home, and press Enter.

Running the Application

To enable multiple sessions from the same browser, configure the application to end each session after one minute of inactivity. Then deploy and run the application.
  1. In the Files window, expand Scopes > web >WEB-INF, as shown in the following figure.

    Figure 10: Files Window Figure 10: Files Window
  2. Double-click web.xml to open the file in the editor.
  3. Type 1 in the Session Timeout text box, as shown in the following figure.

    Figure 11: Setting Session Timeout in theweb.xml Visual Editor Figure 11: Setting Session Timeout in the web.xml Visual Editor
  4. Save and close the file.
  5. Click the Run Main Project button Run Project toolbar icon in the main toolbar.
  6. When the start page appears, select a radio button and click Submit Vote.

    The browser displays the results page. Note that the results page shows the time that you submitted your vote.
  7. Click Home to return to the start page.

    The Submit Vote is disabled because you have voted.
  8. Click View Results.

    Note that the results page no longer shows the time that you voted. This is because the previous request bean is out of scope and a new request bean has been instantiated.
  9. Wait one minute for the session to time out. Then type the following URL into the browser's address text box, and press Enter to start a new session: http://localhost:8080/Scopes. You might need to change 8080 to a different port if you are not using the default server configuration.
  10. Vote again and check the results. The results should include your first vote.
  11. If you have a different browser application, start that browser, type http://localhost:8080/Scopes into the browser's address text box, and press Enter. Submit another vote.
  12. In the first browser, click Refresh Results from the results page.

    The results should include the vote that you submitted from the second browser.

Doing More

Using what you have learned in this tutorial, build an application that prompts for a login name. Add a page that displays the number of unique users who have accessed the web application.

Summary

You use the application bean, the session bean, and the request bean to store information for use by other pages.



This page was last modified:  December, 2007