Search code examples
apache-flexgwtlazy-loadingrich-internet-application

When does lazy loading become a problem in RIAs?


So I've got a simple web application using Spring MVC + Hibernate and am using the OpenSessionInViewFilter. I've recently been thinking of replacing the UI with something like Flex or GWT.

At first I thought it would be easy, in that I can just hit my service layer from the new front end. But as I consider this a bit more, I'm a little bit nervous about the issues surrounding lazy loading. Using a traditional web front end it's no problem because I'm using open session in view...everything that needs to get loaded for the view gets loaded as the view is constructed.

So Let's say I've got a method to return a Customer, and a Customer has a bunch of Contacts, and Contacts have a bunch of Addresses, and so on. If I call getCustomer() from my new "RIA" controller, it's going to get a Customer, but the Customer's collection of Contacts is just going to be a proxy or null.

I could create a new layer on top of what I've already got that returns DTOs which are pre-populated...but... that seems like it's going to get complicated.

Any advice?


Solution

  • You're absolutely right that this does introduce a problem for RIAs. If you're using OpenSessionInViewFilter then data won't get returned null; rather the serializer will walk the entire object graph and send an enormous amount of data back. This is going to introduce serious performance problems.

    Introducing a separate DTO layer gives you a lot of control in that you can ensure that the serializer only walks objects you've constructed; you can ensure that they contain no lazy proxies. This unfortunately introduces some tedium in writing mapping code between your entities and DTOs but it does give you full control to do anything you want.

    Another approach is to introduce a layer just before the serializer that prepares your object graph for serialization. One approach we used on some past projects was to introduce an aspect to the service layer that would walk the entire object graph and replace lazy proxies with a new instance of the Entity with only its @Id property set. If the graph got saved back at a later time, this would ensure that @ManyToOne relationships were not inadvertently nulled. You could call getters or use Hibernate.initialize() to force initialization of data you did want to send over the wire. This does get more complicated when you introduce cascading saving of @OneToMany or @ManyToMany relationships in Hibernate.

    I recently came across a solutin called Gilead that is designed to handle this problem. It uses an approach similar to the one described above:

    http://noon.gilead.free.fr/gilead/

    I also believe Granite DS has a solution to this problem as part of its Tide framework:

    http://www.graniteds.org/confluence/display/DOC/4.+Lazy+Initialization

    One problem I don't think anyone has solved is a way to actually lazy load data in a RIA from the server. I think it could certainly be done but there are some security concerns here. You would need pretty robust security checking in place to make sure that any attempts to lazy load the data were from the user who actually has permission to load that data in the first place.