PDA

View Full Version : TreeGrid using BeanModel Doesn't Load



cri1258
18 Aug 2009, 4:33 PM
When using BeanModel and Java Beans, TreeGrid fails to load. A zip file with a zipped eclipse project is attached. To make the zip file small, I stripped out the following:

gxt.jar from lib/
gxt-all.css and gxt-gray.css from war/gxt/css/
all gxt images files from war/gxt/images/
gwt-servlet.jar from war/WEB-INF/lib

If you restore these and import the project into eclipse with gwt plugin installed, you can run the project to observe what to me seems like faulty behavior.

versions:
gwt 1.7, gxt 2.0.1, eclipse galileo

for reference, my EntryPoint class is:


package com.centurylink.testgwtgxt.client;

import java.util.Arrays;
import java.util.List;

import com.centurylink.testgwtgxt.client.domain.Person;
import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.data.BaseTreeLoader;
import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.data.BeanModelReader;
import com.extjs.gxt.ui.client.data.ListLoadResult;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.data.TreeLoader;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.store.Store;
import com.extjs.gxt.ui.client.store.StoreSorter;
import com.extjs.gxt.ui.client.store.TreeStore;
import com.extjs.gxt.ui.client.util.IconHelper;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.Viewport;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnData;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.layout.FlowLayout;
import com.extjs.gxt.ui.client.widget.layout.RowLayout;
import com.extjs.gxt.ui.client.widget.treegrid.TreeGrid;
import com.extjs.gxt.ui.client.widget.treegrid.TreeGridCellRenderer;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.RootPanel;

public class TestGwtGxt implements EntryPoint {

private final PersonServiceAsync personService = GWT.create(PersonService.class);

public void onModuleLoad() {

Viewport viewport = new Viewport();
viewport.setLayout(new RowLayout());
AsyncTreeGridExample gridExample = new AsyncTreeGridExample();
viewport.add(gridExample);
RootPanel.get().add(viewport);
}

class AsyncTreeGridExample extends LayoutContainer {

@Override
protected void onRender(Element parent, int index) {
super.onRender(parent, index);

setLayout(new FlowLayout(10));

RpcProxy<List<Person>> proxy = new RpcProxy<List<Person>>() {
@Override
protected void load(Object loadConfig,
AsyncCallback<List<Person>> callback) {
personService.getChildren((Person) loadConfig, callback);
}
};

BeanModelReader reader = new BeanModelReader();

// tree loader
final TreeLoader<BeanModel> loader = new BaseTreeLoader<BeanModel>(proxy,reader) {
@Override
public boolean hasChildren(BeanModel parent) {
return true;
}
};

// trees store
final TreeStore<BeanModel> store = new TreeStore<BeanModel>(loader);
store.setStoreSorter(new StoreSorter<BeanModel>() {

@Override
public int compare(Store<BeanModel> store, BeanModel m1,
BeanModel m2, String property) {
return 1;
}
});

loader.load(null);

ColumnConfig name = new ColumnConfig("name", "Name", 100);
TreeGridCellRenderer<BeanModel> renderer = new TreeGridCellRenderer<BeanModel>() {

@Override
public Object render(BeanModel model, String property,
ColumnData config, int rowIndex, int colIndex,
ListStore<BeanModel> store, Grid<BeanModel> grid) {
return super.render(model, property, config, rowIndex, colIndex, store, grid);
}

};
name.setRenderer(renderer);

ColumnModel cm = new ColumnModel(Arrays.asList(name));

ContentPanel cp = new ContentPanel();
cp.setBodyBorder(false);
cp.setHeading("Async TreeGrid");
cp.setButtonAlign(HorizontalAlignment.CENTER);
cp.setLayout(new FitLayout());
cp.setFrame(true);
cp.setSize(600, 300);

TreeGrid<BeanModel> tree = new TreeGrid<BeanModel>(store, cm);
tree.setBorders(true);
tree.getStyle().setLeafIcon(IconHelper.createStyle("icon-page"));
tree.setSize(400, 400);
tree.setAutoExpandColumn("name");
tree.setTrackMouseOver(false);
cp.add(tree);

add(cp);
}

}
}

t3q
19 Aug 2009, 12:48 AM
Any solution on this topic ? I have the same problem with loading BeanModel in TreeGrid.

