wood burning stoves 2.0*
The moose likes JSF and the fly likes Simple list table Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » JSF
Bookmark "Simple list table" Watch "Simple list table" New topic
Author

Simple list table

Kevin Galligan
Ranch Hand

Joined: Aug 10, 2005
Posts: 70
I posted this on java's forum but I figured I should widen my exposure as I haven't had anybody write back yet. Please forgive me if this is overly simplistic, but I can't find an answer.

Both posts were from me. The basic issue is having a relatively simple table list, assumed to be from a database. The user should be able to click on a link and go to a detail page. I currently implement this with the age old "somePage.jsp?id=123" logic. I'm trying to do the JSF equivalent and running into very obvious issues.

I think there might be a paradigm mismatch, as if you were working with a desktop app, you would have to hit some type of refresh button to repopulate your list of table entries. In jsf, you can keep your entries in a session variable and only change that list when the user explicity requests the refresh. That makes sense to a programmer, but that's not really what one would expect on the web. When the page reloads, there's an expectation that what you're looking at is what's current. This also doesn't solve the back button problem.

Anyway, the posts...

****************** First Post ******************

I've been working with JSF for about a week, and I think there's something I'm really missing with the datamodel/table structure. I want to build a simple table that displays a list of items, and allows the user to click on one to (generally) see detail on that item. This is a basic ui pattern in web development.

Generally I do this by appending an id value(s) of some type(s) to the query string, and using that in the target url to pull up and display data.

I've been working from the O'reilly jsf book. The example in there provides the following accessor for table entries in its chapter 10 example...

/**
* Returns a DataModel with Report instances matching the
* filtering criteria, sorted according to the current
* sort column and order.
*/
public DataModel getSortedReportsModel() {
if (reportsModel == null) {
reportsModel = new ListDataModel();
}
List reports = getReports();
sortReports(reports);
reportsModel.setWrappedData(reports);
return reportsModel;
}

The basic idea here is that the jsp page uses this as its data source for the table of elements to choose from...

<f:view>
<h:form>
<h ataTable value="#{reportHandler.sortedReportsModel}" var="report">
<h:column>
<f:facet name="header">
<h:commandLink action="#{reportHandler.sortByTitle}"
immediate="true">
<h utputText value="Title" />
</h:commandLink>
</f:facet>
<h:commandLink action="#{reportHandler.select}" immediate="true">
<h utputText value="#{report.title}" />
</h:commandLink>
</h:column>
<h:column>
[more code...]

My questions are as follows:

1. What happens if somebody adds an entry between the time the user first gets the list and when they click on a link? The entries are linked by index and not id, so this could pose a problem.

2. What happens if, for example, the user gets the list, then sorts by a different value, then clicks back and clicks a link? On the server it would still use the list position, but with the new sorting, to decide which element to pick.

Does there exist some DataModel extension or renderer that could allow list selection by value rather than by index? Again, I've been doing jsf for about a week, so I'm not sure if that's a stupid question.

I'm assuming that I'm either doing this wrong or there is an easy way to get this to work as I think it should, and have a more natural flow. I'm just missing something.

Thanks in advance,
-Kevin

****************** End First Post ******************

****************** Second Post ******************

I got the example from the O'reilly book running and tried my little problem example. It had the same issue as my application as far as selecting list elements.

Now, the only reasons I'm picking on this example are that:

a) Its pretty public, as you can buy the book and/or download the example at http://www.hansbergsten.com/downloadjsf.jsp

b) Considering the book I'm using and the author, this is how one "should" be implementing this.

