dataProvider.refresh() in prernder event
Gurus,
I have a page that list parts and user click on "add new part" button to add new records to parts table. It opens up a "Add new Part" page. I have a "Save" button in the add new part page to save the new record.
My question is that how do I refresh the dataProvider of the part listing page, from the "Add New Part" page. I am currently calling dataProvider.refresh() in the prerender event of the part listing page - so that the page is refreshed each time a user clicks on it. I don't think this is the most efficient use of if. Any suggestions?
Please note that both pages use different data providers of session scope.
Part Listing: SELECT * FROM Parts
Add New Part / View Part Detail: SELECT * FROM Part WHERE partID=?
Thanks
[783 byte] By [
Sabir] at [2007-11-26 9:04:30]

# 1
You could have the dataprovider for the partListing page in the Session Bean. After saving new row, you could do getSessionBean1().getPartListingDataProvider().refresh();in the same save action handler.-Sakthi
# 2
Sounds like a good idea, except that the refresh will not be shared across all user sessions. Or may be I should move the PartListing Data Provider and associated RowSet to ApplicatioBean. I wonder by moving it to Application scope, sorting and pagination will be shared across all users. For example, if one user sorts a column then all users will see it, which is not what we want.
When you create a new table and dragg and drop a database table on it, Ctreator creates a DataProvider in the Page scope and a RowSet in Session scope. I wonder what was the thought behind it. Why not create both in session scope or both at page level? In all the tutorial examples, it uses the Creator generated scopes.
Sabir at 2007-7-6 23:15:08 >

# 3
> Sounds like a good idea, except that the refresh will
> not be shared across all user sessions. Or may be I
> should move the PartListing Data Provider and
> associated RowSet to ApplicatioBean. I wonder by
> moving it to Application scope, sorting and
> pagination will be shared across all users. For
> example, if one user sorts a column then all users
> will see it, which is not what we want.
I have the same qualms that you do about sharing a data provider and the underlying data table across all sessions.
The API for the cached row set data provider says:
The lifetime of the RowKeys handed out [by the] CachedRowSetDataProvider is until the underlying CachedRowSet is closed or reexecuted.
So, if I had a table bound to the sessionDataProvider, and someone else does a sessionDataProvider.refresh() then the rowKey values in my table will no longer be in sync with the sessionDataProvider's rowKeys.
What I am hearing from you is that you do not want to execute a query against the database every time someone lands on the master page. Instead, (1) you want a query to be executed only when someone lands on the master page AND the underlying data has changed. (2) Perhaps you even want the a user's view of the table to refresh if the data has changed while a user is actually viewing the table.
Not sure how to do (1). Perhaps you have a listener on the commit calls?
For (2), you would need some sort of asynchronous connection to push the data out , such as AJAX.
# 4
Yes, you are right in interpreting my requirements. I think there has to be an easier way of doing this - instead of callling refresh() on prerender event of master listing. And no AJAX is not the answer, as I don't want the user view of the data to change right away unless they refresh the browser or click on a link to go to next set of listing, etc.
This is a fairly common issue. For example, in salesforce.com, you can see a list of all opppertunities. One can click on an oppertunity to view its details and change the details (like total revenue, etc.) and the the new detail is reflected across all user sessions, both in the oppertunities listing page and oppertunity detail page. I don't think they are refetching the data every single time you click on "Next Page" to go to next 10 listings.
Message was edited by:
Sabir
Sabir at 2007-7-6 23:15:08 >

