PDA

View Full Version : GXT 2.0 BeanModel objects always null



tim-mattison
13 Jul 2009, 8:20 AM
I am writing an application that uses Hibernate to persist my objects on the server. To translate them to the GWT client I use Gilead. I can send objects back and forth without issues but I think I'm missing something fundamental when it comes to loading these objects into a Grid or really any GXT component.

All BeanModels that I instantiate from my domain objects end up with every field being null. I have tried using the "extends BeanModelMarker" syntax with the @BEAN annotation as well as the BeanModelTag from here:

http://extjs.com/blog/2008/07/14/preview-java-bean-support-with-ext-gwt/

With no success. I get the same results from both builds. Thankfully, when I find a solution it doesn't really matter which one works since including GXT in the DAO layer isn't a big deal to me.

For example,

DomainObject d = new DomainObject();
d.setImportantField("test");

BeanModelFactory factory = BeanModelLookup.get().getFactory(DomainObject.class);

BeanModel b = factory.createModel(d);

At this point, d.importantField equals "test" but b.get("importantField") is null. In a grid I just get a bunch of blank lines.

I tried this as well,

BeanModel b = factory.createModel(new DomainObject());
DomainObject d = b.getBean();
d.setImportantField("test");

But I still get the same results. I used the boilerplate loader code from the BeanModelGridExample with still no luck. However, if I manually set the values like this:

b.set("importantField", "test");

Then I get some results and the grid renders that one field properly.

Is there a simple newbie mistake that I'm making here? The framework is tremendously useful if I can get objects from the server and automatically put them into a grid but currently I cannot do that without writing code to manually copy each field. I know it works in the examples so I have to assume that there's something very obvious that I'm lacking. I didn't see others having the same problem though. This post:

http://extjs.com/forum/showthread.php?t=50402&page=2

Seemed similar but the description of the issue didn't give me enough to go on to resolve my problem.

Any help would be greatly appreciated.

aurelie
27 Jul 2009, 1:10 AM
Hi,

I actually have the same problem.
Have you find a solution?

sven
27 Jul 2009, 1:52 AM
Take a look at the beanmodelgrid example

http://www.extjs.com/examples/explorer.html#beanmodelgrid

It is working fine there. Can you also post your bean etc?

aurelie
27 Jul 2009, 3:59 AM
I'm using the library Gilead to integrate Hibernate.
Here is my Bean :


public class DomaineIndicateurBean extends LightEntity
implements Serializable{
private static final long serialVersionUID = 1L;
private String code;
private String nom;
private String nomFR;


public DomaineIndicateurBean() {
super();
}

public String getDomaineIndicateurPK() {
return this.code;
}

public void setDomaineIndicateurPK(String pk) {
this.code = pk;
}

public String getCode() {
return this.code;
}

public void setCode(String code) {
this.code = code;
}

public String getNom() {
return this.nom;
}

public void setNom(String nom) {
this.nom = nom;
}

public String getNomFR() {
return this.nomFR;
}

public void setNomFR(String nomFR) {
this.nomFR = nomFR;
}

@Override
public String toString() {
boolean includeClassName = true;
return toString(includeClassName);
}

protected String toString(boolean includeClassName) {
StringBuffer str = new StringBuffer();

if (includeClassName) {
str.append("[DomaineIndicateur], ");
}

str.append("pk=" + getCode() + ", ");

str.append("code='" + getCode() + "', ");
str.append("nom='" + getNom() + "', ");
str.append("nomFR='" + getNomFR() + "', ");
if (includeClassName) {
str.append("[DomaineIndicateur]");
}
return (str.toString());
}

public String toXML() {
boolean includeRoot = true;
return toXML(includeRoot);
}

protected String toXML(boolean includeRoot) {
StringBuffer str = new StringBuffer();
if (includeRoot) {
str.append("<docDomaineIndicateur>");
}

str.append("pk=" + getCode() + ", ");

str.append("<code>" + getCode() + "</code>");
str.append("<nom>" + getNom() + "</nom>");
str.append("<nomFR>" + getNomFR() + "</nomFR>");
if (includeRoot) {
str.append("</docDomaineIndicateur>");
}
return (str.toString());
}

public void validateData() throws Exception {
//mandatory attributes
if (code == null) {
throw new Exception("the attribute : 'code' must not be null !");
}
}
}

aurelie
27 Jul 2009, 11:44 PM
I looked the example, i did the same things but i never found where is the problem.
I haven't error

