rich:dataTable - rich:dataScroller

H

Hollow Quincy

Hi,

I am trying to use RichFace 4.1 rich:dataTable with rich:dataScroller.
I am trying to use scroller like that:

<rich:dataTable value="#{tableBean.users}" var="user" rows="10" >
<f:facet name="footer">
<rich:dataScroller page="#{tableBean.pageNumber}" maxPages="5"></
rich:dataScroller>
</f:facet>
</rich:dataTable>

I cannot find properties of the scroller that would refer to my bean
and I would be able to tell scroller that he can display "next" /
"last" buttons.

Is it better to write my own scroller ?

Thanks for help
 
A

Arved Sandstrom

Hi,

I am trying to use RichFace 4.1 rich:dataTable with rich:dataScroller.
I am trying to use scroller like that:

<rich:dataTable value="#{tableBean.users}" var="user" rows="10" >
<f:facet name="footer">
<rich:dataScroller page="#{tableBean.pageNumber}" maxPages="5"></
rich:dataScroller>
</f:facet>
</rich:dataTable>

I cannot find properties of the scroller that would refer to my bean
and I would be able to tell scroller that he can display "next" /
"last" buttons.

Is it better to write my own scroller ?

Thanks for help

I haven't used RichFaces but simply looking at the 4.1 component docs
tells me that there are dataScroller facets for specifying first, last,
next, previous. The wording implies that they are for customization: are
you saying that if you don't specify them then you don't even see them?

I'll assume when you're testing that other things are OK, like the users
table having a bunch of data.

I may give RichFaces a whirl, this has me curious.

No, you don't particularly want to write your own scroller. :) I've
worked with the source for one paginating JSF table (with true
pagination) that has this "dataScroller" functionality, and while it's
not the most difficult task in the world there is a fair amount of Java
and Javascript to get right. The only reason I used this custom code is
because it was written quite a few years ago for JSF 1.1, when nobody
else had anything yet.

AHS
 
H

Hollow Quincy

On 31 Gru, 02:40, Arved Sandstrom <[email protected]>
wrote:
[...]
I haven't used RichFaces but simply looking at the 4.1 component docs
tells me that there are dataScroller facets for specifying first, last,
next, previous. The wording implies that they are for customization: are
you saying that if you don't specify them then you don't even see them?

I'll assume when you're testing that other things are OK, like the users
table having a bunch of data.

I may give RichFaces a whirl, this has me curious.

No, you don't particularly want to write your own scroller. :) I've
worked with the source for one paginating JSF table (with true
pagination) that has this "dataScroller" functionality, and while it's
not the most difficult task in the world there is a fair amount of Java
and Javascript to get right. The only reason I used this custom code is
because it was written quite a few years ago for JSF 1.1, when nobody
else had anything yet.
[...]

I was looking for documentation and I've found only this:
http://docs.jboss.org/richfaces/latest_4_X/vdldoc/rich/dataScroller.html

I can not find any property that would specify numbers of all page or
number of all records.

