vendredi 18 janvier 2008

Seam + ExtJS, Store, Reader, Proxy

Passons maintenant à la pratique. Je commencerai pas exposer les différentes classes côté ExtJS qui permettent de dialoguer avec Seam Remoting. Pour cela, je suis parti de l'exemple d'extension pour DWR proposé par Axel ici : http://extjs.com/forum/showthread.php?t=19529

Now it's time for some code examples. I'm begining to expose the different ExtJS extensions classes which permit to dialog with Seam Remoting. For this purpose, I started with the example extension for DWR proposed by Axel in the ExtJS User Extensions forum : http://extjs.com/forum/showthread.php?t=19529


/**
* Seam remoting proxy.
*
* Can be bound to any WebMethod which signature is like :
* - ResultList<T> webMethod(QueryParam param) for a non paging method.
* - PagingResultList<T> webMethod(PagingQueryParam param) for a paging method.
*
* @param {function} f Points to remote function.
* @param {Object} o Seam component.
* @param {boolean} paging Tells wether the remote method uses paging.
*/

Ext.data.SeamRemotingProxy = function(f, o, paging)
{
Ext.data.SeamRemotingProxy.superclass.constructor.call(this);
this.func = f;
this.instance = o;
this.paging = paging;
};

Ext.extend(Ext.data.SeamRemotingProxy, Ext.data.DataProxy,
{
/**
* Builds a query parameter object (queryParam or pagingQueryParam
* if paging is used by the remote method).
*
* Calls the seam remote method by passing to it the query parameter
* objet and the callback function.
*
* @param {Object} params Object with following fields defined : queryString,
* and if paging enabled, with following more fields : start, limit.
* @param {Object} reader
* @param {Object} loadCallback
* @param {Object} scope
* @param {Object} arg
* @param {Object} remoteArgs
*/

load: function(params, reader, loadCallback, scope, arg, remoteArgs)
{
var dataProxy = this;
dataProxy.fireEvent("beforeload", dataProxy, params);

var args = [];

// Wether the remote method method support paging or not,
// choose the right parameter class.
var queryParamComponentName;
if (this.paging)
{
queryParamComponentName = "pagingQueryParam";
}
else
{
queryParamComponentName = "queryParam";
}

var queryParam = Seam.Component.newInstance(queryParamComponentName);

//
for (var param in params)
{
queryParam[param] = params[param];
}

args[args.length] = queryParam;

args[args.length] = function(response)
{
dataProxy.fireEvent("load", dataProxy, response, loadCallback);
var records = reader.read(response);

if (records.records.length > 0)
{
scope.fields = records.records[0].fields;
}

loadCallback.call(scope, records, arg, true);
}

this.func.apply(this.instance, args);
}
});

/**
* Extension of Ext.data.Record to handle bean data.
* Extends record.get(name) in order to be able to access
* properties of underlying objects like bean.child.property.
*
* @param {Object} data
* @param {Object} id
*/

Ext.data.BeanRecord = function(data, id)
{
Ext.data.BeanRecord.superclass.constructor.call(this, data, id);
};

Ext.extend(Ext.data.BeanRecord, Ext.data.Record, {});

Ext.data.BeanRecord.create = function(o)
{
var f = Ext.data.Record.create.call(this, o);

/**
*
* @param {String} name
*/

f.prototype.get = function(name)
{
var names = name.split('.', 2);

if (names.length > 1)
{
var o = this.data[names[0]];

if (o)
{
var result = eval("o." + names[1]);
return result;
}
else
{
return "";
}
}
else
{
return this.data[name];
}
}

/**
* Copies a record and its underlying seam data bean.
* @param {String} componentName The seam component name of the underlying bean.
*/

f.prototype.copyRecord = function(componentName)
{
var copieRecord = this.copy();
var copieData = copyBean(this.data, componentName);
copieRecord.data = copieData;

return copieRecord;
}

return f;
};


/**
* Extends Ext.data.DataReader in order to read bean data.
*/

Ext.data.BeanReader = function()
{
Ext.data.BeanReader.superclass.constructor.call(this, null, []);
};

Ext.extend(Ext.data.BeanReader, Ext.data.DataReader,
{
read: function(response)
{

var records = [];
var bean;

for (var i = 0; i < response.list.length; i++)
{
bean = response.list[i];

// retreives the bean field names
var fields = [];
for (var prop in bean)
{
if ((new String(bean[prop])).substring(0, 8) != "function")
{
fields[fields.length] = prop;
}
}

// builds dynamically the record definition
var recordDefinition = "[";

var field;
for (var j = 0; j < fields.length; j++)
{
field = fields[j];
recordDefinition = recordDefinition + "{name: '" + field + "'}";
if (j < fields.length - 1)
{
recordDefinition = recordDefinition + ",";
}
}
recordDefinition = recordDefinition + "]";

var ObjectRecord = eval("Ext.data.BeanRecord.create(" + recordDefinition + ")");

// record instantiation
var myNewRecord = new ObjectRecord();

// record data is the bean
myNewRecord.data = bean;

records[records.length] = myNewRecord;
}
return {
records: records,
totalRecords: response.totalRecords
};
}
});

