Apr 292006

If you are using the new linux kernel (2.6.x) and remote debugging is slow, there was a change in the kernel that revealed a bug in the JDK with remote debugging. There is a fix thoug by running this command:

This changes the algorithm that breaks up TCP packets (if I recall correctly) and essentially makes sending a ton of tiny packets faster, which is the bug in the Java debugging architecture.

Apr 262006

Hibernate doesn’t fetch collections within a bean in the same session the beans were created in. If you need objects in those collections later on within that session, you had better put them in there. This even holds true when you go back to hibernate to refetch the same object instance. Here’s a quick example:

Once the session is closed out and the fetch is performed in a new session then this will work fine. I can see how this behavior protects the object instance somewhat, but this means that the instance also misses any updates within other threads to its associations. This I haven’t tested because it is a severe pain in the ass, but I’ll probably give it a try tomorrow.

As a quick closing thought, all this ORM stuff in Java seems like such a pain compared to Rails and ActiveRecord. I can understand that transactions can be quite powerful and the POJO model is powerful, but I’m not convinced that this truly makes life that much better as compared to what you gain from a dynamic language’s ability to handle all of the mapping internally and on the fly while making the class look like a simple data holder.

Apr 252006

Something else came up today with all this transaction and MySQL stuff. Looks like Hibernate updates do not work unless the session is participating in a transaction when using MySQL InnoDB Max with the default isolation level set to READ-COMMITTED or READ-UNCOMITTED. The tricky part is that inserts work fine but updates never get executed. If you tweak the code and add a transaction or use a Spring annotation or proxy to manage the transaction everything starts working quite nicely.

Apr 252006

I need to remember this, so I’ll post it.

Spring transaction (annotations or proxies) will join the current session, which is associated with the current thread of execution, if there is one or create a new session if there isn’t one. This is the default behavior. However, if you specify REQUIRES_NEW it creates a new Session for that particular method invocation, which also brings along a new transaction. This is expected, but I never really believe it until I sout the hell out of an application just to make certain.

Exceptions that get thrown will always rollback the transaction regardless of where it was started. This invalidates the session as well. The trick is to ensure that methods that could fail always start new transactions. The reason being that for the most part each request to a web application can reuse the same transaction for almost all operations. The only operations that fail are usually insert, update and delete operations, which should probably be wrapped in separate transactions to ensure that the outer transaction stays intact and usable during the entire request.

Apr 252006

Tony and I just got done with an 8 hour debug fest of our DB code. This was rather brutal and finally we ended up with a mess of souts (IJ users will know these as System.out.printlns) to track it down. The issue was that if I start a transaction and then call to another method or service that starts a separate transaction to insert some data, the original transaction won’t ever see that data.

At first we were thinking this was some hibernate magic that was caching negative selects or something, but using our trusty souts we found that the problem was at the JDBC connection level. We figured this out by printing out the hashCode of the JDBC connection objects as well as the hibernate session objects to see what Spring was doing with transactional boundaries.

Turns out that MySQL 5.x using InnoDB and Max by default sets the connections isolation level to REPEATABLE-READ! A repeatable read means that at the nanosecond the transaction is started MySQL in essence takes a snapshot of the entire database. Any select you perform will always return the same data no matter what other connections and transactions are doing to the database. This is great for super-uber-financial-debacle applications, but for our CRUDesque web app this is complete overkill. So, updating /etc/my.cnf to include a new transaction-isolation setting set to READ-COMMITTED fixes this nicely.