Pageable Row Set???
18/09/08 04:14 Filed in: Adobe flex
So my coworker Justin has been telling me
that I should be writing a blog about some of
the stuff I’ve been working on with Flex and
Java. So here’s my start....
I’ve been working with decently large datasets, about 10k to 20k rows of data. The data has many attributes, so the size of it is quite large, 10M or so.
Of course I started with a nice gzip on the server, so that compressed the data down which increases the download of the dataset, but of course this is a stop gap measure because as the size of the data grows the difficulty of dealing with it grows.
I’ve looked at java side RowSet and using BlazeDS PageableRowSetCache, with a homegrown actionscript paged array collection.
I didn’t find much information to do this, so I thought I would write up what I did.
First, I did the basic java remote method.
With this row set we can now call the PageableRowSetCache.cacheRowSet.
We now pass the PageableRowSet back to the Flex side. The nice thing is that the PageableRowSet gets converted into an mx.util.ObjectProxy that has the following properties that I use.
The initialData holds the first page of data and you should use the length to identify the pageSize to fetch.
The totalCount holds the complete row count of the SQL STATEMENT that was excecuted.
The serviceName holds the destination name for requesting pending data. It has a default value of PageableRowSetCache, you have to setup the JavaAdapter in the remoting-config.xml file i.e.
The flex.messaging.services.remoting.PageableRowSetCache has a method called
So at this point we’ve set up everything without writing much Flex code. So now comes the bigger piece of it.
A few things to remember about this are
The one thing I really like about this implementation is how it allows the ArrayCollection to deal with keeping the data and this class to deal with acquiring the pending data, as well as being able to replace an ArrayCollection with a PageableCollection.
I’ve been working with decently large datasets, about 10k to 20k rows of data. The data has many attributes, so the size of it is quite large, 10M or so.
Of course I started with a nice gzip on the server, so that compressed the data down which increases the download of the dataset, but of course this is a stop gap measure because as the size of the data grows the difficulty of dealing with it grows.
I’ve looked at java side RowSet and using BlazeDS PageableRowSetCache, with a homegrown actionscript paged array collection.
I didn’t find much information to do this, so I thought I would write up what I did.
First, I did the basic java remote method.
RowSet rowSet =
new
WebRowSetImpl();
rowSet.setReadOnly(true);
rowSet.setDataSourceName("java:comp/env/jdbc/DATASOURCE_CONNECTION");
rowSet.setCommand("SQL
STATEMENT");
rowSet.execute();
With this row set we can now call the PageableRowSetCache.cacheRowSet.
PageableRowSet pRowSet = PageableRowSetCache.cacheRowSet(rowSet, 15);
We now pass the PageableRowSet back to the Flex side. The nice thing is that the PageableRowSet gets converted into an mx.util.ObjectProxy that has the following properties that I use.
serverInfo:Object which contains
id:String // unique
totalCount:int
initialData:Array
serviceName:String
The initialData holds the first page of data and you should use the length to identify the pageSize to fetch.
The totalCount holds the complete row count of the SQL STATEMENT that was excecuted.
The serviceName holds the destination name for requesting pending data. It has a default value of PageableRowSetCache, you have to setup the JavaAdapter in the remoting-config.xml file i.e.
<destination id="PageableRowSetCache">
<properties>
<scope>application</scope>
<source>flex.messaging.services.remoting.PageableRowSetCache</source>
</properties>
</destination>
The flex.messaging.services.remoting.PageableRowSetCache has a method called
00001: getRecords(id:String, start:int,
numOfRecords:int) which is used
to retrieve other data from the Row Set. The id is
the unique id in the serverInfo object.
So at this point we’ve set up everything without writing much Flex code. So now comes the bigger piece of it.
public
class PageableCollection extends ArrayCollection {
public static var
pendingObject:Object
= "Pending";
protected var
pagedFetched:Object
= new Object();
protected var
pagedObject:Object;
protected var
pageService:RemoteObject;
protected var
pageSize:Number;
public function
PageableCollection(obj:Object) {
pagedObject
= obj;
var
array:Array = new Array(pagedObject.totalCount + 1);
var
i:int;
for
(i = 0; i
<
pagedObject.initialData.length; i++)
{
array[i]
= (convert(pagedObject.initialData[i] as
Array));
}
pageSize
= i;
for
(; i < pagedObject.totalCount; i++)
{
array[i]
=
pendingObject;
}
super(array);
pageService
= new
RemoteObject(pagedObject.serviceName);
pageService.addEventListener(ResultEvent.RESULT,
handleResult,
false, 1, true);
}
override public function get
length():int {
return
pagedObject.totalCount
+ 1;
}
override public function
getItemAt(index:int,
prefetch:int
= 0):Object {
var
obj:Object = super.getItemAt(index,
prefetch);
if
(obj != pendingObject) {
return
obj;
}
var
page:int = Math.floor(index / pageSize);
if
(pagedFetched[page]
!= null) {
return
obj;
}
pagedFetched[page]
= true;
var
token:Object
=
pageService.getRecords(pagedObject.id,
page *
pageSize,
pageSize);
token.index
= page * pageSize;
return
obj;
}
protected function
handleResult(event:ResultEvent):void {
for
(var i:int =
0; i < event.result.Page.length; i++)
{
this.setItemAt(convert(event.result.Page[i]),
i + event.token.index);
}
}
public
var convert:Function = function(a:Object):Object{
return
a;
};
}
}
A few things to remember about this are
- You need a java sticky session on the server side.
- Sorting and filtering can be problematic, (I’m hoping to have a post to address this issue)
- You need to manage the PageableRowSetCache, such as releasing it when you’re done
The one thing I really like about this implementation is how it allows the ArrayCollection to deal with keeping the data and this class to deal with acquiring the pending data, as well as being able to replace an ArrayCollection with a PageableCollection.