Context:
Hibernate uses lazy initialization to load entities. E.g if some association is accessed after Hibernate session is closed we get LazyInitializationException. To solve this problem Hibernate team invented a pattern called Open Session In View. Spring offers OpenSessionInViewFilter that implement this pattern. This filter is used in many applications we have developed including AMS.
Problem:
Using OpenSessionInViewFilter solves issues with accessing uninitialized data from view. However the problem is that all intialization requests are made in a non-transactional manner. Hibernate will create new transaction for each initialization. What problems does this actually cause? First performance will be affected as DB needs to create much more transactions. Secondly atomacity of "transaction" is lost. How serious are these problems? I dare to say that not very serious so I don't think it is absolutely required to fix this for older applications but it's good thing to know when designing new applications.
Solution A:
Add another filter that will wrap the entire request inside a transaction. Downside is that we now have one big tx. Also we may discover the fact the tx needs to be rolled back after response has already been sent.
Solution B:
Improve solution A by changing tx attributes of business layer from propagation_required to propagation_requires_new. Now we can make the view rendering tx read-only and view rendering will be independent of business layer tx issues. Downside is that if service A is calling service B then we may not need to start new tx for B. One optimization here is using facades. These facades provide few methods that are specially tailored for presentation layer.
Resulting transactions:

To achieve this solution here is what we need:
- simple filter that will be wrapped inside a read-only tx.
- move tx management from services to facades.
- change transaction attributes in facade to propagation_requires_new.
Comments (10)
Mar 13, 2007
Sven Filatov says:
Another approach to make sure the data is already initialized by the time the vi...Another approach to make sure the data is already initialized by the time the view accesses it, is to fill the data object with all its properties before returning it in the response. So that there is no need for a transaction for the time the view is processed. The idea may sound overly simple perhaps, but in fact needs some care.
There are two strategies for building data objects for this:
It is good not to expose the inner business objects to outside the application, because then business layer can do whatever it wants with its own objects without caring of the outside world. Well, it is debatable if the presentation layer is really a outside world though... at least it is another component of the application. Moreover, consider a remote application talking to your application over the wire. We have made some work-arounds in Regio project for such a case (the notorious Service class if you are familiar with the project).
So I think it is better to make the separation of objects as in the latter option above. Even though it requires some extra (albeit trivial) code for the translation.
Mar 14, 2007
Ürgo Ringo says:
I think the benefit of initializing business objects before sending them to UI i...I think the benefit of initializing business objects before sending them to UI is that you can get rid of OpenSessionInView which is considered (probably rightfully) to be a lazy man's solution. However in situation where there is no specific reason to distrust the UI layer I see no harm in being a bit lazy.
About constructing special data objects for UI instead of reusing business objects I think again that unless you have some reason to suspect that there is something fishy going on in UI I wouldn't go for such approach. Of course in most cases it is not possible to expose your business objects directly but one has to wrap them inside some adapters. But these require much less pooring translation code as UI object to business object conversion.
Does anybody know if we have developed any application where business objects are not used UI layer?
Mar 14, 2007
Sven Filatov says:
Does anybody know if we have developed any application where business objects ar...Regio Monitor and FriendFinder; Hansa LoanComponent.
Mar 14, 2007
Ürgo Ringo says:
Does Hansa LoanComponent have business entities that contain actual business log...Does Hansa LoanComponent have business entities that contain actual business logic?
So far all our applications that I have seen have been built using quite procedural design where all business logic is implemented by services whereas business entities are pretty similar to plain DTOs.
Mar 14, 2007
Sven Filatov says:
They contain a little. But they are definitely closer to DTOs than "ideal" busi...They contain a little. But they are definitely closer to DTOs than "ideal" business entities.
Mar 14, 2007
Sven Filatov says:
One example where preparing the objects early for the view will not work well is...One example where preparing the objects early for the view will not work well is when the object has an associated collection that is configured as extra-lazy in Hibernate. In that case the view triggers loading the data when accessing concrete items of the collection.
Mar 14, 2007
Ürgo Ringo says:
Yes but shouldn't using either OpenSessionInView or Hibernate.initialize(myBusi...Yes but shouldn't using either OpenSessionInView or Hibernate.initialize(myBusinessObject.extraLazyCollection) solve lazy initialization problem even for extra lazies?
Mar 14, 2007
Sven Filatov says:
Yes, it does, and that was actually my pointYes, it does, and that was actually my point
Mar 14, 2007
Ürgo Ringo says:
You mean that because we are exposing business entity to view some associated bi...You mean that because we are exposing business entity to view some associated big collection may get initialized?
But if it is not wanted to load that many objects then why is it even made possible to access such collection? I mean we get same problems if we access this collection inside business entity to DTO translation code.
Maybe in such situation we should instead consider making this collection write-only. This enables to cascade saves without having any dangerous methods in business objects. Business entities from associated collection can be accessed through Query API which makes it possible to load only these entities that are actually wanted.
Mar 14, 2007
Sven Filatov says:
For example, a big collection in a reference data. Since it is not likely that ...For example, a big collection in a reference data. Since it is not likely that a huge amount of data is required for the view, this big collection in the reference data should be filtered out and only required (few) collection elements included. This is controller's responsibility then. Should help avoid the trouble at least most of the times.
It may be required to have such a big collection available though for processing in business logic. And there you may want to access the (few) items of such a (big) collection so that each item is loaded on-demand.
Of course, one could always use Query API to load "special" data.
Add Comment