Table Component Sample Visual Web Project for NetBeans IDE 6.0

I migrated the sample tutorial project that I created for the Sun Java Studio Creator IDE into a NetBeans IDE 6.0 web application that uses the Visual Web Java Server Faces framework. You can download this NetBeans IDE project from here. If the pages do not display in the Visual Designer (and you get an error page instead), do a clean build, then close and reopen the IDE.

Note that this project uses the JSF 1.4 versions of the Web UI components, and not the newer versions.

This sample project:

  • Gets the data from an ObjectListDataProvider
  • Has dropdown lists, checkboxes, and buttons in the table
  • Has input fields that are not associated with the underlying data provider, so the input needs to be stored separately
  • Calculates totals from the selected table rows
  • Has dynamic footer information

When you click a detail button, the button's action method uses a tableRowGroup method to get the row key for the row that the button is in. The method then uses the row key to get the value for the foodId column, which it saves in the request bean for use by the detail page.

    public String showDetailBtn_action() {
        // Find out what row was clicked
        RowKey rowKey = tableRowGroup1.getRowKey();
        // Save food id so detail page knows what food item to show
        // provide detail info for
        getRequestBean1().setFoodId(
          getSessionBean1().getFoodListDataProvider().
          getValue("foodId", rowKey).toString());
        return "detail";
    }

The checkbox column is not bound to any column in the dataprovider, but is instead bound to a page property named selected. The getter and setter use a TablePhaseListener object to manage which checkboxes are selected.

    public void setSelected(Object object) {
        RowKey rowKey = tableRowGroup1.getRowKey();
        if (rowKey != null) {
            tablePhaseListener.setSelected(rowKey, object);
        }
    }

    /\*\*
     \* Getter for selected.
     \* @return Object value for the current row's checkbox
     \*/
    public Object getSelected() {
        RowKey rowKey = tableRowGroup1.getRowKey();
        return tablePhaseListener.getSelected(rowKey);
    }

Winston explains how to do this as well as how to highlight the rows that are selected in his How to Create Muli-Row Selectable Table Component blog.

To calculate calories, the Calculate Calories button's action method calls a method that iterates over the tableRowGroup object's selectedRowKeys to accumulate the total calories for the selected rows.

    public String calculateCaloriesBtn_action() {
        getSessionBean1().setTotalCalories(getTotalCalories());
        return null;
    }

    public String getTotalCalories() {
        int total = 0;
        // Go through the list of selected rows
        Integer calories;
        Integer nbrServings;
        FoodListDataProvider foodListDP =
          getSessionBean1().getFoodListDataProvider();
        RowKey[] selectedRowKeys =
          getTableRowGroup1().getSelectedRowKeys();
        for (int i = 0; i < selectedRowKeys.length; i++) {
            String rowId = selectedRowKeys[i].getRowId();
            RowKey rowKey = foodListDP.getRowKey(rowId);
            // get serving size
            String size = (String)
              getSessionBean1().getServingSizeMap().get(rowId);
            // get calories for serving size
            calories = (Integer) foodListDP.getValue(size, rowKey);
            // get number of servings
            nbrServings = (Integer)
              getSessionBean1().getNbrServingsMap().get(rowId);
            // add to total
            total += calories.intValue() \* nbrServings.intValue();
        }
        return Integer.toString(total);
    }