Anway, if you install this app, and go to the index page, click on expense report app final version in "Chapter 12". Enter say 3 report entries, with various dates. Then open a different window, preferably in a different browser to prevent session tampering (but I don't think this is required). Click on "Report List Area, stage 3". You'll see your 3 entries. Go back to the other browser, and add another entry. Make sure this date is the newest of the group. Alt+Tab back to the other browser with the table list. Click on the first. You would expect to see the entry you clicked on, but you will see the newest entry.

This is clearly not how this should be implemented. What's the recommended way to handle this?

****************** End Second Post ******************
Gregg Bolinger
GenRocket Founder
Ranch Hand

Joined: Jul 11, 2001
Posts: 15299
    
    6

Alright, I am going to show you how I do what you are wanting to do. I believe the code will basically answer all these questions. Each UIData is specific to the users session. So no matter how many other people come in and add items or remove items, everyone has their own UIData and has their own categoryList. So you don't have any issues with clicking and getting the wrong data. JSF handles all this for you. No more GET paremeter query strings.





[ August 10, 2005: Message edited by: Gregg Bolinger ]
[ August 10, 2005: Message edited by: Gregg Bolinger ]

GenRocket - Experts at Building Test Data
Kevin Galligan
Ranch Hand

Joined: Aug 10, 2005
Posts: 70
I think you're in the same boat I am, unless I'm missing something.

I assume you're declaring CategoryAdmin to be in session scope? Now you're ok if somebody adds something to the central store, however there are other problems. I covered this in the last paragraph of the first part of my post...

"In jsf, you can keep your entries in a session variable and only change that list when the user explicity requests the refresh. That makes sense to a programmer, but that's not really what one would expect on the web. When the page reloads, there's an expectation that what you're looking at is what's current. This also doesn't solve the back button problem."

So, if your code just displays what's in the CategoryAdmin session object, how do you show new category data? If you hit refresh, it should just pull the stale data from the session. So, you have to add a special button to "refresh" the data and force a cache dump. The user, however, would expect a browser refresh to do this.

So, if you change the code to pull from the data store every time so the browser refresh button functions as expected, you're back where I started.

Now, your solution still doesn't address the back button issues. Lets say I go to your page...

<row #1><dataId #1><name "Sam">
<row #2><dataId #2><name "Bill">
<row #3><dataId #3><name "Mike">
<row #4><dataId #4><name "Tammy">

Then click a button to sort by the 'name' column.

<row #1><dataId #2><name "Bill">
<row #2><dataId #3><name "Mike">
<row #3><dataId #1><name "Sam">
<row #4><dataId #4><name "Tammy">

Then click the browser back button and select "Bill". When the detail page comes up, I'll get "Mike". Right?
Gregg Bolinger
GenRocket Founder
Ranch Hand

Joined: Jul 11, 2001
Posts: 15299
    
    6

The back button and JSF is a known issue that will be addressed in 2.0 so let's just skip that for now.

As far as the other things. I don't have the problems you are describing. I have my CategoryAdmin managed-bean in request scope. Now, if you have issues when you hit "refresh" on your browser, that could be because hitting refresh possibly pulls the page from the browsers cache and never actually requests the page from the server again, therefore, never updating your data.

When the page reloads, there's an expectation that what you're looking at is what's current.

Personally, I rarely rely on any browser button functions. I want full control of what my app is doing all the time. So yes, I might code a special refresh button if I wanted to handle this differently. I don't really see this as an issue. Just more of how a browser handles things. However, if you changed my backing bean to look like this...



then every single time your page is refreshed for whatever reason, and the dataTable went and fetched the categoryList value using the above method, the data should be current, no matter if you're sorting or doing whatever.
Kevin Galligan
Ranch Hand

Joined: Aug 10, 2005
Posts: 70
I was reading up a little on 1.2. They do mention that the back button issue is solved. Does this mean that it "works", shows an error, or just brings the user back to the current view?

Your CategoryAdmin is in request scope, but is CategoryService in session? Is the list retrieved by 'catService.getall()' held in the user's session, or in a global storage of some type (database, application level memory, etc)? If that List is not kept in the user's session in some manner, or at least specifically tied to that user, I think you would have the problem I'm having. If that list is externally updated while your user is looking at your page, before they click on one, your indexes could be incorrect. At least that's the issue I'm having.

I guess it comes down to this question. Does the dataTable hold onto the object reference for each Category object inside the UIData object, so the call to 'categoryData.getRowData()' returns the original object?

If yes, then ignoring the back button, things are ok. We don't need to keep that list in a session variable, or hit the data store to refresh the data (although you will if its in the constructor).

If not, it would have to go back to the table parent object and get the Category object through a reference to '#{categoryAdmin.categoryList}'. At that point we're back to square 1. Keep that list in the session in some fasion, or suffer the consequences.

I'm assuming no because it would need to persist your Category object to the client if the config specified to persist UI state on the client (correct?) rather than the default server state.

I should move onto other stuff, but I'm sure I'll wind up trying this tonight instead.

The refresh issue isn't a browser cache thing. Browser apps is all I do all day every day.

Before I write the next section, please keep in mind that I do honestly appreciate you taking the time to respond to my questions. I come off harsh sometimes in text, but I'm really just looking for some guidance and yours is certainly appreciated. However...

Personally, I rarely rely on any browser button functions. I want full control of what my app is doing all the time.

Are you building internal apps? My concern is not that I "rely" on the buttons rather than I can't stop people from using them. I think if there were a standard way to say, "No back, forward, stop or refresh functionality", every web application developer would use it. You can pop up a window without those buttons, and you can disable some right-clicking, but ultimately there's a way to do what you want to do. Hot keys and such. If an error popped up saying that you shouldn't have done that and you will be taken to the proper page, that might be ok, but that's some extra code at least.

In the current implementation not only could it not work, you could potentially be dealing with simply the wrong data. If your indexes were messed up, and you were updating data, it might update values on the wrong object. At best annoying. At worst litigious. Any application opens the door to bugs, but the example that started this whole thing for me was out of a reference book, and seems to be considered standard practice.

Also, I think if you're careful, you can build the applications to use the browser navigation. There are areas of flow in which this should be prevented, but often navigating a data set isn't one of them.

I feel like an old man, stuck in my ways.
Gregg Bolinger
GenRocket Founder
Ranch Hand

Joined: Jul 11, 2001
Posts: 15299
    
    6

I suppose I should mention that I use the MyFaces implementation of JSF. That said, you might be interested in their DataTable extension. Maybe it addresses some of the issues you are having if you are not using MyFaces.

(In my example, I used MyFaces however, for simplicity sake of what I was showing you I pulled out some of the MyFaces specific attributes used.

...but the example that started this whole thing for me was out of a reference book, and seems to be considered standard practice.

Never assume a book is using best practices. In fact, they usually aren't. They typically show you the easiest way to get something done which isn't always the best way.
Kevin Galligan
Ranch Hand

Joined: Aug 10, 2005
Posts: 70
Ahh, see, that's what I'm talking about. That extension solves the problem. I tried both the "data added while on the screen" issue, and navigating from the back button after sorting. Both issues are solved. When I get the chance I want to crack open the code and see how its actually doing it, as I imagine it must be re-getting the list data model and looping through for the id on submit, but still it works...

<f:view>
<h:form>
<x ataTable value="#{reportHandler.sortedReportsModel}" var="report"
forceIdIndexFormula="#{report.id}"

rows="#{reportHandler.noOfRows}"
first="#{reportHandler.firstRowIndex}"
styleClass="tablebg" rowClasses="oddRow, evenRow"
columnClasses="left, left, left, right, left">
<h:column>
<f:facet name="header">
<h:commandLink action="#{reportHandler.sortByTitle}"
immediate="true">
<h utputText value="Title" />
</h:commandLink>
</f:facet>
<h:commandLink action="#{reportHandler.select}" immediate="true">
<h utputText value="#{report.title}" />
</h:commandLink>
</h:column>
<h:column>

Thanks for the help.
Gregg Bolinger
GenRocket Founder
Ranch Hand

Joined: Jul 11, 2001
Posts: 15299
    
    6

Great! Glad it is all working for you now.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Simple list table
 
Similar Threads
Please HELP me. How To Hard Code Values in Each Row of a dataTable?
HtmlDataTable and "duplicate ID"
using h:selectManyCheckbox inside h:dataTable
JSF java.util. Concurrent ModificationException
how to use TreeSelectionListener in a tree ?