tim-mattison
29 Jul 2009, 11:23 PM
I haven't had a chance to work on this for a while but I'll check against the examples you provided and see what I come up with. If anyone finds a solution who is having the same problem please let me know. As soon as I resolve it I'll also post some code that fixes this issue or at least the initialization steps that I was missing.

aurelie
30 Jul 2009, 8:12 AM
I have found the solution.
you must delete "extends light entity" in your bean class and it works.
i think that beans musn't extend some classes.

tim-mattison
30 Jul 2009, 11:08 PM
Ok, if that turns out to be the case (I hope it does) then users of Gilead cannot use stateless mode (http://noon.gilead.free.fr/gilead/index.php?page=stateless) and must use stateful mode (http://noon.gilead.free.fr/gilead/index.php?page=stateful-mode).

Does that fix the problem for anyone else? I will try to test it today.

aurelie
31 Jul 2009, 12:38 AM
What I don't understand is that I use the stateless mode!

eliasbalasis
31 Jul 2009, 4:41 PM
I used same technique with Gilead and Hibernate etc. based my example on the same BeanModelGrid example (http://extjs.com/examples/explorer.html#beanmodelgrid) but I have been able to successfully populate the grid only when used BaseModelData derived DTOs from server side.
Stateful Gilead mode did not work either.

Result is still the same, No rows in Grid :-(

eliasbalasis
31 Jul 2009, 5:30 PM
Tried to debug BeanModelReader source code during my RPC call.

I observed an exception being raised in "read" method at the point where a factory for enumerating bean properties is instantiated
Here is the exception

java.lang.RuntimeException: No BeanModelFactory found for class com.artifax.projects.mdahellas.membersdb.POJO.UserPOJO

(UserPOJO is class of objects returned from server)

the exception was caught/handled somewhere by RpcProxy implementation but was never thrown to GWT. so I couldhave so far seen it in GWT hosted mode browser's log window

please note that UserPOJO is a composite class, it is the root of a hierarchy of objects (groups, rights, roles etc.)
in this RPC call UserPOJO objects are not fully populated (lazy JPA loading), only UserPOJO part has values, composite parts are empty.

I hope this helps. any ideas?

eliasbalasis
31 Jul 2009, 5:57 PM
More observations:

called "BeanModelLookup.get().getFactory(UserPOJO.class);" to simulate behavior of BeanModelReader but returned null

BeanModelReader throws an exception in that case (mentioned in previous post) but RpcProxy consumes it silently

Moreover, BeanModelLookup.get().getFactory(any class); always returns null

I will try to check the source code of the actual factory implementation class

eliasbalasis
31 Jul 2009, 6:19 PM
I went through the BeanModelLookup generator class source code and found out that the actual implementing/generated class during GWT compilation becomes com.extjs.gxt.ui.client.data.BeanModelLookupImpl

its implementation parses all classes (using type oracle) for occurences derived/implementing either BeanModelMarker or BeanModelTag interfaces, generates a factory for each one and groups them all inside BeanModelLookupImpl

it looks like the reason that BeanModelLookup.get().getFactory(a class) was returning null is this. no class exists in my classpath derived from either BeanModelMarker or BeanModelTag interfaces

the funny thing is that the Customer class from BeanModelGrid example (http://extjs.com/examples/explorer.html#beanmodelgrid) is not derived from these interfaces. I wonder how this example works after all in samples Explorer.

finally, it looks like this will work with Gilead in either stateless or stateful mode. Gilead beans state mode seems to be unrelated.

eliasbalasis
31 Jul 2009, 6:32 PM
OK here it comes.

Customer class from example is using BeanModelMarker interface which requires/has an annotation @BEAN(com.extjs.gxt.samples.resources.client.model.Customer.class) specifying the generated class.

so beans that need to be processed by BeanModelReader and returned by RPC calls should either
1.
implement BeanModelMarker interface
and
@BEAN(generated.class)

or

2.
just implement BeanModelTag interface

eliasbalasis
31 Jul 2009, 7:29 PM
Final conclusions

only requirement is to implement BeanModelTag interface
(it is much simpler than BeanModelMarker)

Gilead works in stateless mode (no need for stateful)

Bean Model Generator produces implementation for complete class hierarchies
(very convenient)

aurelie
3 Aug 2009, 7:30 AM
I have a Bean class named "DomaineIndicateurBean" that implements BeanModelTag.
When I want to load instances of this bean in a grid like the BeanModelGrid, it works without implementing my bean with ILightEntity.
I have a second class named "IndicateurBean" that implements BeanModelTag too.
But when I want to load instances of this bean in a grid, in the server log appears the following exception :
"java.lang.RuntimeException: net.sf.gilead.exception.ProxyStoreException: Class class fr.IndicateurBean must implements ILightEntity interface"

Here is my first class (DomaineIndicateurBean) :


public class DomaineIndicateurBean implements Serializable, BeanModelTag{
private static final long serialVersionUID = 1L;
private String code;
private String nom;
private String nomFr;

public DomaineIndicateurBean() {
super();
}

public String getDomaineIndicateurPK() {
return this.code;
}

public void setDomaineIndicateurPK(String pk) {
this.code = pk;
}

public String getCode() {
return this.code;
}

public void setCode(String code) {
this.code = code;
}

public String getNom() {
return this.nom;
}

public void setNom(String nom) {
this.nom = nom;
}

public String getNomFr() {
return this.nomFr;
}

public void setNomFr(String nomFR) {
this.nomFr = nomFR;
}

@Override
public String toString() {
boolean includeClassName = true;
return toString(includeClassName);
}

protected String toString(boolean includeClassName) {
StringBuffer str = new StringBuffer();

if (includeClassName) {
str.append("[DomaineIndicateur], ");
}

str.append("pk=" + getCode() + ", ");

str.append("code='" + getCode() + "', ");
str.append("nom='" + getNom() + "', ");
str.append("nomFR='" + getNomFr() + "', ");
if (includeClassName) {
str.append("[DomaineIndicateur]");
}
return (str.toString());
}

public String toXML() {
boolean includeRoot = true;
return toXML(includeRoot);
}

protected String toXML(boolean includeRoot) {
StringBuffer str = new StringBuffer();
if (includeRoot) {
str.append("<docDomaineIndicateur>");
}

str.append("pk=" + getCode() + ", ");

str.append("<code>" + getCode() + "</code>");
str.append("<nom>" + getNom() + "</nom>");
str.append("<nomFR>" + getNomFr() + "</nomFR>");
if (includeRoot) {
str.append("</docDomaineIndicateur>");
}
return (str.toString());
}

public void validateData() throws Exception {
// mandatory attributes
if (code == null) {
throw new Exception("the attribute : 'code' must not be null !");
}
}
}
Here is my second class IndicateurBean


public class IndicateurBean implements Serializable {
private static final long serialVersionUID = 1L;
private String code;
private String description;
private Boolean estManuel;
private Boolean estSynthese;
private String nom;
private String nomFr;
private String roles;
private String type;
private Long valeurSeuil1ParDefaut;
private Long valeurSeuil2ParDefaut;
private DomaineIndicateurBean domaineIndicateur = null;
private boolean forceLoadDomaineIndicateur;

public IndicateurBean() {
super();
}

public DomaineIndicateurBean getDomaineIndicateur() {
return domaineIndicateur;
}

public void setDomaineIndicateur(DomaineIndicateurBean domaineIndicateur) {
this.domaineIndicateur = (DomaineIndicateurBean) domaineIndicateur;
}

public void addDomaineIndicateur(DomaineIndicateurBean c_domaineIndicateur) {
this.domaineIndicateur = (DomaineIndicateurBean) c_domaineIndicateur;
}

public void setForceLoadDomaineIndicateur(boolean force) {
this.forceLoadDomaineIndicateur = force;
}

public boolean getForceLoadDomaineIndicateur() {
return this.forceLoadDomaineIndicateur;
}

public String getIndicateurPK() {
return this.code;
}

public void setIndicateurPK(String pk) {
this.code = pk;
}

public String getCode() {
return this.code;
}

public void setCode(String code) {
this.code = code;
}

public String getDescription() {
return this.description;
}

public void setDescription(String description) {
this.description = description;
}

public Boolean getEstManuel() {
return this.estManuel;
}

public void setEstManuel(Boolean estManuel) {
this.estManuel = estManuel;
}

public Boolean getEstSynthese() {
return this.estSynthese;
}

public void setEstSynthese(Boolean estSynthese) {
this.estSynthese = estSynthese;
}

public String getNom() {
return this.nom;
}

public void setNom(String nom) {
this.nom = nom;
}

public String getNomFr() {
return this.nomFr;
}

public void setNomFr(String nomFR) {
this.nomFr = nomFR;
}

public String getRoles() {
return this.roles;
}

public void setRoles(String roles) {
this.roles = roles;
}

public String getType() {
return this.type;
}

public void setType(String type) {
this.type = type;
}

public Long getValeurSeuil1ParDefaut() {
return this.valeurSeuil1ParDefaut;
}

public void setValeurSeuil1ParDefaut(Long valeurSeuil1ParDefaut) {
this.valeurSeuil1ParDefaut = valeurSeuil1ParDefaut;
}

public Long getValeurSeuil2ParDefaut() {
return this.valeurSeuil2ParDefaut;
}

public void setValeurSeuil2ParDefaut(Long valeurSeuil2ParDefaut) {
this.valeurSeuil2ParDefaut = valeurSeuil2ParDefaut;
}

@Override
public String toString() {
boolean includeClassName = true;
return toString(includeClassName);
}

protected String toString(boolean includeClassName) {
StringBuffer str = new StringBuffer();

if (includeClassName) {
str.append("[IndicateurBean], ");
}

str.append("pk=" + getCode() + ", ");

str.append("code='" + getCode() + "', ");
str.append("description='" + getDescription() + "', ");
str.append("estManuel='" + getEstManuel() + "', ");
str.append("estSynthese='" + getEstSynthese() + "', ");
str.append("nom='" + getNom() + "', ");
str.append("nomFR='" + getNomFr() + "', ");
str.append("roles='" + getRoles() + "', ");
str.append("type='" + getType() + "', ");
str.append("valeurSeuil1ParDefaut='" + getValeurSeuil1ParDefaut() +
"', ");
str.append("valeurSeuil2ParDefaut='" + getValeurSeuil2ParDefaut() +
"', ");
if (includeClassName) {
str.append("[IndicateurBean]");
}
return (str.toString());
}

public String toXML() {
boolean includeRoot = true;
return toXML(includeRoot);
}

protected String toXML(boolean includeRoot) {
StringBuffer str = new StringBuffer();
if (includeRoot) {
str.append("<docIndicateur>");
}

str.append("pk=" + getCode() + ", ");

str.append("<code>" + getCode() + "</code>");
str.append("<description>" + getDescription() + "</description>");
str.append("<estManuel>" + getEstManuel() + "</estManuel>");
str.append("<estSynthese>" + getEstSynthese() + "</estSynthese>");
str.append("<nom>" + getNom() + "</nom>");
str.append("<nomFR>" + getNomFr() + "</nomFR>");
str.append("<roles>" + getRoles() + "</roles>");
str.append("<type>" + getType() + "</type>");
str.append("<valeurSeuil1ParDefaut>" + getValeurSeuil1ParDefaut() +
"</valeurSeuil1ParDefaut>");
str.append("<valeurSeuil2ParDefaut>" + getValeurSeuil2ParDefaut() +
"</valeurSeuil2ParDefaut>");
if (includeRoot) {
str.append("</docIndicateur>");
}
return (str.toString());
}

public void validateData() throws Exception {
//mandatory attributes
if (code == null) {
throw new Exception("the attribute : 'code' must not be null !");
}
if (estManuel == null) {
throw new Exception("the attribute : 'estManuel' must not be null !");
}
if (estSynthese == null) {
throw new Exception("the attribute : 'estSynthese' must not be null !");
}
if (roles == null) {
throw new Exception("the attribute : 'roles' must not be null !");
}
if (valeurSeuil1ParDefaut == null) {
throw new Exception("the attribute : 'valeurSeuil1ParDefaut' must not be null !");
}
if (valeurSeuil2ParDefaut == null) {
throw new Exception("the attribute : 'valeurSeuil2ParDefaut' must not be null !");
}
}
}


Why does this exception appears for this class but not for the first class?

Arno.Nyhm
6 Aug 2009, 1:36 AM
i think i can not help you many.

but i see some differences and possible issues in your classes:

double function:

public void setDomaineIndicateur(DomaineIndicateurBean domaineIndicateur) {
this.domaineIndicateur = (DomaineIndicateurBean) domaineIndicateur;
}

public void addDomaineIndicateur(DomaineIndicateurBean c_domaineIndicateur) {
this.domaineIndicateur = (DomaineIndicateurBean) c_domaineIndicateur;
}
missing BeanModelTag:


public class DomaineIndicateurBean implements Serializable, BeanModelTag{
public class IndicateurBean implements Serializable {