The Nbr Servings text field and Serving Size drop down list are also not bound to the underlying data provider. I created Map objects to store the values for each row and bound the components to session bean properties.

    
    /\*\*
     \* Getter for property nbrServings.
     \* @return Value of nbrServings for current row
     \* defaults to 1
     \*/
    public Integer getNbrServings() {
        TableRowDataProvider rowData = 
          (TableRowDataProvider) getBean("currentRow");
        if (rowData == null) {
            return new Integer(1);
        } else {
            String rowId = 
              rowData.getTableRow().getRowId();
            Integer nbrServingsValue = 
             (Integer) this.getNbrServingsMap().get(rowId);
            if (nbrServingsValue == null) {
                return new Integer(1);
            } else {
                return  nbrServingsValue;
            }
        }
    }
    
    /\*\*
     \* Setter for nbrServings for current row
     \* @param nbrServings New value of nbrServings.
     \*/
    public void setNbrServings(Integer nbrServings) {
        TableRowDataProvider rowData = 
          (TableRowDataProvider) getBean("currentRow");
        if (rowData != null) {
            String rowId = rowData.getTableRow().getRowId();
            this.getNbrServingsMap().put(rowId, nbrServings);
        }
    }
    
    /\*\*
     \* Getter for servingSize.
     \* @return Value servingSize for current row
     \* Defaults to cup
     \*/
    public String getServingSize() {
        
        TableRowDataProvider rowData = 
         (TableRowDataProvider) getBean("currentRow");
        if (rowData == null) {
            return "cupCalories";
        } else {
            String rowId = rowData.getTableRow().getRowId();
            String servingSize = 
             (String) this.getServingSizeMap().get(rowId);
            if (servingSize == null) {
                return "cupCalories";
            } else {
                return  servingSize;
            }
        }
    }
    
    /\*\*
     \* Setter for servingSize for current row
     \* @param servingSize New value of property servingSize.
     \*/
    public void setServingSize(String servingSize) {
        TableRowDataProvider rowData = 
         (TableRowDataProvider) getBean("currentRow");
        if (rowData != null) {
            String rowId = rowData.getTableRow().getRowId();
            this.getServingSizeMap().put(rowId, servingSize);
        }
    }
    
    /\*\*
     \* Holds value of property nbrServingsMap.
     \*/
    private Map nbrServingsMap = new HashMap();
    
    /\*\*
     \* Getter for property nbrServingsMap.
     \* @return Value of property nbrServingsMap.
     \*/
    public Map getNbrServingsMap() {
        
        return this.nbrServingsMap;
    }
    
    /\*\*
     \* Setter for property nbrServingsMap.
     \* @param nbrServingsMap New value of property nbrServingsMap.
     \*/
    public void setNbrServingsMap(Map nbrServingsMap) {
        
        this.nbrServingsMap = nbrServingsMap;
    }
    
    /\*\*
     \* Holds value of property servingSizeMap.
     \*/
    private Map servingSizeMap = new HashMap();
    
    /\*\*
     \* Getter for property servingSizeMap.
     \* @return Value of property servingSizeMap.
     \*/
    public Map getServingSizeMap() {
        
        return this.servingSizeMap;
    }
    
    /\*\*
     \* Setter for property servingSizeMap.
     \* @param servingSizeMap New value of property servingSizeMap.
     \*/
    public void setServingSizeMap(Map servingSizeMap) {
        
        this.servingSizeMap = servingSizeMap;
    }
    
Comments:

Hello,
I didnt catch you where you wrote:
return "detail";
at howDetailBtn_action()

I opened page navigation to find where you are taking the detail but detail is not ont he page navigation....

Bye and thank you.

Posted by Mauricio on October 05, 2007 at 06:43 AM PDT #

Hi Mauricio,

I think there might have been some kind of bug with this early version of the migration software that I used to migrate the Creator project to NetBeans. You are correct that when you bring up the Page Navigation, it does not show the linkage between the pages.

However, in the Projects window, expand Configuration Files and double-click navigation.xml. For me, this opens a Page Navigation that does show the linkage. Does it work for you?

Posted by Diva #2 on October 05, 2007 at 07:24 AM PDT #

Hello,
You r sure regards the navigation.xml.
And I'm not understanding from where the informations on the table are coming...
one more question....
Both netbeans 5.5 and 6.0 beta are very slow in my machine.
Are there any configuration to fix this slowness?
I have 512 of memory ddr2 and AMD Athlon 64 processor

Bye.

Posted by Mauricio on October 07, 2007 at 04:11 AM PDT #

Mauricio,

You wrote: "You r sure regards the navigation.xml." I do not understand what you are saying.

To answer your question about where the data is coming from...The table is bound to the FoodListDataProvider. To understand how that works, see http://www.netbeans.org/kb/55/vwp-hibernate.html#object.

Note that this project was originally created for the Sun Java Studio Creator IDE. I simply migrated it to NetBeans 6.0 and did not change any code to take advantage of the 6.0 features. You no longer need to wrap the data with a data provider. See http://www.winstonprakash.com/articles/netbeans/JPADataBinding.html for other options.

For the answer to your final question, I suggest that you search the archives of the nbusers (http://www.nabble.com/Netbeans---Users-f2605.html) and vwp-interest (http://www.nabble.com/Visual-Web-f24578.html) mailing lists. There has been discussion on that topic.

Posted by Diva #2 on October 08, 2007 at 03:45 AM PDT #

Hello,
What I am supposed to say is that I could see the details at navigation.xml it opens the Page navigation that shows the linkage.

I installed the Sun java studio creator today...this is the first time that I use Sun Java studio creator and it´s 10x faster than netbeans!!!
I´m trying to do your entire article..thank you for your contribution!
:)
Have a nice week