/**
* [en]
* Added configuration parameters :
* - remoteComponent (Object) : Seam component resulting from a call to
* Seam.Component.getInstance(name)
* - remoteComponentName (String) : Seam component name to remote-access.
* This parameter is non used if remoteComponent is defined.
* - remoteMethodName (String) : Web remote method name (annotated @WebRemote)
* - paging (bool) - optional (false by default) : tells wether the remote method uses paging.
*
* Use example :
*
* var store = new Ext.data.SeamRemotingStore(
* {
* remoteComponent: customerWebAction,
* remoteMethodName: "listAllCustomersWithPaging",
* paging: true,
* sortInfo:
* {
* field: 'nom',
* direction: "ASC"
* },
* groupField: 'customerType'
* });
*
* store.load(
* {
* params:
* {
* queryString: '',
* start: 0,
* limit: 15
* }
* });
*
* [fr]
* Paramètre de configurations supplémentaires :
* - remoteComponent (object) : Composant seam obtenu par un appel à Seam.Component.getInstance(name)
* - remoteComponentName (String) : nom du composant Seam à consulter (paramètre non pris en compte si le précédent est défini)
* - remoteMethodName (String) : nom de la méthode remote (marquée @WebRemote)
* - paging (bool) - optionnel (false par défaut) : la méthode remote supporte la pagination
*
* @param {Config} c
*/

Ext.data.SeamRemotingStore = function(c)
{
// configuration
var seamComponent = c.remoteComponent;

if (!c.remoteComponent)
{
var remoteComponentName = c.remoteComponentName;
seamComponent = Seam.Component.getInstance(remoteComponentName);
}

var remoteMethodName = c.remoteMethodName;

var paging;
if (c.paging)
{
paging = c.paging;
}
else
{
paging = false;
}

var remoteMethod = eval("seamComponent." + remoteMethodName);

// instantiale a proxy and a reader
this.proxy = new Ext.data.SeamRemotingProxy(remoteMethod, seamComponent, paging);
this.reader = new Ext.data.BeanReader();

// record currently selected
this.currentRecord = null;

this.getCurrentRecord = function()
{
return this.currentRecord;
}

this.setCurrentRecord = function(record)
{
this.currentRecord = record;
}

Ext.data.SeamRemotingStore.superclass.constructor.call(this, c);
};
Ext.extend(Ext.data.SeamRemotingStore, Ext.data.GroupingStore);

/**
* Utility method to create a copy of a bean knowing it's seam
* component name.
*
* @param {Object} bean The bean to be copied
* @param {String} beanName Seam component name
*/

function copyBean(bean, beanName)
{
var newBean = Seam.Component.newInstance(beanName);

for (var prop in bean)
{
if ((new String(bean[prop])).substring(0, 8) != "function")
{
newBean[prop] = bean[prop];
}
}

return newBean;
}


5 commentaires:

Osman İzbat a dit…

Hi,

I'm trying to use SeamRemotingStore with GridPanel but this code doesn't work:

Ext.onReady(function(){

var store = new Ext.data.SeamRemotingStore(
{
remoteComponentName: 'dummySearch',
remoteMethodName: "getBrands"
});
store.load();

var grid = new Ext.grid.GridPanel({
store: store,
columns: [
{id:'brandId',header: "Brand", width: 160, sortable: true, dataIndex: 'brandId'},
{header: "brandName", width: 75, sortable: true, dataIndex: 'brandName'}
],
stripeRows: true,
height:350,
width:600

});

grid.render('topic-grid');

});


Could you please give a simple example.

Regards.

Osman İzbat a dit…

Hi again.

I've finally solve my problem.
I've created pagingQueryParam and queryParam seam components:


................

@Name("queryParam")
public class QueryParam {
private String queryString;
...
}

@Name("pagingQueryParam")
public class PagingQueryParam extends QueryParam {
private Integer start;
private Integer limit;
...
}
...............


I'm calling to below methods:

public List getBrands(QueryParam param) {
return entityManager.createQuery(
"select brand from Brand brand " + param.getQueryString()).setMaxResults(
).getResultList();
}

public List getBrandsAsPaginated(PagingQueryParam param) {
return entityManager.createQuery(
"select brand from Brand brand " + param.getQueryString()).setMaxResults(
param.getLimit()).setFirstResult(param.getStart()).getResultList();
}

from following code:

Ext.onReady(function(){
var store = new Ext.data.SeamRemotingStore({
remoteComponentName: 'dummySearch',
remoteMethodName: "getBrandsAsPaginated",
paging: true
});

store.load({
params: {
queryString: "",
start: 0,
limit: 15
}
});

var grid = new Ext.grid.GridPanel({
store: store,
columns: [
{id:'brandId',header: "Brand", width: 160, sortable: true, dataIndex: 'brandId'},
{header: "brandName", width: 75, sortable: true, dataIndex: 'brandName'}
],
stripeRows: true,
height:350,
width:600,
tbar: new Ext.PagingToolbar({
pageSize: 15,
store: store
})

});

grid.render('brand-grid');

});


But doesn't it needed to set totalProperty of BeanReader for true pagination ?
By the way what are the ResultList, PagingResultList classes ?


Regards.

Osman İzbat a dit…

Hi,

I've figure out the PagingResultList class and my sample works.

Thank you very much.


public class PagingResultList {

private List list;
private Integer totalRecords;
.....
}

public PagingResultList getBrandsAsPaginated(PagingQueryParam param) {
........

}

CVX a dit…

Hi,

Sorry for not having answered, I was in hollidays :)

I'm going to add an article for the java needed java classes !

Unknown a dit…

This worked perfect for me. Thank you so much. Could you help me in invoking and maintaining seam conversation between page navigations.