sven
19 Aug 2009, 12:50 AM
This thread is better places in the help forum. There is an AsyncTreeGrid example which works without problems.

cri1258
19 Aug 2009, 5:57 AM
I looked in the help forum first. I found no help there. There was a guy reporting a similar problem, but there was no solution ever posted. In the examples there is a working async TreeGrid example, but it doesn't use the BeanModel/Java Bean design. It uses FileModel which extends BaseModelData. Plus, you see that someone replied to this thread saying that they have the same problem. Seems like there is a bug to me.

sven
19 Aug 2009, 6:10 AM
Have you debugged your own code? It is thworing an exception: com.extjs.gxt.ui.client.data.BaseListLoadResult cannot be cast to java.util.List

cri1258
19 Aug 2009, 7:44 AM
Sigh. Lord knows I've tried. You are probably much better at this than me. Maybe I'll learn something here. Been at it over 16 hours now. Plus another of our guys spent about a half day. I can't figure out where you are seeing that exception. I've tried putting a catch/try around various methods, but I'm not seeing any exceptions thrown. Plus, nothing shows up in the GWT hosted mode console window. I'll keep digging. Thanks -Chuck

sven
19 Aug 2009, 7:54 AM
You need to return a BaseListLoadResult from your service

cri1258
20 Aug 2009, 11:24 AM
I finally got my code working using the work around approach at http://extjs.com/forum/showthread.php?t=74514&highlight=TreeGrid+BeanModel. This approach doesn't use a BeanModelReader. Instead, it does the necessary conversion with a BeanModelFactory. I tried Sven's suggestion of using BaseListLoadResult, but ran into other problems. I may go back later and try to use a BeanModelReader and BaseListLoadResult since I think that this is really the correct approach.

fvisticot
5 Oct 2009, 3:59 AM
You need to return a BaseListLoadResult from your service

Can you please elaborate your explanation. I try to use the BeanModelReader with trees from 1 week but it does not work for me with the BeanModelReader.
Can you please provide a sample code ?


The post with sample code:
http://www.extjs.com/forum/showthread.php?t=81543&highlight=BeanModelReader

cri1258
5 Oct 2009, 7:31 AM
The best code example is at http://extjs.com/forum/showthread.ph...Grid+BeanModel (http://extjs.com/forum/showthread.php?t=74514&highlight=TreeGrid+BeanModel). This is the one that I used, though I have the impression that it isn't the "right" or intended approach. My suspicion is that the intended mechanism may be broke since no one seems successful in using it. It would be great is a TreeGrid example using BeanModel population were added to the examples.

fvisticot
5 Oct 2009, 7:56 AM
Agree with you !!!
The working sample DOES NOT USE the BeanModelReader (factory is used manualy in the load method)

