Home > JavaEE > The OpenSessionInView antipattern

The OpenSessionInView antipattern

With such a controversial title, I’m bound to be the target of heated comments. Although provocative, such is not my goal, however, I just want to initiate an educated debate between people that are interested into thinking about the problem.

The origin of this post was a simple discussion between developers of different level of experience on Hibernate. The talk was about eager-, lazy-loading and the infamous LazyInitializationException. Since I imagine not everyone has the problem in his mind right now, let me resume it at first.

Most of the times, your entities have relations to one another: a course has students, an invoice has a customer, etc. These relations could take you really far (a student follow courses, which are taught by teachers, who in turn have other courses), and since most of the time, you don’t need the whole objects cluster, Hibernate let you define relations as either eager or lazy. Eager relations do get the association, while lazy relations are replaced by Hibernate by a proxy. These proxies do nothing until activated by calling the getter for the association. At this time, the proxy queries the database through its encapsulated Hibernate session.

If the latter is already closed, you’ll get the LayInitializationException, since Hibernate tries to query the DB without connection. However, there are 3 solutions to the exception.

The simplest is, of course to tag the relation as eager. Hibernate will never use a proxy, and thus, you’ll never have this exception (from this relation at least). This is not a solution per se, since if you do this with all relations, Hibernate will load all associations, and you’ll end up with a mighty big objects cluster. This defeats Hibernate lazy strategy as well as clutter the JVM’s memory with unused objects. Associations that are used throughout the application are a good candidate for eager tagging, but it’s the exception, not the norm.

Another solution for this is the OpenSessionInView “pattern”. Before going into explaining it, let me layout the whole thing.Good web applications are layered, meaning the persistence layer (the one nearer to the database) is responsible for interacting with the DB. Most DAO will open the Hibernate session at the beginning of the method (or get it from the current thread but it’s another matter), use it to CRUD the entity. and return control to the service layer. From this point on, there should be no more interaction with the DB.

Now the “pattern” tells us that if an Hibernate proxy need to access the DB in the presentation layer, well, no problem, we should open the session on demand. This approach has 3 big disadvantages IMHO:

  1. each lazy initialization will get you a query meaning each entity will need N + 1 queries, where N is the number of lazy associations. If your screen presents tabular data, reading Hibernate’s log is a big hint that you do not do as you should
  2. this completely defeats layered architecture, since you sully your nails with DB in the presentation layer. This is a conceptual con, so I could live with it but there is a corollary
  3. last but not least, if an exception occurs while fetching the session, it will occur during the writing of the page: you cannot present a clean error page to the user and the only thing you can do is write an error message in the body

Another variant of this is to use Value Objects and let a mapping framework (such as Dozer) call your proxied getter methods in the service layer. This let you correctly handle errors but your number of queries is still the same.

The best solution I’ve found so far to lazy initialization is the “join fetch” feature in Hibernate, available from both the Criteria API (setFetchMode(association, FetchMode.EAGER)) and HQL (JOIN FETCH). This means your query methods will be aimed at providing a full objects cluster to your upper layers. This also means, and I must confess this is a disadvantage, that your presentation/service layers will leak to your persistence methods: for example, you will have a getCourseWithTeacher() method and a getCourseWithStudents() method where in both cases some relations will be eagerly fetched (the teacher in the first case, the students in another).

Nevertheless, this approach let you do only one query for each screen/service and it lets you cleanly manage your exceptions.

I see only a use case for OpenSessionInView: if you have a bunch of junior Hibernate developers, no time to properly explain them the whole shebang, and no performance issues (perhaps because of a very simple entity model or from very simple screens), then it is a good trade-off (but still not a pattern). As soon as you diverge from this configuration, it will lead you to a world of pain…

I’m interested in having your inputs and arguments about advantages  I may have missed about OpenSessionInView so long as it has nothing to do with:

  • I’ve always done so successfully
  • I never had any problems
  • XXX advertise for OpenSessionInView in YYY book (yes, I know about Gavin King but it shouldn’t stop anyone from thinking on his own). A variant of this is: the ZZZ framework has a class that does it (I know about Spring too)

I’m also interested in other solutions for the LazyInitializationException, if you’ve have creative insights about it.

