Friday, August 20, 2010

The evil debugger



Let's take a look at the following piece of C# code:





1:  using System; 
2:  using System.Collections.Generic; 
3:  using System.Linq; 
4:  using System.Text; 

5:  namespace ConsoleApplication1 { 
6:    class Program { 
7:      private string myString = null; 
8:      public string MyString { 
9:        get { 
10:          if (myString == null) { 
11:            myString = "Bad string"; 
12:          } 
13:          return myString; 
14:        } 
15:        set { 
16:          if (myString == null) { 
17:            myString = value; 
18:          } 
19:        } 
20:      } 
21:      public override string ToString() { 
22:        return MyString; 
23:      } 
24:      static void Main(string[] args) { 
25:        Program program = new Program(); 
26:        program.MyString = "Good string"; 
27:        Console.WriteLine(program); 
28:      } 
29:    } 
30:  }  


The result, as you would expect should be "Good string" written to the console. That is, when you run it from the command line.
Suppose I run it in Visual Studio .NET 2008 and I put a breakpoint at line 27 in the debugger. Then I debug the program, I reach line 27, I move to line 28 and the result is of course "Good string".
Let's put a breakpoint at line 26. You'd say "what does the breakpoint have to do with the result ?" Well, it does, because in this case, "Bad string" will be displayed. This is like Heisenberg principle (or the observer effect), isn't it ? When we debug, we actually influence the result. This is possible because when the breakpoint is set at line 26, MyString getter is executed and in effect myString is set to "Bad string". After that trying to set myString to "Good string" can't succeed because in the setter the test (myString == null) is false. At line 27 ToString() is called, displaying of course "Bad string".

The default behavior of the debugger in Visual Studio .NET 2008 is to evaluate the properties when the debugger hits them. Also, the ToString() method is called by default whenever you hover with the mouse pointer over an instance (like "program" in line 26).
You can disable these behaviors under Tools -> Options -> Debugging -> General.

It's good to know this, because as you can see, .NET properties and ToString() evaluation in VS.NET can give you lots of headaches.


Sunday, August 15, 2010

Hibernate: OpenSessionInView reloaded

In the previous post regarding Hibernate, I've shown how the OpenSessionInView pattern can be implemented.
In short, the idea was that the transactional statements (CRUD operations with the database) happen in between the following lines:

sf.getCurrentSession().beginTransaction();
....
sf.getCurrentSession().getTransaction().commit();

These lines are executed by a servlet filter, making thus sure that the Hibernate session is kept open until the view is rendered, and thus allowing us to use managed entities, as opposed to detached.

However, there is still something about which we haven't talked yet: what happens in the real case, with several simultaneous requests to the servlet ? We know that servlets are multithreaded objects, i.e. multiple threads may call the servlet's methods at the same time. We also know that servlets are not thread safe, so we  have to pay attention to instance or class variables, which can be shared by several threads.

In the case of the OpenSessionPerView pattern, note that sf.getCurrentSession().beginTransaction() may be called by several threads. This means that the result of sf.getCurrentSession(), which is the current Session object, is shared among threads, which is dangerous since a Session is not a thread safe object. This asks for trouble, since the instance of Session is used to create queries and perform CRUD operations with the database.

So how can we ensure a thread-safe behavior of the OpenSessionPerView pattern ? ThreadLocal pattern to the rescue.
In a few words, what we need is a Session object per thread, which can be easily implemented using a ThreadLocal variable, as in the code below:

public class HibernateUtil {
    private static final SessionFactory sessionFactory;
    private static final ThreadLocal threadSession =
    new ThreadLocal();

    static {
      // initialize SessionFactory
      sessionFactory = new Configuration().configure().
      buildSessionFactory();
    }

    public static Session getSession() {
      Session s = (Session) threadSession.get();
      // open a new Session, if this thread has none yet
      try {
        if (s == null) {
          s = sessionFactory.openSession();
          threadSession.set(s);
        }
      } catch (HibernateException ex) {
        throw new InfrastructureException(ex);
      }
      return s;
    }

    public static void closeSession() {
      try {
        Session s = (Session) threadSession.get();
        threadSession.set(null);
        if (s != null && s.isOpen()) s.close();
      } catch (HibernateException ex) {
        throw new InfrastructureException(ex);
      }
    }
}

You get the picture. We would call HibernateUtil.getSession().getTransaction() in our servlet filter, instead of sf.getCurrentSession().beginTransaction(). Now each thread running through the servlet (and the filter) gets its own session object, so it performs the CRUD operations to the database without interfering with the other threads.