# 5
So your requirements are:
When a user lands on the master page, the data is refetched only if the database table values are different from what is displayed (that is, if the user lands on the page for the first time, the data is fetched, and, if there has been a commit by some session, then the data is fetched).
However, (and this is the new part that I am not sure about), if the user clicks the Next Page button to display 10 more rows from the fetched data, there must be NO refetch. (hard to say what you want here because you say both "I don't want the user view of the data to change right away unless they refresh the browser or click on a link to go to next set of listing, etc" and "I don't think they are refetching the data every single time you click on "Next Page" to go to next 10 listings.")
My first thought would be to keep an application bean property that is a time stamp and any page that updates the data (does a commit) updates the time stamp. This assumes that this application is the only one that updates the db. The prerender uses the time stamp to decide whether to do a refetch.
This isn't really a problem that is caused by the IDE's constraints. It is more of a problem imposed by the synchronous nature of web applications and web app lifecycles. I am interested to see what types of solutions exist for what seems to be a common scenario. If I find out, I will let you know.
# 6
This is exactly how I was going to approach it - using an application scope property that has a time stamp. I was wondering if there was a better way to do this. Since this is a fairly common use in many web applications, I thought there may be some best practices or built-in tools that I am not aware of. . Tutorials don't touch this, where most web applications that I have seen, would have to manage this scenario. Thanks for your input.
> My first thought would be to keep an application bean
> property that is a time stamp and any page that
> updates the data (does a commit) updates the time
> stamp. This assumes that this application is the only
> one that updates the db. The prerender uses the time
> stamp to decide whether to do a refetch.
>
> This isn't really a problem that is caused by the
> IDE's constraints. It is more of a problem imposed by
> the synchronous nature of web applications and web
> app lifecycles. I am interested to see what types of
> solutions exist for what seems to be a common
> scenario. If I find out, I will let you know.
Sabir at 2007-7-6 23:15:08 >

# 7
Sabir,I have pinged a few engineers to get their ideas. Hopefully they will provide some thoughts.
# 8
Chris, any update on this? I think this information will be useful for many developers. Any data -driven web app where multiple people can read and write data can benefit from this best practice. Thanks.
Sabir at 2007-7-6 23:15:08 >

# 9
Sorry, nothing yet. Between summer vacations and the job to get the add on pack for Creator done, it is hard to get quick responses. I will keep trying.
# 10
Sabir,
I have been thinking about the scenario that you mentioned:
This is a fairly common issue. For example, in salesforce.com, you can see a list of all opppertunities. One can click on an oppertunity to view its details and change the details (like total revenue, etc.) and the the new detail is reflected across all user sessions, both in the oppertunities listing page and oppertunity detail page. I don't think they are refetching the data every single time you click on "Next Page" to go to next 10 listings.
This scenario is a bit different from the other one we were discussing, and has an easy solution. In fact, you can see the solution if you bind a Table component to a data source and enable pagination. When you click the next page button, the table is refreshed using the current data. The application does not refetch the data every single time you click on the next page button.
If you are not using the Table component with its bundled paging mechanism, you can create your own paging mechanism that does not refetch the data.
First you need to set up a flag to indicate whether you want to refetch the data. For my example, I decided that I want to refetch the data every time a user lands on the page from somewhere else or selects a new master. I do not want to refetch the data if the user clicks "Show Next 5".
I added a Standard Data Table and a Button component. I bound the Data Table component to TRAVLEL.FLIGHT
I add a request bean property firstRow. This returns 0 by default when you land on the page from another page, and is thus my "flag".
I modified the methods as follows (please excuse my sloppy code):
public void prerender() {
try {
int first = getRequestBean1().getFirstRow();
if (first == 0) {
getSessionBean1().getFlightRowSet().setObject(1, dropDown1.getSelected());
flightDataProvider.refresh();
}
dataTable1.setFirst(first);
} catch (Exception e) {
error(e.toString());
}
}
public void dropDown1_processValueChange(ValueChangeEvent event) {
getRequestBean1().setFirstRow(0);
}
public String button1_action() {
int first = dataTable1.getFirst();
if (first < flightDataProvider.getRowCount()-5) {
first +=5;
}
getRequestBean1().setFirstRow(first);
return null;
}
Like the paging provided by the Table component, the page iterates through the data and does not refetch the data every time.
