Matt RaibleMatt Raible is a Web Developer and Java Champion. Connect with him on LinkedIn.

The Angular Mini-Book The Angular Mini-Book is a guide to getting started with Angular. You'll learn how to develop a bare-bones application, test it, and deploy it. Then you'll move on to adding Bootstrap, Angular Material, continuous integration, and authentication.

Spring Boot is a popular framework for building REST APIs. You'll learn how to integrate Angular with Spring Boot and use security best practices like HTTPS and a content security policy.

For book updates, follow @angular_book on Twitter.

The JHipster Mini-Book The JHipster Mini-Book is a guide to getting started with hip technologies today: Angular, Bootstrap, and Spring Boot. All of these frameworks are wrapped up in an easy-to-use project called JHipster.

This book shows you how to build an app with JHipster, and guides you through the plethora of tools, techniques and options you can use. Furthermore, it explains the UI and API building blocks so you understand the underpinnings of your great application.

For book updates, follow @jhipster-book on Twitter.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.

[Hibernate] Open Session in View Pattern

I get this question a lot when folks check out my struts-resume application - so I figured I'd document it here - and then I can just send future developers a URL. The question is this:

Why do you tie your View to your Model Implementation by putting a Hibernate Session in your Service Interfaces?

I have a couple of reasons. The first reason is that I initially had ses.currentSession() and ses.closeSession() at the beginning and end of each DAO method. In fact, I found this old e-mail where you can see an example. This seemed to work for me and I was happy with it. However, I got an e-mail from Gavin (Hibernate's Lead Developer) that I was doing it all wrong. He said that I should use one session per request, rather than one on each method. Why? For performance reasons and to allow rolling back the entire session, rather than just a method. At least that's why I remember him saying.

So I refactored and implemented the Open Session in View pattern in conjunction with the Thread Local Session. You can checkout my ActionFilter and ServiceLocator for the View and ThreadLocal, respectively.

The problem now is that I pass my the Session object from my View -> Business Layer [example: UserManager] -> DAO Layer. So I'm tightly coupled with Hibernate, which I don't mind, because I really, really like Hibernate and have no plans to implement an alternate DAO (even though the architecture allows it). Even if I did choose to implement a new plain ol' JDBC DAO Layer, I can always get a java.sql.Connection from the Session using ses.connection(). Another option I've thought of is to just pass the ServiceLocator between the different layers, and call ses.currentSession() or ses.connection() when it's needed. But that seems to be the same thing I was doing before when I was opening/closing at the method level.

Comments and suggestions, as always, are welcomed and encouraged.

Posted in Java at Jun 11 2003, 02:12:31 PM MDT 8 Comments
Comments:

Well, you could encapsulate your data access using the Command pattern. At least that would get Hibernate out of your method signatures. I chose to implement a persistence layer with DAO's. No reference to Hibernate sessions leaves that layer. My DAOFactory creates DAO's and hands each new DAO a ThreadLocal Hibernate session to do its work.

Posted by Jason Boutwell on June 11, 2003 at 08:47 PM MDT #

This still doesn't help map a users "action" to a Hibernate Session. You want to be able to treat each action on the part of the user as an atom, no?

Posted by Adam Sherman on June 11, 2003 at 09:54 PM MDT #

Well, that much I did realize :) (I like Hibernate a lot too), so I guess the only question left is - since you are instantiating the UserManagerImpl in the Business Delegates (e.g. UserManager) in Struts-Resume, why can't you just make a UserManagerImpl(Session s) constructor, rather than desecrating the interface API, and tying it to the interface API signature. I think that's a helluva lot cleaner :). And inside the Impl class, have a private instance Session var to which you will assign the Session and use it for the entire transaction. Or have a JDBC "Connection" constructor, and just pass in a connection if you're a JDBC junkie and you can afford to handcode JDBC for your project... Makes more sense, no? :) So your UserManager interface becomes:

public interface UserManager {
public UserForm getUser(String username) throws Exception;
public ArrayList getUsers(UserForm userForm) throws Exception;
public UserForm saveUser(UserForm userForm) throws Exception;
public void removeUser(UserForm userForm) throws Exception;
}

And then for each type of UserManagerImpl, you'd have a constructor like:

public class UserManagerImpl implements UserManager {
...
private Session session;

UserManagerImpl(Session session) {
    this.session = session;
}
...
rest of API implemented
}

And then for a JDBC based UserManagerImpl, you'd have

import java.sql.Connection;

public class UserManagerImpl implements UserManager {
...
private Connection conn;

UserManagerImpl(Connection conn) {
    this.conn = conn;
}
...
rest of API implemented
}