Posted by Mauricio on October 08, 2007 at 05:18 AM PDT #

i download your example and i found a getter method called getCalories and did not saw where you use it.

i have a problem using a dropdownlist in a table component, i don't know how to get each value in the dropdownlist.

sorry about my english, and thank you so much

Posted by Gustavo on January 02, 2008 at 05:03 AM PST #

Gustavo,

You are correct. I do not use that property. I forgot to remove that bit of detritus. It is not working code.

Take a look at getTotalCalories(). The program is using the servingSizeMap to store the values for the drop down list.

Posted by Diva #2 on January 03, 2008 at 05:51 AM PST #

hi there,
I imagined that, but let me ask you someting, where you store the servingSizeMap?, in getTotalCalories() or in getServingSize() from the sessionBean1?

i did not catch where you get those values from the dropdownlist; becouse when i debug the proyect i put the breakpoint in the "for" sentence of getTotalCalories and it seens like the hashMap was fill it previously

thanks for all

Posted by Gustavo on January 03, 2008 at 07:02 AM PST #

Is there no way to make the textField in the table right-aligned?

I tried the Style properties on the properties window and change it to text-align:right but was ineffective.

I have tried this and other examples but I cannot find one that have a table containing right-aligned numeric field.

Posted by cyber dummy on January 09, 2008 at 04:19 PM PST #

solved.

Posted by cyber dummy on January 15, 2008 at 04:43 PM PST #

Hi CD,

Sorry I didn't reply, I hadn't had time to look into it. How did you solve it?

Posted by Diva #2 on January 16, 2008 at 12:38 PM PST #

