I am working on a project that includes GWT and Hibernate. I
If I am not wrong, Hibernate doesn't leave our beans mere a POJO. It just completely changes our beans if we see it by refactoring, most probably when the bean is not completely loaded, it becomes instance of some MyBean$$EnhancerByCGLIB class. So when we try to send this bean to GWT client, that bean is no more IsSerializable. So as a temporary solution, I have prepared one convertor using refactor that converts my Hibernate bean to simple IsSerializable kind of POJO. But as project is growing, issues are rising and I need to enhance the convertor for copying object graph.
So I want to know that if anyone has faced the same issue earlier and is there any stable solutions for this issue. I came across one technology called "Hibernate4GWT". I didn't get time to try it out. But its documentation says that it supports GWT 1.4 and 1.5 version. so again want to know that what if I am using GWT 1.6.
I also request moderators if it is possible to have link of the same thread in the forum of Swing/AWT/.. also. Its quite possible to get answer of this query in that forum.
>>If I am not wrong, Hibernate doesn't leave our beans mere a POJO.
Hibernate should completely leave your bean alone. It remains the same object type throughout its lifecycle.
Hibernate doesn't add any hooks into a POJO, and in fact, all the Hibernate configuration is external to the bean. That's why people love Hibernate so much.
What is happening to your POJOs that makes you think they have been transformed into some strange monster? What Hibernate version are you using?
Here's an example of Hibernate persisting a POJO named user. The main method does all the stuff. You'll notice that at no time is the User instance ever anything but a User instance. I can then pass this User instance off to GWT or an EJB, or a JSF component, or whatever, and it's always used as a User POJO - no Hibernate 'hooks' at all.
I am really surprized that Hibernate really doesn't do any such thing with beans. And still I am totally confused about what actually happens. I am using Hibernate-distribution-3.3.1-GA. I seen my pojo in debugger after fetching data and after hibernate session is closed. If I print all the field of an object that is not completely loaded by hibernate, result was surprizing.
e.g. If I have one property named "name" then its converted to something Field$$name$$ (Dont exactly remember it right now).
Is it JPA that makes some difference? I want to know that is there any difference between Hibernate JPA and simple Hibernate?? And on e more thing I want to mention is that I didn't use method of annotation. So is there something in the mapping that makes difference? whatever I mentioned about the $$CGLIB or Field$$, doesn't happen in every case. it happens only when hibernate is not loading complete object graph and instead of that only proxy object is loaded. so ultimately i am not getting able to pass the bean to GWT-client.
If I'm on the right track, your problem is that you load an entity, and then you need an associated entity, or something somewhere else on the object graph. Well, Hibernate will not load all associate properties in a one to many or many to many relationship by default.
So, if you pass a POJO to GWT, and then ask for that POJO's associated property, well, it will not have been loaded. What you think you're seeing is Hibernate inside of your POJO. I understand that impression. But really, all you are seeing is a placeholder for data Hibernate refused to load for performance reasons. Rather than nulls, Hibernate is putting in a dummy proxy, which you might be seeing as a bizarre Object or reference. Hibernate does this, so if you do need the associated object, and the Hibernate Session is open, it can get it for you.
Did you hear that? IF THE HIBERNATE SESSION IS OPEN. You are getting a partial object graph, closing the Session, and passing the object to GWT. Why not get the object, pass the object to GWT with the session open, let Google Web Toolkit do its magic, and then, close the session. Your problem will be solved.
This is referred to as the "Open Session in View" pattern. It can't fit into all architectures, but it fits into most.
So, am I getting to the heart of the matter? Are you feeling a bit of forgiveness for accusing Hibernate infecting your POJO's with Swine Flu?
Joined: Oct 12, 2008
yes... you are bang on the target now in gettin my point, however, I am not fully convinced with the solution, as it will no more be following MVC. And the application is large scale enterprise application so really can't afford to keep my doors open for everyone... Whats your openion on that?? Would it be wise solution of keeping hibernate session open for view?? Won't it be nightmare?
I am in search of solution which can just convert my hibernate-infected-bean into simple POJO. Even I have written my on BeanConvertor. Basically I have two set of beans one for client side (Transfer Objects) and one for server side for persistence. Each persistent bean has exactly same corresponding bean in the client side. In the up-trip, I call this convertor to convert my client side bean to server-side bean and in the down-trip, I convert my persistent-bean into client side bean. This convertor converts complete object graph to client side bean, sets "null" in the client side bean where proxy object is found in the persistent bean. But issues are rising as its used more and more. e.g. Handle beans with Bi-directional associations, handle collections in the bean and many more.. I got rid of some of them but frequently I need to spare time to enhance it So I want to get rid of these frequent distractions.
Are you feeling a bit of forgiveness for accusing Hibernate infecting your POJO's with Swine Flu?
I will reply on this after this problem gets completely solved....
I have successfully used RESTlike service(s) for backing a GWT UI and I get the feeling it may solve the problem you have in this case.
(RESTafarians take note: I say RESTlike, not RESTful!)
The RESTlike service takes an additional parameter in all requests which enables me to specify the depth of the data representation I want to retrieve. Say that I have the following relation:
One Customer can have many Orders and one Order can contain many Items.
If I specify the depth of 1 when retrieving the Customer, I will get the Customer data and URIs to all the Orders of the Customer in the representation.
If I specify the depth of 2 when retrieving the Customer, I will get the Customer data and the data for all the Orders of the Customers. In each order, there will be URIs to all the Items of the Order.
Using the above, you can still use Hibernate for persistence AND close the Hibernate session as soon as you are finished retrieving data, because you know that the UI will use any enclosed URIs if it want to access data beyond the depth in the request. In fact, since the RESTlike service(s) returns a representation of the data in JSON or XML, the UI never even touches your POJOs.
Hope this is of any help!
Cameron Wallace McKenzie
author and cow tipper
I think Ivan is really bang on here with the concept.
The problem is getting the proper 'depth' as Ivan says. Given a certain request, your server needs to know how deep to copy your POJOs.
I always have a service layer doing this. The Service layer gets a command, executes the command, and then does a deep enough copy to ensure that the object being sent back has all the appropriate associations initialized. Indeed, this can be different for each command coming in, but it is an alternative to the Open Session in View pattern. Indeed, the open session will really only work if your Data tier and web tier are on the same machine (JVM?). In an enterprise environment where the data and web tiers are separate, Open Session in View runs out of steam, as the session will not span JVMs.
But essentially, you have the problem of how much data the client needs. Right now, your associations are lazy, and your clients are not getting enough data back. You could make all your associations eagar in the hibernate configuration file, but that would send too much data back, and potentially cause performance problems. So, you need to figure out how to send just the right amount back. How are you going to do that is really the question. I'd say in a service class of some sort - an application service.
Joined: Oct 04, 2006
I think that you can have all the associations lazy, since, when you create the representation of an object (the representation being JSON, XML or whatever you like), you will traverse associations to the desired depth, but no further.
For instance, if I have a class named Customer which can contain any number of Orders and I have a method that creates the JSON representation of a Customer, it may look like this:
Enough with my ramblings. Please let me know if anything I've said is unclear and I will try to explain.
Joined: Oct 12, 2008
Ivan, as I mentioned earlier, I have seperate set of beans for client side and server side. So instead of transforming it into JSON representation, I am converting server side bean to client side bean. Second thing is that, the system in which I am working on is totally dynamic. So at compile-time, I have no idea about what depth I will need at run-time.
I have two beans called Container and Component at server and for client I have ContainerTO and ComponentTO.
Because Container-Component's inheritance and aggregation relationship, whenever I retrieve Container instance I need to load that instance fully. If "components" set inside Container has objects which are instanceof Container, then I again need to load that container. So one instance may have 3 level depth in "components" and the other may have only one level in its "components" meaning all the instances in the set are Non-container.
I am loading my beans upto required depth but I get stuck when Proxy object of Hibernate is found. Even that can also be solved but I want to have some reliable solution. I feel that current solution is not permanent. Here is the conversion code that I am using to convert my server-side beans to client-side beans.
I am trying to understand these APIs also to get rid of this.
It looks fairly painless, although there is a need to do some extra inheritance in your POJO objects. I went to this technology solution after hitting the following message, after doing everything I thought I needed to do to 'remove hibernate from my POJO.'
Exception while dispatching incoming RPC call javassist_3' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded.