Hibernate and Flex? Please, dev in "Debug"!

If you're using Hibernate as the ORM behind a Flex application, I highly recommend running BlazeDS (or LiveCycle, or ColdFusion) with its services-config set to log "Debug" level to the console.

Why?

Short version: you may run a lot of unintended SQL, sometimes with really weird consequences.

Let's look at a simple e-commerce example, where a User hasMany Order, and an Order hasMany LineItem. When a user logs in, you're likely to return the user to the Flex side of the equation.

Here's what happens (assuming you've got an OpenSessionInViewFilter in place to even allow things to half work to begin with):

1. You send data to Flex (probably a User instance) 2. You read the User from the database using Hibernate. This isn't so much your pure User object as one that Hibernate knows can lazy-load things like orders. 3. You state that you want to return the User to Flex. 4. The BlazeDS serializer kicks in to turn your User into an AMF packet, calling each getFoo() method on user, including getOrders(). 5. Hibernate now comes back into the scene: getOrders() was called, and it's a lazy-loaded collection. Hibernate runs a SELECT statement to get the user's orders, even though you (probably) don't care about them at all.

With BlazeDS set to its normal default of "Warning" and Hibernate not printing SQL to the console, you'd never know this happened. However, if you print SQL to console and set BlazeDS to log at the Debug level, you can see exactly when and if a remote request is running extra SQL by looking for any SQL after BlazeDS begins serializing its response:


<!-- Any SQL before this is caused by code you've written! -->
10:37:19,570 INFO [STDOUT] [BlazeDS] Serializing AMF/HTTP response
<!-- Any SQL after this is running during BlazeDS serialization! -->

How can I set up BlazeDS in debug?

Pop open your services-config.xml file. Make sure it has a <logging /> block, and set it up like so:


<logging>
<target class="flex.messaging.log.ConsoleTarget" level="Debug">
<properties>
<prefix>[BlazeDS] </prefix>
<includeDate>false</includeDate>
<includeTime>false</includeTime>
<includeLevel>false</includeLevel>
<includeCategory>false</includeCategory>
</properties>
<filters>
<pattern>Endpoint.*</pattern>
<pattern>Service.*</pattern>
<pattern>Configuration</pattern>
</filters>
</target>
</logging>

What to do about unintended SQL?

If BlazeDS is fetching data the operation doesn't care about (Who cares about orders? We're just logging in!), instead of sending back the User object returned by Hibernate, I'd return a User (acting as a DTO) that just contains the pertinent information, using an assembler to create the DTO rather than cluttering up my remoting service.

If BlazeDS is fetching data you need (say, you actually _did_ need all of the User's orders immediately on login), you've got options. If a User can't exist without all of its orders (strong composition / aggregation), you could set up User's mappings to either eagerly fetch its Orders. However, I prefer a looser composition, and typically ask for an eager fetch in HQL:


def hql = "select User user from User inner join fetch user.orders"

Conclusion

When using Hibernate (or other lazy-loading Java ORMs), running BlazeDS (or LCDS, or ColdFusion) without letting it log at the Debug level can be dangerous. It's easy to miss a property or collection that BlazeDS will happily ask the ORM to go fetch, possibly causing monster queries to run and equally problematic object graphs to get moved about.

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
Bruno's Gravatar Hi,

You can also consider library such as Gilead (http://gilead.sourceforge.net), that will clone the User instance, taking care of lazy properties. One cloned, the BlazeDS serialization process won't fetch lazy properties.
Note that Gilead puts Hibernate proxy back to the User instance when sent from Flex to the server...

Hope this helps
Bruno
# Posted By Bruno | 12/3/08 6:36 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002. Contact Blog Owner