GWT 1.5 , Hibernate - A way to create serialized pojos

84 views
Skip to first unread message
Message has been deleted

Raghunath

unread,
Mar 8, 2008, 2:48:02 PM3/8/08
to Google Web Toolkit
Hi ALL,
I started working on GWT 1.5. GWT generics are great. Now it wont
throw errors for annotations.
I created on utility function to get serialized pojos from hibernated
beans which are written based on ejb 3.0 annotations.

How it works:
---------------
It will clone full hibernate proxy object to a bean pojo (relation
ships also). And the pojo is of type hibernate bean. It will copy the
relationships recursively based on depth.


Advantages:
--------------
1)No need to create any dtos
2)No need of hibernate4gwt (I never used it, but I read few blogs)
3)It will support hibernate object tree (means in client side i can
get the tree)
4)for LazyInitialization it will fill the lazy objects with null.
5) No need of 3rd party libs

Disadvantages:
------------------------
1) pojos from Client to Servce ,service to hibernate session not yet
done.

How to Use :
-------------------
1) create your hibernate bean class with only default constructor no
parametrized constructor.
2) All fields of type public .(If u want private ,you can modify this
method slitly)
3) All hibernate beans should be of type IsSerializable
4) The bean class can contain ejb 3.0 annotations, Generics
5) no field should be primitives. (you can use Long in place of long ,
jdk 1.5 will take care of autoboxing thisng..


Util Function:
==================

public static Object toPOJO(Object fromObj,int depth){

Class c=fromObj.getClass();
Object to=null;

System.out.println("POJOConverter.toPOJO"+c);
String className=null;
if(c.getSimpleName().indexOf('$')>0)
className=c.getName().substring(0,c.getName().indexOf('$'));
else
className=c.getName();
try {
System.out.println("POJOConverter.toPOJO"+className);
to=Class.forName(className).newInstance();

} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Field fields[]=to.getClass().getDeclaredFields();

for (int i = 0; i < fields.length; i++) {
String
fieldName=Character.toUpperCase(fields[i].getName().charAt(0))
+fields[i].getName().substring(1);

try {

Field fromField=fromObj.getClass().getField(fields[i].getName());

if(Modifier.isStatic(fromField.getModifiers())||
Modifier.isFinal(fromField.getModifiers())||
Modifier.isPrivate((fromField.getModifiers())))
continue;
Object
n=fromObj.getClass().getMethod("get"+fieldName).invoke(fromObj, null);
if(n==null)
fields[i].set(to, null);
else if(n instanceof IsSerializable ){
if(depth==0)
continue;
fields[i].set(to, toPOJO(n,depth-1));
}
else if(n instanceof Collection){
if(depth==0)
continue;

Collection fromCol=(Collection)n;
Collection toCol=null;
if(fields[i].getType()==Set.class){
toCol=new HashSet(0);
}else{
toCol=new ArrayList(0);
}
for (Object object : fromCol) {
toCol.add(toPOJO(object,depth-1));
}
fields[i].set(to, toCol);
}
else
fields[i].set(to, n);

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return to;
}
}



Sample Bean:
=============
@Entity @Table(name = "message") public class Message2 implements
IsSerializable { public Long id; public Thread thread; public Set s;
public Set t;
public Double rating;
public Long ratingCount;
public String messageText;
public Long creationDate;

public Message2() {
s=new HashSet();
s.add("Hi");
s.add("Hi2");
t=new HashSet();
Thread p=new Thread();
p.id=90l;
t.add(p);
Thread pp=new Thread();
p.id=908l;
t.add(pp);
}

public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Double getRating() {
return this.rating;
}

public void setRating(Double rating) {
this.rating = rating;
}
public String getMessageText() {
return this.messageText;
}
public void setMessageText(String messageText) {
this.messageText = messageText;
}
public Long getCreationDate() {
return this.creationDate;
}
public void setCreationDate(Long creationDate) {
this.creationDate = creationDate;
}
public Long getRatingCount() {
return ratingCount;
}

public void setRatingCount(Long ratingCount) {
this.ratingCount = ratingCount;
}
}

Please post your comments..........

thanks
raghunath
http://gwtwinner.blogspot.com/

Raghunath

unread,
Mar 9, 2008, 1:31:20 AM3/9/08
to Google Web Toolkit

The above bean definition is not complete one ,
the complete bean will have all ejb 3.0 annotations..

part of bean def will look kie this:

---

@Id
@Column(name = "id", unique = true, nullable = false, precision = 10,
scale = 0)
public Long getId() {
return this.id;
}

public void setId(long id) {
this.id = id;
}

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
public UserInfo getUserInfo() {
return this.userInfo;
}

----

raghunath

noon

unread,
Mar 9, 2008, 8:09:21 AM3/9/08
to Google Web Toolkit
Hi,

You definitively cannot replace lazy properties with null : when the
POJO is sent back to the server, Hibernate will *delete* the
property !!!!
I work on this issue since more than one year on hibernate4gwt, and
trust me, it is not a trivial issue that can be solved with one
class...

About GWT 1.5 and Hibernate, you can read
http://www.dotnetguru2.org/bmarchesson/index.php?p=786&more=1&c=1&tb=1&pb=1

Finally, now than an official milestone of GWT 1.5 is available, I
will start to work on it and make hibernate4gwt more useful (no need
to DTO with Java5 classes).

Regards
Bruno

Ping

unread,
Mar 9, 2008, 11:45:05 AM3/9/08
to Google Web Toolkit
Hi,

Just a minor correction I think: hibernate will either throw an
exception or delete the property if you nullify a collection or call
clear() on it, respectively. This only happens if you have the session
open (openSessionInView pattern). the problem is you must replace lazy
properties with null and avoid hibernate of tracking changes to that
properties. Like Bruno said, the problem is not simple. Although I
haven't tested Bruno's hibernate4gwt yet, I would be glad to give it a
ride if it could work with plain annotated pojos and no DTOs at all.

On Mar 9, 12:09 pm, noon <bruno.marches...@gmail.com> wrote:
> Hi,
>
> You definitively cannot replace lazy properties with null : when the
> POJO is sent back to the server, Hibernate will *delete* the
> property !!!!
> I work on this issue since more than one year on hibernate4gwt, and
> trust me, it is not a trivial issue that can be solved with one
> class...
>
> About GWT 1.5 and Hibernate, you can readhttp://www.dotnetguru2.org/bmarchesson/index.php?p=786&more=1&c=1&tb=...

noon

unread,
Mar 9, 2008, 12:20:48 PM3/9/08
to Google Web Toolkit
Hi again,

You are right : nullyfied collection properties are not deleted, but
throw an exception ;-)
About GWT 1.5 support, I will start to work on it next week, and hope
to make it work with full EJB3 annotated POJO soon.

Stay tuned !
Bruno

PS : sorry if my previous post seems agressive. It was not my
intention. Damned busy week :-/ ...

bwtaylor

unread,
Mar 9, 2008, 4:20:19 PM3/9/08
to Google Web Toolkit
I agree that this is a hard problem. I've struggled with the interplay
between a transfer object assembler and lazy loading. If you use java5
features in your domain model and thought GWT1.5 would make the need
for an assembler go away, I have bad news for you. Hibernate's proxies
and persistent collections make this impossible. So you are still
going to need some form of assembler. There are two alternatives: to
make it configurable by use case or to make it generic.

Wherever the object graph is clipped, you need some way to mark it in
the client side object graph. You can use null, but only if you are
going to create use case specific assembler code that handles the
field or collection in question. For example, if you have an Employee
class and a Deptartment class and you send back an object graph of an
employee and his department where the department.getEmployees()
collection is null, your assembler has to know that it isn't supposed
to persist that collection in this use case. This means in every use
case you have to explicitly define in advance what section of the
object subgraph you care about, and eagerly load it. When an updated
subgraph is returned, you've got to reattach it to a persistent object
graph and not change anything outside of the subgraph. Configuration
and/or code for each use case will obviously proliferate and take a
lot of maintenance.

If you want to not have to decide up front what object subgraph is
used in each use case, and instead infer it from what's handed to you,
then you need some way to mark where the subgraph has been "clipped".
Now this marker cannot be null because that already has a meaning and
intermixing "not loaded" with "delete" is obviously not good. The
obvious thing to do is use a special meaning subclass. Imagine sending
an employee and his department to the webapp. When you assemble this
for transport to GWT, you'd need to put an object representing an
unloaded collection in the department.getEmployees() field. The GUI
use case may or may not want to traverse this collection. If it
doesn't, then eventually the object graph could be sent back and the
unloaded collection marker object would be deserialized and reattached
as an unloaded hibernate persistent collection. If on the other hand,
the GUI decides it needs to access department employees, it could make
another GWT-RCP call to load that collection and merge the result into
the clientside object graph. It would be REALLY COOL if somebody could
implement this as framework code for transparent remote lazy loading.


On Mar 9, 7:09 am, noon <bruno.marches...@gmail.com> wrote:
> Hi,
>
> You definitively cannot replace lazy properties with null : when the
> POJO is sent back to the server, Hibernate will *delete* the
> property !!!!
> I work on this issue since more than one year on hibernate4gwt, and
> trust me, it is not a trivial issue that can be solved with one
> class...
>
> About GWT 1.5 and Hibernate, you can readhttp://www.dotnetguru2.org/bmarchesson/index.php?p=786&more=1&c=1&tb=...
Reply all
Reply to author
Forward
0 new messages