Hello Divas.
Cool stuff. Here is a question not so much related with the DB side of the tutorial: why in the netbeans 6 (don't know about other versions or IDEs) the Table component does not show the same in Firefox en Internet Explorer? is there a fix/config? im with Mozila firefox 2.0.0.11, and the page buttons don't render properly. Only the "Page [ ] of 3 {Go}" thing shows, the others like <, |<, >, >|, 'show in pages/all in one page' toggle buttons are nowhere in sight. I'm in Brazil, the "Go" button shows as "Ir" as expected, but not the other stuff.
Any help will be appreciated.

Posted by Ramiro on January 21, 2008 at 07:39 AM PST #

Hello Ramiro,

For me, both IE and Firefox render the table the same, with the paging buttons and all. I suggest that you write to the nbusers alias. Someone there might have a similar problem or a solution for you. See http://www.netbeans.org/community/index.html.

Posted by Diva #2 on January 22, 2008 at 04:19 AM PST #

I'm like Gustavo, i don't see how you get the value of your dropdown lists.
thanks for your help.

Posted by Patrice on February 08, 2008 at 12:52 AM PST #

Patrice,

To get the selected serving size for a row, call getSessionBean1().getServingSizeMap().get(rowId)

Posted by Diva #2 on February 08, 2008 at 01:16 AM PST #

´lo Divas,
Im working in a CRUD-like application, experimenting with Visual JSF, Netbeans 6.0, mixing stuff from this site with this one:
http://www.netbeans.org/kb/60/web/inserts-updates-deletes.html

I can create a table, with drop down lists, text fields, and other editable components without problem. The table is databound to a tripDataProvider, from the sample Trip database, which returns all records from that table. the tripType column is represented with drop down lists, wich are databound to the tripType table, so it show sthe name of the trip type instead of its id.
I have a "Save Changes" button, that calls:
tripDataProvider.commitChanges();

So far so good. I can save any changes by clicking save. And i have a "Details" button, wich calls code to get the id from the clicked row on the table. The details page uses that ID with a data provider to show the info from the db in another databound component (for now im just using another table)

My details page is pretty much the same as the list page, the only difference is i dont have a detail button in the detail page(duh), and that i use a data provider with a row set that accepts 1 parameter (the current trip id from the list page).

The problem (finally):
Why cant i save from the details page? I call commitChanges() from the data provider bound to the table, but i get an error saying that i have to initialize one parameter;
I initialize said parameter, error is gone but no save is made.

From what i see, if the data provider uses a row set that uses a parameter in the select statement, i cant use it to write in the database. Any truth in that?

Posted by Ramiro on April 17, 2008 at 10:46 PM PDT #

Hi Ramiro,

It has been a long time since I worked on the VWP pack, so my memory is a bit rusty. You can certainly commit an updated record. You don't give much details about what is going on so it is hard to tell where to put the fix. See Joe Brown's blog for how to do logging (and other good info about data providers) at http://blogs.sun.com/jfbrown/

Some other resources:

http://blogs.sun.com/divas/entry/simple_form_tutorial

http://blogs.sun.com/divas/entry/sqlexception_at_least_one_parameter

http://developers.sun.com/jscreator/reference/techart/2/index.jsp#Working%20with%20Data%20Tables (working with data tables section)
While these are for Sun Java Studio Creator, they should give you an idea how to work with data providers. I would suggest looking at the code in the Two Page CRUD with Table Sample App.

Posted by diva#2 on April 18, 2008 at 07:10 AM PDT #

I think i narrowed the problem down, doesn't seem to be with the data providers, but the clicking of the button, as strange as it sounds. Here is the updated scenario:

Visual Web JSF application, with three visual jsf pages, Page1, Page2 and Page3. Working with the Travel sample database. [netbeans 6.0.1, updated Woodstock components to last stable release]

Page 1: Woodstock table, databound to the Person table in the db(simple drag and drop). Added a button column, with the button action:

RowKey rowKey = tableRowGroup1.getRowKey();
Integer personID = (Integer)personDataProvider.getValue("PERSONID", rowKey); getRequestBean1().setCurrentPerson(personID);
return "toMyTripsPage";

CurrentPerson is an attribute in the request bean.
faces-config maps the return to Page2.

Page2: pretty much the same thing, except that the table is bound to the Trips db table, and the tripsRowSet takes a parameter in the person field. The attribute is set in Page2´s preRender with:

Integer personID = getRequestBean1().getCurrentPerson();
this.getSessionBean1().getTripRowSet().setObject(1, personID);
tripDataProvider.refresh();

A button column is added to the table, with the action:

RowKey rowKey = tableRowGroup1.getRowKey();
Integer tripID = (Integer) tripDataProvider.getValue("TRIPID", rowKey);
getRequestBean1().setCurrentTrip(tripID);
return "toTripDetailsPage";

faces-config maps the return value to Page3. Repetitive, isnt? If anybody is still awake, here is where it gets weird. Same ritual, a woodstock table bound to Trips db table, with its own rowset with a parameter for the tripId. the table should show a single row, the selected trip from the previous page. Which it does! all works fine, except when i add a button column to this table. Anything i add in the button action does not get executed. im serious, not even a JOptionPane with a showMessageDialog. The page does react to the button click, but behaves like there is nothing in the action method that would be returning null, which just refreshes the table. if i add any code in the action, even different string return value, doesn't matter.

Sanity check: At least my expectation is what it should be?(the code from the button1_action() should be called)

Posted by Ramiro on April 22, 2008 at 11:29 AM PDT #

Ramiro

If the action method is not being invoked and if the page is not getting redirected then that is usually indicative of a runtime error. Do you have a message group component on the page to report runtime errors? In addition, you can look at the server output window to see it there are any errors being reported. Look for conversion errors.

Sorry I took so long to reply but I have been on vacation.

Posted by diva#2 on May 02, 2008 at 12:37 AM PDT #

Hello Divas,

I want to create such a table component like this but i get the datas from an oracle database. I use entity beans. My query that selects the datas from the database is sophisticated. I cannot use the ObjectListDataProvider because there are joined two table in my query. (Something like this: SELECT x.name, y.address FROM table1 x, table2 y WHERE x.id = y.id) And in this case the result contains not only one object. What can i do? What kind of dataprovider does solve the problem? I have to use Visual Web Pack by all means. I have already tried the ListDataProvider however I cannot force to operate.
I hope it is clear what's my problem!

Thanks for all!

Posted by Andor on May 11, 2008 at 11:57 PM PDT #

Andor,

You might want to take a look at http://www.netbeans.org/kb/55/vwp-hibernate.html. This is an old tutorial and I believe that they have made improvements since I wrote this (I no longer work on the Visual Web Pack team and have not been very gook at keeping up with the new features). Another tutorial that might interest you is http://www.netbeans.org/kb/60/web/web-jpa.html.

Posted by diva #2 on May 12, 2008 at 02:52 AM PDT #

Post a Comment:
Comments are closed for this entry.
About

divas

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today