Spring, Hibernate, Lazy loading

Hi there,

I’m evaulating Vaadin for a private small project. I work a lot with Hibernate and Spring at work, so I’ve set up a little project with spring 3.0, hibernate 3.5. Now I’m figuring around with this stack expanded by vaadin.

The wiki shows how to use vaadin with hibernate through the HbnContainer. I tried this and facing some problems:

I’ve got some relation-mappings in my hibernate files which end up with lazy loading exceptions. So, the HbnContainer cannot handle lazy loading or am I doing something wrong?

Is the usage of the HbnContainer a “best practice”? Another thought was to build a container for each entity I’ve got in my project but this seems too heavy in this case. Its possible that I’m not seeing the easy way of this.

Thanks for reading

HbnContainer should be able to lazy load. You might also want to try to JPAContainer. For a small private project AGPL license should not be a problem.


Onur
, having a look at
HbnContainer.java
I see that nothing prevents from being lazily loaded, if you implement
HbnContainer$SessionManager.getSession()
to retrieve the session via
org.springframework.orm.hibernate3.LocalSessionFactoryBean
. Also you will probably need to extend the lifetime of Hibernate session to the HTTP session (otherwise it will be closed and opened by transaction manager): read
here
, but you need to
wire Vaadin and Spring
via
org.springframework.web.servlet.DispatcherServlet
, as this is the only way to support interceptors.

I would like to ask the community about the following:

Usually containers that support lazy loading require a reference to some DAO (DB DAO, or WebService reference, or in context of this post a reference to
HibernateSessionFactory
), which is not very handy to pass via all constructors and UI class hierarchy (MyApplication->MyTable->MyContainer). What are the approaches one uses to handle this nicely using Spring?
More over such containers cannot be serialized within a HTTP session (not Serializable). Is it bad? Maybe it is possible to tell Vaadin not to serialize such containers. There is possibility to mark referenced to DAO as transient and then recover them via
AOP load-time weaving
but is it really sexy?

Dmitry,

the approach I’ve taken is to wire EVERYTHING through Spring. In other words, my main application class is very bare-bones and just references a mainWindow; which is itself a Spring (session-scoped) component.

I’ve found this works very well. It removes the need to pass references to various components through the constructor which very quickly becomes cumbersome in a complex application.

In terms of the DAO objects - these now become globally scoped objects in the Spring application context which are simply dependency injected into my session scoped vaadin components.

You are correct that they DAO’s cannot be serialized; so I mark them simply as “transient”. However, it does pose a problem if the application is serialized and deserialized to another cluster member. Right now, this isn’t really a problem for us as we don’t cluster our applications yet, but it will become an issue at some point in the future.

One possibility I was thinking of was indeed what you suggested - i.e. use AOP to detect the deserialization call (i.e. readObject) and “re-attach” any transient components from the new application context. Problem here is this absolutely mandates the use of AspectJ as the readObject method call is private and cannot be intercepted by just using Spring AOP.

Another possibility would be to ignore Vaadin’s serialization/deserialization process altogether and instead figure out some way to have a Spring Session be serialized and failed over to another cluster member. Assuming that this can be solved, the picture from the vaadin side now gets much simpler as it’s simply a matter of re-attaching the main application class to the new Spring context (which would have the failed over session components).

Regarding the original topic - lazy hibernate loading and Vaadin is problematic. I haven’t tried what you suggested, but let’s assume for the moment that using the techniques you described it’s possible to implement a Hibernate session-per-HTTP Session so that you can do lazy loading in a long lived Vaadin applicaition - the approach certainly seems reasonable.

The problem now moves to session failover. The Hibernate Session cannot be serialized, so after the application fails over (and the Hibernate POJO’s along with it), you have a new Hibernate Session and now need to re-attach all the POJO’s to the new session. Again - not easy.

I find this is really the problem with all these technologies… hibernate, spring, aop, vaadin… they all work well in isolation or in simple test cases… but in a real world scenario; the complexity of dealing with basic application behavior quickly spirals out of control.

Yes, I can imagine how it looks like. In the
continuation of the thread
there is a discussion of how to make application completely Spring-based.

My application is quite tiny, and there are just few places where I need a
service
or
DAO
, so it’s easier to pass the objects. But in a big application it might be a problem, I agree. But how for example you solve the following issues:

  • Access to main window in listeners. For example when something went wrong the button click listener would like to show a notification via
    getMainWindow().showNotification()
    . When the listener comes from Spring context, it needs to be set a main window. That is doable, but everywhere you need a main window, you need a bean property for it.
  • Internationalization. For example I would like to create main window with a title, which depends on bowser preferred language.
    In this case it should be assured, that main window is created after the vaadin application was populated with locale from HTTP request.
  • Perhaps population of vaadin application to
    StreamResource
    instances might be tricky.

Anyway you can’t aspect non-interface methods in general approach, and in particular private
readObject()
(even with CGLIB ), and
AopContext.currentProxy()
trick will not help. I have never used this
load-time weaving
myself, but as I understand String comes with special agent,which need to be included into the boot cycle of JVM. These agent notifies Spring AOP about class loading and allows Spring to do the bean advising. The only thing which might be a problem is that the constructor is not called for deserialized objects.

I am using
OpenSessionInViewFilter
in web.xml – works absolutely fine for me.

Till now, using OSIV, I was hable to get an HB Session x HttpRequest.
Could someone sugest a way to make it stable for HttpSession ?
Tks
Tullio

As far as I understand the problem might be

  • in application architecture - after transaction has been executed your code is still trying to call uninitialized bean. To avoid this you should initialize all lazy initialized beans before transaction has finished either by accessing bean within transaction(it will be initialized automatically) or use join fetch construction in you JPA queries.
  • if application architecture looks fine you should sometimes when needed to use join fetch construction to avoid exception
  • the last variant when it is too late to change anything you can create DeproxyUtil class that will explicitly re-associate lazy initialized bean with persistent context and deproxy it.

While developing
Lexaden Administration
(demo/demo) we instructed Spring to create transactions on the view layer(not web) where we build up and initialize UI components.