email
Send to Kindle
Categories: JavaEE Tags: ,
  1. Marcus K.
    November 2nd, 2010 at 02:09 | #1

    I usually use OSIV because it is simple to use. Just if it causes performance issues on some pages with larger tables, I create custom queries with explicit FETCH statements. On the other hand, I was trying to use eager fetching queries via Criteria API, but the entities were still loaded while rendering the view. In fact, entering some nonsense like setFetchMode(“doesnotexist”, FetchMode.EAGER) does not create any error or warning. I think have to figure out how it should work…

  2. November 2nd, 2010 at 09:46 | #2

    Hi,

    to start off, I’d like to state that I’ve OSIV workaround in quite a lot of applications and it had helped me quite a lot. So I’d like to take the counterpart position of what you stated, especially the three points of critique you gave:

    1. Each lazy initialization will get you a query meaning each entity will need N + 1 queries, where N is the number of lazy associations. If your screen presents tabular data, reading Hibernate’s log is a big hint that you do not do as you should

    Well, that’s arguing against lazy loading in general, not against OSIV in particular. N+1 queries can be avoided through correct mapping already. So I definitely agree on the “you have to know what you’re doing” on this side.

    2. This completely defeats layered architecture, since you sully your nails with DB in the presentation layer. This is a conceptual con, so I could live with it but there is a corollary.

    That’s not the only aspect of app development that faces this tension. Transactions are usually at the granularity of services but are a deeply DB related concern. As Session management is as well, they are an infrastructure concern so you shouldn’t deal with things like that in your application code. I am perfectly fine to configure a Spring OSIVF in my web.xml as it just clearly states: I want one open Session for my entire request.

    3. Last but not least, if an exception occurs while fetching the session, it will occur during the writing of the page: you cannot present a clean error page to the user and the only thing you can do is write an error message in the body.

    On subtle thing here. You stated that Sessions will be opened and closed at will which is definitely not the with Spring’s OSIVF e.g. It will open exactly one session in the beginning of the request, setting it to FlushMode.NEVER (so that you don’t accidently flush data that you’ve accidently changed while rendering the UI on the way back) and thus forcing you to have transactions in layers below that take care of actually persisting things.

    Regarding the error stuff you should have some common servlet container error page for your application that hides RuntimeExceptions from your users anyway, right?

    I’d even argue that you do more harm to your application architecture by cluttering the service layer with very fine grained use case specific methods as this implicitly makes the service layer aware of very detailled UI needs. I’d continue arguing that you shouldn’t code an OSIVF implementation yourself as there are quite a few ones out there in your application framework of choice.

    Cheers,
    Ollie

  3. November 2nd, 2010 at 22:17 | #3

    @Oliver Gierke
    Hi Ollie,
    First, I’d like to warmly thank you for your input. Though we disagree, the point is the debate, not the conclusion.

    Please no arguments like “I’ve already done it and it succeeded”. That’s no argument, only happenstance (or dumb luck if you prefer).

    I do not argue against lazy loading. Correct mapping does not ensure a single query: you could need an association in one screen and not in another. That would definitely hint to lazy loading and you would still have the problem where tabular data is concerned.

    However, I find your point regarding transactions in the service layer, though DB related, very interesting. It’s a good parallel. As I stated before though, that’s conceptual, so I can live with it.

    OK, for the single session opening. Yet, you still does not answer the problem of the exception: if there’s an exception while accessing the DB during page write, there’s NO way to redirect to an error page because the stream was already partially sent to the client. That’s the biggest problem of the matter and I hope you will be faced with it soon enough, because then will you realize all the evil this “pattern” does (a bit melodrama doesn’t hurt).

    Cheers,

    Nicolas

  4. denlab
    November 23rd, 2010 at 21:12 | #4

    On a recent web project, we demarcated txn’s in the service tier. However, anytime an eagerly loaded entity was required (above the service tier), forced us to write cluttered methods (eager vs. non-eager, etc) as you pointed out. This could easily become a maintenance nightmare, if we’re not careful.

    Even more painful, we use Jackson’s JSON object parser to render JSON objects (for AJAX calls), during the processing of the view (provided by Spring 3.0.x), which forces you to a) either provide a txn (via OSIV, I suppose) so it can traverse the entity, or b) mark the entity with @JsonIgnore annotations, which may not be as ugly as a bloated service but highlight the deficiencies in our design.

    Maybe OSIV is the way to go when building web apps using IoC like Spring out of the box, provided the db is properly indexed; You know you will incur a cost (N+1), but only when you try to access a proxy. Maybe better [hql] querying could reduce that cost, but then I guess the developers need to be up to speed. So is it really a debate on cost to market vs. application performance? Anyway, just food for thought, there’s no simple solution, you will experience pain with either pattern, imo.

  5. Maksym Govorischev
    January 19th, 2011 at 16:49 | #5

    @Nicolas Frankel
    Nicolas, I’m not really sure that it’s OSIV’s problem. I believe it’s more likely to be a problem with your view layer, because even if you don’t use OSIV, you can still get the same issue if an exception occurs
    because of any other reason. I think the right way is to prepare view data and then render the view page. In this case you get an exception before any part of the stream has been sent to the client.
    An example can be Spring MVC. In the controller you first form a Model object and then after controller has finished it’s work, this model is merged into view(in my case it’s Velocity template).
    So if you get an exception you can easily redirect to dedicated error page.

    Cheers,
    Maksym

  6. Iakov Gnusin
    July 11th, 2011 at 12:49 | #6

    what about returning fully structured DTOs from the service layer, and keep all hibernate persistence only in DataAccess/Service layers?

    this would eliminate the OSIV approach, however add another abstraction layer via DTOs and more classes

    Regards, Iakov

  7. July 11th, 2011 at 13:04 | #7

    Yes, it’s a valid approach. However, the whole DTO thing is overkill most of the time when they entirely mirror entities structure and relations, which is often the case.
    For simple web-applications which only access to the service layer is the presentation layer, entities are enough, and OSIV an anti-pattern.

  8. JS
    August 26th, 2012 at 22:18 | #8

    I guess it’s little late but still… DTO doesn’t mean that you have to duplicate entities structure in DTO structure. I’m usig DTO per view so my DTO object contains only data needed by concrete view (possibly data from many entities / associations). This approach usually allows loading what you need in one single query (like “select new com.somecompany.MyDto(entity1.value1, entity1.value2, entity2.value1…) from Entity1 entity1 join entity1.e2 entity2…)

    Regards
    JS

  1. No trackbacks yet.