users@woodstock.java.net

Data Provider for Table

From: Quintin Beukes <quintin_at_last.za.net>
Date: Sat, 26 Jul 2008 23:15:30 +0200

Hey,

I have a very odd, but very real problem, and unless I understand/use
this wrong, is a problem in the general design of woodstock.

Lets say I'm using a PostgreSQL (because it needs different techniques
to be reproduced for different DBs) table "users", and it looks like
this

id | name
1 | John
2 | Joe

Then I have a managed bean "ManageUsers", and a JSF page
"ManageUsers". Inside this page I have a "<webuijsf:table>" and
"<webuijsf:tableRowGroup sourceData='#{ManageUsers.olUsers}'", where
olUsers is an ObjectListDataProvider instance variable of the
ManageUsers managed bean.

In the table, each row has a text field for the "name", and an update
button which updates that specific row. So inside the action method
for this button, I do the update logic. To do this I retrieve the
object with the olUsers.getObject(rowKey), update it's values with
those in the textfield (ie. name) and then "merge" it using my
facade's EntityManager.merge() method.

This all works fine, but there's a catch.

Since the instance variable isn't "remembered" between requests, I
have to "refresh" it's data, ie. read it from the database again, and
then only can I do getObject(). Also, the getObject() method fetches
the object, based on the row number. So if you update the second row,
then it will fetch the second record retrieved from the database. So
if the natural ordering of the rows changes, or a row comes in between
when using fixed ordering, and the row you updated has it's position
changed, then you will update the wrong row.

So for the above example dataset, load the page and change the name
for the user in the 2nd row, ie. joe. Then go into the database
separately, and update the first row. This means PostgreSQL will now
list the data like so:
id | name
2 | Joe
1 | John

Go back to the page and click the update button. it's trying to update
the row with index 1, so since the data is refreshed using the new
ordering, you're actually updating John, instead of the intended Joe.

The only way to get around this is to store the data provider in the
session, which isn't ideal, because for a large project like mine, the
session object is going to become cluttered with hundreds of data
providers.

But developer comfort isn't a real problem. User experience is. And
when storing the data in the session might cause problems when the
same user has 2 windows open, since both windows will be using the
same session right? Some might argue that this isn't a problem, as the
same data set is represented, but the same problem regarding ordering
will be experienced this way.

Can anyone tell me how to get around this?
--
Quintin Beukes