Flex Pasta » Serialization Profiles with BlazeDS

Serialization Profiles with BlazeDS

The problem is common when using BlazeDS and Hibernate: Lazy loading is not possible without inflating a large object graph.  The most common solution to the problem is to “break” parts of the model into manageable pieces based on how the application works.  So while there should be a many to many relationship between two entities, maybe it is just left off to avoid problems.  This can fragment the object model.  When the object model becomes fragmented, it causes extra code to be written to make up for the lack of a correct object model.

A different approach to the problem

Another approach to keep the model pure but avoid large data loads is to use a serialization profile.  This means keeping the model the the way it should be, but defining profiles on service methods to determine what parts of the graph are inflated during serialization.  Most of the time a service provides functionality to one part of an application, or multiple parts that are used in a similar manner.  It is more common for an object model to be used differently in different places of an application. Therefore it makes sense to single out service calls to determine object inflation.

How BlazeDS comes into it

A while back I wrote a post regarding annotations for remote objects with BlazeDS.  I have expanded the annotated bean proxy to include this concept of a serialization profile.  I also created a small demo project to show just how easy serialization profiles could be used.

My ‘Pet’ Project

Take a look at the following image showing the model for the pet project.  As you can see, the pet class has 4 one to many relationships.

Pet Project Class Model

Now take a basic flex application that has a datagrid with a list of pets.  Clicking on a pet results in the details being shown.

Pet Data Grid

This query in hibernate is something like this: getHibernateTemplate().loadAll(Pet.class);  The result would be one query for the list of pets plus and then n+ queries for all of the collections as serialization happens.  In this case the whole database of records would be loaded.  For 3 record this is ok, but for a large number of pets we could be waiting a long time as the entire database is loaded simply because we cannot have lazy collections.

How to use a Serialization Profile

Now let’s show how a serialization profile would help.  Here is the small snipet of code for my service method:

@SerializationProfile(profile = “petList”)
public List<Pet> getAllPets()
{
return petDao.getAllPets();
}

@SerializationProfile(profile = “petDetails”)
public Pet getPetById(Integer id)
{
return petDao.getPetById(id);
}

I have used the new annotation tag @SerializationProfile to define the profile for the remote methods.  The second step is to set profiles on lazy loaded one to many collections in my Pet class.

@FlexField(profiles = “petDetails”)
@OneToMany(fetch = FetchType.LAZY, mappedBy = “pet”)
public List<VetVisit> getVetVisits()
{
return vetVisits;
}

I can place one to many profiles on each getter method to determine its serialization profile.  I only placed one getter example here, but all 4 of my collections on Pet.class have been set the same way.  The all have a profile of petDetails.  This tells the proxy, hey, I only want to load these collections when the profile method is petDetails.  Our method call to getAllPets() now results in one query ran and only a list of pets returned, without all the extras.  Once a user clicks on a pet, the getPetById() method is called.  This method has a profile of petDetails, so all the collections are inflated upon return to flex.

Pet Details

Summary

By using the new Serialization Profile annotation and bean proxy, we were able to keep our model pure without inflating everything.  I was able to inflate the Pet object when demanded by the application and avoid it when not needed.  When other parts of the Pet application are written, they can utilize the full power of the object model without fear of various collections inflating themselves.  The performance effect(of a serialization profile) is very minimal and the performance hit(while minor) is only the first time an object is serialized.

Do you think this would be helpful on a project?

7 Comments

  • 1. lont replies at 18th April 2010, 2:04 pm :

    I think it is easier to serialize a lazy collection only when it is initialized. Just add to the beanproxy: if (Hibernate.isPropertyInitialized(….)) {return super…} else {return null} .
    In this case annotion-profiles are not needed, and makes things easier. Currently we use this approach on our projects, and works great for us.

  • 2. Kenton replies at 19th April 2010, 6:43 pm :

    You are my hero, I have this exact problem, and was working on a similar solution.

  • 3. Marty Pitt replies at 19th April 2010, 11:10 pm :

    Hey

    Cool post.

    Check out dpHibernate - which supports this functionality without the need for extra annotations (although annotations exist for customizing advanced scnearios).

    Essentially the properties of Pet get proxied and loaded behind the scenes when requested in the client. It requires very few changes to your code, and is pretty performant.

    Check it out at http://code.google.com/p/dphibernate/

    Marty

  • 4. Kenton replies at 20th April 2010, 9:37 am :

    I have two questions
    1) Is there a concept of a default profile? Also could you have the reverse where you exclude a property on a profile?

    2) And let me be the first to impatiently ask, when can we expect the code? Do you need a hand testing?

  • 5. Brian Telintelo replies at 29th April 2010, 8:04 am :

    @Kenton

    A default would be if a service method had no profile attached, then it would just serialize as normal. I thought about the “excluded” tag and thought it would make things more complicated, but I could consider it further. I will be releasing the code soon. :)

  • 6. Andrew Joseph replies at 11th February 2011, 3:42 pm :

    Have you ever considered adding more videos to your blog posts to keep the readers more entertained? I mean I just study through the whole post of yours and it was quite good but since I’m more of the visual learner,I discovered that to be more helpful well let me know how it turns out! I love what you guys are usually up too. Such clever function and reporting! Maintain up the great functions men I’ve additional you men to my blogroll. This is a great article many thanks for sharing this informative information.. I’ll visit your blog regularly for some latest post.

  • 7. Brian replies at 18th May 2011, 9:05 am :

    I was wondering if you could share how you were able to make the link between the service endpoint method with the @SerializationProfile and the @FlexField annotation processed by the BeanProxy? I didn’t know if there was some magic in the Blaze APIs that made the link for you, or if you had to setup an independent context for your code that used aspects or something else to link the two? Thanks in advance for anything you can share.

Leave a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <blockquote cite=""> <code> <em> <strong>