Gabor has posted 5 posts at DZone. View Full User Profile

A Tricky Lazy-Exception With JSF

07.29.2010
| 6067 views |
  • submit to reddit

JSF with Seam and JPA is quite a powerful combination. However, you still have to be aware of many nuances. I plan to share some of these, starting with a lazy-load exception that is quite strange at first sight.

As JSF+JPA developers know, when not using Seam conversations, one web request uses one Hibernate (let's take this as example) session. When using Seam, that session is valid during the rendering phase as well, so you don't have to write code in your backings to force the loading of your entities' lazy associations that is going to be needed in your view. You can just write: #{entity.lazyCollection} in EL. With Seam conversations you can get even further.

However, there's a small tricky part with JSF repeat tags (h:dataTable, facelets ui:repeat and a4j:repeat all apply). Their data sources are also evaluated during a faces phase before actions are invoked. This causes a problem when the user navigates back to a page using the back button, and presses some button there that invokes a faces action. If, on that view, there is a repeat tag bound to some data that might be unavailable later or relying on a lazy-loaded association, you'll be in trouble :)

The painful part of this is that the action that the user is invoking might be actually unrelated to the data presented on the page. So to invoke that action, it is not necessary to have that data loaded. But you have to make sure that it can be successfully evaluated (and it will be evaluated before the actual action is invoked).

Maybe my description is a bit hard to follow, but there's a simple way to reproduce this:

  • Have a backing with a Company entity and a lazy-loaded addresses association
  • Have a view company page that renders the company data and its addresses using ui:repeat
  • Have another view that presents some other data related to the company. Navigating to this view from the first page reloads the Company entity in the backing, but the addresses association is not loaded
  • When we use the back button to go back to the first page, and press the same button again, the magic happens: before processing our action, the ui:repeat in the view, that we are not actually using, now will try to fetch the addresses collection

This might seem to be a rare situation, but we have faced this problem several times. A solution to this problem might be to load the presented collections into a collection in the backing, eg: #{backing.companyAddresses}, and fill this list in the action that shows the first page - this property will always evaluate without exceptions.

To summarize, don't get spoiled by ease that Seam offers. You still have to be aware of what your entities are doing, when they and their relations are loaded, and how long are they available.

3
Your rating: None Average: 3 (1 vote)
Published at DZone with permission of its author, Gabor Farkas.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)