ExtJS team, Can you please help us with a sample code using BeanModel and BeanModelReader ???? :((

fvisticot
12 Oct 2009, 1:25 PM
I really need a sample code with TreeGrid + BeanModel + BeanModelReader...
:-?

razorman8669
23 Nov 2009, 8:08 AM
+1 agree there should be a working tree + beanmodel example...The only way to get it working is to use the beanModelFactory and manually convert my List<PageDTO> into a List<BeanModel>:



RpcProxy<List<BeanModel>> proxy = new RpcProxy<List<BeanModel>>() {
protected void load(final Object loadConfig, final AsyncCallback<List<BeanModel>> callback) {
PageDTO model = loadConfig == null ? null : (PageDTO)((BeanModel)loadConfig).getBean();

service.getChildren(model, new AsyncCallback<List<PageDTO>>() {
public void onFailure(Throwable caught) {
callback.onFailure(caught);
}

public void onSuccess(List<PageDTO> result) {
// FIXME: use a beanModelReader instead of manually converting here.
BeanModelFactory factory = BeanModelLookup.get().getFactory(PageDTO.class);

List<BeanModel> list = new ArrayList<BeanModel>();

for (PageDTO page : result) {
list.add(factory.createModel(page));
}

callback.onSuccess(list);
}
});
}
};

// create tree loader and store
TreeLoader<BeanModel> loader = new BaseTreeLoader<BeanModel>(proxy);

TreeStore<BeanModel> store = new TreeStore<BeanModel>(loader);

TreePanel tree = new TreePanel<BeanModel>(store));



What I WANT to do is something like so:



// data proxy for loading the next set of children for the expanded wikipage parent.
RpcProxy<List<PageDTO>> proxy = new RpcProxy<List<PageDTO>>() {
@Override
protected void load(Object loadConfig, AsyncCallback<List<PageDTO>> callback) {
service.getChildren((PageDTO) loadConfig, callback);
}
};

// create tree loader and store
BeanModelReader reader = new BeanModelReader();
TreeLoader<BeanModel> loader = new BaseTreeLoader<BeanModel>(proxy, reader);



But I get errors and it doesnt work this way...

fvisticot
23 Nov 2009, 11:37 AM
Ext JS team, please answer to this post. A sample code would be very usefull for everybody !!!:((

getaceres
11 Dec 2009, 4:05 AM
I think it has to do with the loadConfig object.

I have the following code:



RpcProxy<List<Customer>> proxy = new RpcProxy<List<Customer>>() {

@Override
protected void load(Object loadConfig, AsyncCallback<List<Customer>> callback) {
if (loadConfig == null) {
patSvc.getCustomers(callback);
} else {
if ((Boolean)loadConfig) {
patSvc.getAssociated(callback);
} else {
patSvc.getUnassociated(callback);
}
}
}
};

final ListLoader<ListLoadResult<ModelData>> loader = new BaseListLoader<ListLoadResult<ModelData>>(proxy, new BeanModelReader());
ls = new ListStore<BeanModel>(loader );
..............................................................
Grid<BeanModel> grid = new Grid<BeanModel>(ls, cm);


If I call loader.load(null) I get my grid populated. If I call loader.load(true) or loader.load(false) the grid never renders the data. It shows the Loading message continuously.
I looked at firebug and I saw that getCustomers and getAssociated returns exactly the same data, but getCustomers works while getAssociated keeps the grid waiting forever, even if the RPC has returned the data.

Also I tried this simple change:



if (loadConfig == null) {
patSvc.getAssociated(callback);
} else {
if ((Boolean)loadConfig) {
patSvc.getCustomers(callback);
} else {
patSvc.getUnassociated(callback);
}
}


And in this case, getAssociated prints data in the grid, while getCusomers, that previously was printing data, gets stuck with the loading screen. With this test, I think that it has something to do with the loadConfig object. Maybe I'm using it in the wrong way?

pgraham
18 Feb 2010, 9:29 AM
You need to return a BaseListLoadResult from your service


This is not right. The problem is that the BeanModelReader implements DataReader<ListLoadResult<ModelData>>. However, a TreeLoader needs a DataReader<List<ModelData>> implementation to work correctly since it passes the result of DataReader#read(...) to BaseTreeLoader#onLoadSuccess(Object loadConfig, List<M> result). It doesn't matter what your service returns as it will always result in a ListLoadResult object getting passed to a method that expects a List.

I've been able to work around this problem is by creating my own implementation of DataReader for use with TreeLoaders that wraps a BeanModelReader:



public class TreeGridBeanModelReader implements DataReader<List<ModelData>> {

private BeanModelReader reader = new BeanModelReader();

public boolean isFactoryForEachBean() {
return reader.isFactoryForEachBean();
}

public List<ModelData> read(Object loadConfig, Object data) {
ListLoadResult<ModelData> models = reader.read(loadConfig, data);
return models.getData();
}

public void setFactoryForEachBean(boolean factoryForEachBean) {
reader.setFactoryForEachBean(factoryForEachBean);
}
}
Now when I create a tree store I use TreeGridBeanModelReader instead of BeanModelReader:



RpcProxy<?/* Either List<?> or ListLoadResult<?>*/> proxy = new RpcProxy<?>() {
@Override
protected void load(Object loadConfig, AsyncCallback<?> callback) {
// ...
}
};
TreeLoader<BeanModel> loader = new BaseTreeLoader<BeanModel>(proxy, new TreeGridBeanModelReader()) {
@Override
public boolean hasChildren(BeanModel parent) {
// ...
}
};

TreeStore<BeanModel> store = new TreeStore<BeanModel>(loader);
TreeGrid<BeanModel> grid = new TreeGrid(store, createColumnModel());

T
23 Feb 2010, 10:04 AM
@pgraham: (http://www.extjs.com/forum/member.php?u=86381)
Thank you, it's works for me :)
(http://www.extjs.com/forum/member.php?u=86381)