When I am using it like this:
<rich:dataScroller page="#{tableBean.pageNumber}" maxPages="5" />
in my bean I have my current "pageNumber" and scroller show five
buttons.
In table I have code:
<rich:dataTable value="#{tableBean.users}" var="user" rows="10" >
getUsers() method return only 10 users (because I can read from
database specified "page" of users, I don't read all table at once).
When I give 10 users to dataTable, scrollers buttons are not active.

I do not want to read all table from database. I want to read per 10
users only for every page click.

Thanks for help
 
A

Arved Sandstrom

On 31 Gru, 02:40, Arved Sandstrom <[email protected]>
wrote:
[...]
I haven't used RichFaces but simply looking at the 4.1 component docs
tells me that there are dataScroller facets for specifying first, last,
next, previous. The wording implies that they are for customization: are
you saying that if you don't specify them then you don't even see them?

I'll assume when you're testing that other things are OK, like the users
table having a bunch of data.

I may give RichFaces a whirl, this has me curious.

No, you don't particularly want to write your own scroller. :) I've
worked with the source for one paginating JSF table (with true
pagination) that has this "dataScroller" functionality, and while it's
not the most difficult task in the world there is a fair amount of Java
and Javascript to get right. The only reason I used this custom code is
because it was written quite a few years ago for JSF 1.1, when nobody
else had anything yet.
[...]

I was looking for documentation and I've found only this:
http://docs.jboss.org/richfaces/latest_4_X/vdldoc/rich/dataScroller.html

I can not find any property that would specify numbers of all page or
number of all records.

When I am using it like this:
<rich:dataScroller page="#{tableBean.pageNumber}" maxPages="5" />
in my bean I have my current "pageNumber" and scroller show five
buttons.
In table I have code:
<rich:dataTable value="#{tableBean.users}" var="user" rows="10" >
getUsers() method return only 10 users (because I can read from
database specified "page" of users, I don't read all table at once).
When I give 10 users to dataTable, scrollers buttons are not active.

I do not want to read all table from database. I want to read per 10
users only for every page click.

Thanks for help
I fired up a rich:dataTable with a rich:dataScroller just now, running
on JBoss AS 7, using Richfaces 4.1. It's simply pointing at a list for
the moment, works like a charm.

I have enough items in the list that with rows="5" I have 8 pages of
data, with maxPages="5" I only see 5 explicit numbered page buttons in
the scroller (as expected), I see First, Last, <<, >>, << <<, >> >>,
everything enabled or disabled properly depending on currently selected
page.

That's just for my satisfaction, I haven't used Richfaces before and
wanted to try this out. However, I can see what your problem is: if you
are implementing naive data pagination, which you are, what makes you
think that rich:dataScroller has any idea that you've got more than 10
users total? It doesn't. I can easily confirm the same effect if I code
naive data pagination.

Some googling and some experimentation shows me that
org.ajax4jsf.model.SequenceDataModel<E> which extends
org.ajax4jsf.model.ExtendedDataModel<E> is a good way to go. You
probably won't have to override more than a few methods even for DB
access, it looks like walk() and getRowCount() are among the obvious
few. Your rich:dataTable (and hence the scroller) will simply see your
SequenceDataModel subclass, and it's that which will fake out the
scroller as to perceived row count and getting the correct rows.

AHS
 
H

Hollow Quincy

On 31 Gru 2011, 17:46, Arved Sandstrom <[email protected]>
wrote:
[...]
I fired up a rich:dataTable with a rich:dataScroller just now, running
on JBoss AS 7, using Richfaces 4.1. It's simply pointing at a list for
the moment, works like a charm.

I have enough items in the list that with rows="5" I have 8 pages of
data, with maxPages="5" I only see 5 explicit numbered page buttons in
the scroller (as expected), I see First, Last, <<, >>, << <<, >> >>,
everything enabled or disabled properly depending on currently selected
page.

That's just for my satisfaction, I haven't used Richfaces before and
wanted to try this out. However, I can see what your problem is: if you
are implementing naive data pagination, which you are, what makes you
think that rich:dataScroller has any idea that you've got more than 10
users total? It doesn't. I can easily confirm the same effect if I code
naive data pagination.

Some googling and some experimentation shows me that
org.ajax4jsf.model.SequenceDataModel<E> which extends
org.ajax4jsf.model.ExtendedDataModel<E> is a good way to go. You
probably won't have to override more than a few methods even for DB
access, it looks like walk() and getRowCount() are among the obvious
few. Your rich:dataTable (and hence the scroller) will simply see your
SequenceDataModel subclass, and it's that which will fake out the
scroller as to perceived row count and getting the correct rows.
[...]

Thanks for answer.
You are right that I have to extend some class. I was reading about
this, and it seems to be complicated. (I have to override a lot of
event).
In my oppinion it is faster to write my own paginator..

What do you think about writting own paginator ?
 
A

Arved Sandstrom

On 31 Gru 2011, 17:46, Arved Sandstrom <[email protected]>
wrote:
[...]
I fired up a rich:dataTable with a rich:dataScroller just now, running
on JBoss AS 7, using Richfaces 4.1. It's simply pointing at a list for
the moment, works like a charm.

I have enough items in the list that with rows="5" I have 8 pages of
data, with maxPages="5" I only see 5 explicit numbered page buttons in
the scroller (as expected), I see First, Last, <<, >>, << <<, >> >>,
everything enabled or disabled properly depending on currently selected
page.

That's just for my satisfaction, I haven't used Richfaces before and
wanted to try this out. However, I can see what your problem is: if you
are implementing naive data pagination, which you are, what makes you
think that rich:dataScroller has any idea that you've got more than 10
users total? It doesn't. I can easily confirm the same effect if I code
naive data pagination.

Some googling and some experimentation shows me that
org.ajax4jsf.model.SequenceDataModel<E> which extends
org.ajax4jsf.model.ExtendedDataModel<E> is a good way to go. You
probably won't have to override more than a few methods even for DB
access, it looks like walk() and getRowCount() are among the obvious
few. Your rich:dataTable (and hence the scroller) will simply see your
SequenceDataModel subclass, and it's that which will fake out the
scroller as to perceived row count and getting the correct rows.
[...]

Thanks for answer.
You are right that I have to extend some class. I was reading about
this, and it seems to be complicated. (I have to override a lot of
event).
In my oppinion it is faster to write my own paginator..

What do you think about writting own paginator ?
You have to write your own data pagination no matter what, whether own
solution from scratch or using the RichFaces components.

I probably read most of the same articles and forum threads you did,
because this is a common problem. I saw some of the commenters -
including some who should have known better - complain that the API for
hooking into one's data pagination implementation wasn't provided by the
RichFaces dataTable and dataScroller. That's not true, it's all there in
the SequenceDataModel and/or ExtendedDataModel.

How many methods you have to override depends entirely on how you do
your pagination. For example, my first cut at writing an implementation
based on SequenceDataModel is suitable for small to medium database
tables (one, or several that are joined), and relies on obtaining a list
of all relevant primary keys (PKs) when the data model is constructed.
The sequence of steps for building the final sub-classed
SequenceDataModel is something like

List<MyDataWrapper> wrappers
= <code to obtain all PKs and build list of wrappers>;
MyDataModel myDataModel =
new MyDataModel(new ListDataModel(wrappers));

where the relevant bits of MyDataModel are

public class MyDataModel
extends SequenceDataModel<MyDataWrapper> {

public MyDataModel(DataModel<MyDataWrapper> wrapped) {
super(wrapped);
}
....
}

and the wrapper class is something like

public class MyDataWrapper {

private Integer myDataId;
private MyData myData;

// ctors and accessors
}

Integer here is my PK class but could be different for your table(s).
MyData, as you may surmise, is the "real" data element.

In the above, myDataModel is what is presented to the rich:dataTable and
rich:dataScroller. The approach is simple because the UI sees a list of
the correct length. There is no extra coupling between presentation and
model because whether the JSF sees a MyData or a MyDataWrapper is
irrelevant; it still has to know about model details.

DATA PAGINATION IN THIS SIMPLE APPROACH:

When the list of wrappers is built all of the wrappers have null
references to the contained MyData's. Only the PKs (Integers in this
example) are initialized.

The only other RichFaces SequenceDataModel method I have to override in
this approach is walk(). My implementation is like this:

@Override
public void walk(FacesContext context, DataVisitor visitor,
Range range, Object argument) {

SequenceRange sr = (SequenceRange) range;

/* Use getWrappedModel(), sr.getFirstRow(),
* and sr.getRows() to access the data source,
* e.g. the DB, and load up the specified
* range of wrappers with the contained
* data elements.
* NOTE: don't confuse the JSF DataModel
* getWrappedModel() terminology with the
* data "wrappers" used in this implementation.
*/

super.walk(context, visitor, range, argument);
}

Where I have the comment block is where I call my repository class with
those 3 arguments, and it builds the SQL with an IN clause of the
correct range of PKs. The MyData references in the selected range of
wrappers are the initialized. That's all that the RichFaces UI
components need to see.

I happened to use JDBC for my experiment, but JPA with
setFirstResult()/setMaxResults() is also fine.

A side benefit of this simple approach is that with only a bit of extra
work you can have caching.

BUMPING IT UP A NOTCH

The obvious next step, and one you'd have to entertain if you have large
tables, is not to maintain any kind of full-length list at all, even a
lightweight one of wrappers. Here you will want to extend your data
model class from ExtendedDataModel, not SequenceDataModel.

This is where many of the decent available Internet articles on this,
e.g.
http://gochev.blogspot.com/2009/08/richfaces-server-side-paging-with.html,
come in. They tend to use SerializableDataModel, I'm sticking with
ExtendedDataModel, but the concepts are the same.

If you've worked through the exercise with the PK-list-based approach,
it's perhaps a bit easier to understand this next step up. Seeing it
presented in one fell swoop in an article can be a bit confusing,
though, because the authors hide a lot of trial and error and their own
initial confusion. There are also interesting points to be drawn
regarding how to work with implementing a superclass like this, that
some of the articles gloss over.

Here's how I go about thinking this through, and I'll refer to the cited
article above. I extend my new data model, let's call it
PagedMyDataDataModel, and at first glance I've got 10 methods I need to
implement.

1. The first obvious one is getRowCount(). It's easily understood that
you need this method, and why you need it now; the RichFaces UI
components no longer have a full-length list to look at.

This value supplied with a JDBC or JPA count on your table(s) with
appropriate WHERE conditions. Unless you expect things to change you can
cache this value, as is also suggested by some authors.

2. Some of the methods that you think you need to implement you really
don't. They show up as stubs because that's what Java requires. You can
look at a number of them, like getRowIndex(), and immediately figure out
that you don't have to implement them because you *cannot*.

Although it's been done for you by the other folks, as in the cited
article above, you can confirm for your own purposes with logging that
some of these overridden methods are never used, and can be ignored.

This is a useful lesson because you will run into similar situations
again in your Java career. Just because Java demands that you override a
bunch of methods doesn't mean you have to implement them all; it all
comes down to earlier design decisions by other folks as to what to
extend from, and what the actual clients are (like the RichFaces UI
components in this case).

3. Especially with comparison to what worked in my simple first
approach, the published implementation of the methods

getRowKey
setRowKey
walk
isRowAvailable
getRowData

plus getRowCount (discussed above) should make more sense now. What the
data model class is doing is maintaining exactly the same kind of
wrappers I did previously, but through the agency of a Map, with the map
keys being the PKs. As subsequent ranges of data are requested the map
slowly gets added to.

It should be common sense also why the above methods are now needed on
top of my very simple first approach. Because we now have a sparse
backing list, in effect (the map, thought of as a list), the front-end
needs our extra help to return the correct row.

4. walk() hasn't actually changed that much from my first
implementation. The main difference is simply to load the requested
range of data into a map rather than beefing up a sublist of wrappers.

5, With this approach you'll be returning data items directly, rather
than wrapper objects, so the JSF page EL will reflect that.

A NOTE ABOUT DB PAGINATION

When implementing the code in the walk() method that retrieves a range
of items from the DB, be a bit careful so as not to defeat the purpose.
A naive query followed by paging in the ResultSet (which you might get
even with JPA) means you're pulling back more than you wanted. So you
may want to ensure that you really are paging directly on the table (e.g
ROWNUM pagination with Oracle).

SUMMARY

I still wouldn't recommend writing it all yourself. There is a lot done
for you by the combination of rich:dataTable and rich:dataScroller. But
the data source pagination (whatever the data source is) you cannot
avoid implementing yourself.

AHS
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top