(Perhaps tihis should be in the design patterns forum, but I think it's appropriate here as well).
For a while we have struggled with the design pattern for basic list processing (paging back and forth through data, potentially thousands of records) using CMP. Normally we only display e.g. 20 records. The aim is of course to be portable across app servers.
The way that the Collection works which is returned from finder methods when using JBoss is really good, if I understand it right. It is acting as a dynamic facade to the ResultSet. So, I execute a finder method, and a Collection is returned to me, but all the elements haven't been filled in. Depending on tuning parameters, maybe only a few of the elements have been filled in.
However, if I ask for the size() of the collection, it returns the correct result, i.e. the total number of records in the result set, which I guess is being done by consulting the result set at the back end.
Great. So what I would want to do now, for really easy paging functionality is just record as hidden values on my form the start and end index of what I read from the collection. To page forward, I run the finder again, and just retrieve from lastIndex+1 up to lastIndex+pageSize.
But of course, the Collection interface doesn't support that. If it was a java.util.List, I could retrieve a subList of the required elements.
(of course there are some issues there - if records had been inserted in the meantime, my index positions would not be accurate, but I'm prepared to live with that).
Without this ability, I have to resort to the following:
- store first and last indexes of things I am ordering by as hidden values on the form
- use two finders (one for paging forwards, and one for paging backwards) that must use JBossQL extensions, specifically the use of > or < on a String value (ANGER - I ABSOLUTELY CANNOT BELIEVE THAT THE EJB-QL SPEC DOESN'T ALLOW THAT!).
I want to be portable. Allowing java.util.List as the return type of a finder method would allow that, I believe (would force all vendors to support the subList).
What does everyone think? Am I missing the point here? Should I be approaching the whole topic differently?
Or would this be a valuable change to the spec?
I should have said - I realise that I can use the OFFSET extensions within JBossQL, but I have to be portable, at least across JBoss and Oracle 9i.
Well I'll carry on my own conversation for my own benefit :-)
I was of course talking rubbish about how the collection works. It's reporting the real number of elements, and all records were being read.
So the only way I have to limit the number of records is to use OFFSET and LIMIT.
I can't use this, because it's totally specific to JBoss, and makes even the signature of the methods specific.
Im not sure if im making any sense here, but if u can tune the maximum number of beans in cache, cant u make the equivalent of loading 100 beans first(the default maximum number of beans is 100 ). I will check in the JBoss code to see what happens if there is an attempt to load more than the maximum number of beans? if it throws some sort of an exception(like a CacheFull Exception), we can probably catch that and make decisions accordingly. Even in that case, for the next page, you have to store the starting record number for that page and do another load.
I see what you are getting at.
But when I run the finder, if I understand it right, it will still load _all_ of the primary keys from the database.
That is the part which could take a very long time.
According to the docs, the maximum size is not a REAL maximum size and the number gets expanded if there are more concurrent requests. There is another parameter called strictMaximumSize that can be used to limit the maximum size and a strictTimeout to wait if all the beans are filled and another request is waiting for a free bean. If the strictTimeout is 0 (or negative) it throws a java.rmi.ServerException. Perhaps you can catch this excpetion, have a counter that indicates the number of beans in memory and do your analysis based on this.
There should definitely be a easier way,maybe some of the Jboss developers can shed some light!!