Now everyone's happy because they can use either a Hibernate implementation or handcoded JDBC implementation (or EJB, if you're really perverted ;), and the interface API signatures are clean, that is, not tied to any particular persistence layer.

:)
Martin

Posted by Martin Naskovski on June 11, 2003 at 10:03 PM MDT #

Your timing is impecible! I was just beginning to have issues with this in Hibernate and sure enough, you are blogging about it. I feel it is going to become a major design issue for Struts/Hibernate users and I hope that we can work a nice example in struts-resume to follow. My issue began when I got lazy initialization failures because my session was closed by the time I got to the view. I will be checking out these suggestions and see if I can get it all working without opening and closing sessions profusely.

Posted by Dan Allen on June 12, 2003 at 06:00 PM MDT #

I too have recently tackled this very problem. I went one step further with this after coming to the realisation that *any* OR/JDO/JDBC/XML data persistence mechanism will require some kind of 'connection' object/configuration/JNDI ref/etc passed into the *ManagerImpl class.

I have simply put something like this into my *Manager :

UserManagerImpl(Object connection)

{ userDAO = daoFactory.createUserDAO(connection) }

Don't quote me on the above code as its from memory and its very late here. If anyone's interested I can paste the relevent code onto my blog tomorrow.

Posted by Pratik Patel on June 12, 2003 at 10:26 PM MDT #

I found Gavin's original e-mail. Adding it here seems appropriate:

> Hi Matt,
> 
> I've just been having a look over stuts-resume because I'm 
> looking for a nice example application using Struts to give 
> to a bunch of grad developers we have coming on board real 
> soon here at here at Expert. I think you struts-resume looks 
> absolutely perfect as a starting point for MVC development. 
> When is your book coming out?
> 
> However, I had just one technical quibble. Your persistence 
> code starts and ends a transaction / Hibernate Session in 
> every DAO method. I would have thought that 
> transaction/session management should be done in a layer 
> *above* the DAOs, so that we can group together multiple 
> calls to the DAO in the same Session/transaction. It seems 
> that you would end up with DAOs were much coarser-grained 
> than usual, and would contain all the business logic for a 
> transaction *inside* the DAO, instead of in a "Command" that 
> calls the DAO.
> 
> I usually split things as follows:
> 
> Action = pageflow logic / session management
> CommandHandler = framework object that manages 
> exceptions/sessions/transactions 
> Command = business logic 
> DAO = persistence logic (no exception handling/session 
> management/transaction management)
> 
> Now, that is probably slightly too heavyweight for this 
> example app, so perhaps you could do the stuff that my 
> CommandHandler does in an Action superclass.
> 
> I'm interested in your thoughts on this.... 
> 
> peace....
> Gavin King

Posted by Matt Raible on June 13, 2003 at 12:01 PM MDT #

I struggled with this for a while. To use OSIV or to use a session facade keeping the persistence layer in the backend, where I feel it should be and using old school transfer objects. I went the session facade route with transfer objects and Im glad I did. I have clean separation from the view and model, the backend can reside on any number of backend app servers while the view can reside on small footprint web servers that 'plugin' to the backend. I use DTO's between the persistence layer and controller to view, so I am never cursed with lazy iniitialization. I know what I need up front and the persistence layer prepares the DTO's with the data thats required. Also, with front end toolkits such as GWT, OSIV will not work and GWT demands transfer objects. Big question is: does it scale? Sure does. Right now we have 8 web servers that are load balanced that plugin to two load balanced backends. If we start getting bottlenecks, its just a matter of scaling the correct tier either horizontally or vertically, and voila. New power added. for XA demaracation, we can roll back an entire transaction due to an exception on the *backend*. An exception in the view should not cause a backend transaction to fail, no? lets say I want to send the user an email upon registration, this involves two txns, one for a fire and forget message to a queue which will be consumed by a bean thats responsible for sending emails and one transaction to the db to update some flags. if this XA txn makes it, but theres an exception in a view, I certainly do not want to roll back the back end !! And Gavin, although as smart as he is, is just human. He bleeds like the rest of us.

Posted by billy vandory on June 18, 2010 at 09:13 PM MDT #

Pratick, while you are correct that any DAO needs a resource to persist the data, instead of passing, injection is the way to go. I was late jumping on the IOC bus, because I am old and stubborn, but IOC is actually something that has rejeuvenated my joy in coding. Being in the IT industry for 22 years, having developed some of the late bbs technology and porting it to the InterWeb (Jtalk, Dax, Sasha, to name a few), IOC is really exciting. Some of the new coders who started out with Spring may raise an eyebrow asking "IOC rocks, well, what other way is there?" haha. Let me say two words: Space Invaders

Posted by billy vandory on June 18, 2010 at 09:18 PM MDT #

Post a Comment:
  • HTML Syntax: Allowed