« June 2004 | Main | August 2004 »

July 27, 2004

Webpshere 4 Lock-In

Listen to this articleListen to this article

Lately I'd come to think of Websphere 4 as a steaming pile of crap but then the other day I read an article which changed my mind; Human waste is actually useful for something.

We have a an application that runs within the web container against a DB2 database. For development we use OrionServer which, sensibly, leaves the isolation level at READ_COMMITTED by default. For production we'll be using Websphere 4 which gives a default transaction isolation level of REPEATABLE_READ.

Sidebar: There are four basic transaction isolation levels:

  • READ_UNCOMMITTED - Let me read anything even if it's not been committed yet; Actually you should be committed for using this;
  • READ_COMMITTED - Only allow me to read stuff that's been committed; The sensible choice for the descerning developer;
  • REPEATABLE_READ - I want to lock every row I've read because somehow I think I might want to read the same stuff again with the exact same results in the exact same transaction; Also known as please Sir can I have a deadlock; and;
  • SERIALIZABLE - My users are nostalgic for the response times they enjoyed during the good old days of 1200/300 baud accoustic couplers.

Yay! Bring on those deadlocks. And the only way to change the isolation level in Websphere 4 is to deploy an EJB and specify the isolation level in the custom descriptor (I assume this is pretty common but no doubt not specified in the J2EE standard- anyone?). All very well and dandy IF YOU HAPPEN TO HAVE AN EJB FROM WHICH TO DO THIS!

breath...in...out

Unable to get Websphere to cooperate in any sensible fashion (no I don't count EJB's as sensible) we turn to the database. Ahh good old DB2 you old thing you..hey...hey...nudge nudge...wink wink. What can you do for us?

Bugger all that's what! Well, not quite. A good-old Google search reveals some interesting stuff. It seems I can go in and set a server-level parameter DB2_RR_TO_RS which basically says "hey mister DB2, if that Websphere kid comes around here asking for REPEATABLE_READ, just smile and say yes yes and send him blissfully on his way but don't actually do anything. ok?" Even more interesting, we found this solution right on IBMs website for their own Portal Server Software! And what do you know? It worked. No more deadlocks.

So that should be it right? Wrong! The problem with this little solution is two-fold: Firstly, it's at the server instance not dabase instance level so it affects EVERY database; and secondly; it's not a supported option in DB2 version 8.1 (works in 7.1) which we'll be using for production. Instead, 8.1 supports so-called Type 2 indexes which supposedly solve the same problem. The index solution seems a little fragile to me though. I bet my bottom dollar someone will add a new table and forget to add the appropriate indexes. BLAMMO!

Back to square one. We try every combination of locklists and maxlock parameters, you name it. None work and frankly although they would have decreased the likelyhood of deadlocks, they don't actually solve the underlying problem namely that that REPEATABLE_READ is a retarded default.

But what can we expect? I mean we aren't doing it the J2EE way. "Please Sir, can I have READ_COMMITTED" we feebly plead. "How can you have any READ_COMMITTED if you don't have any EJB's?" Websphere replies cruely.

In the end it looks like I'll need to dust off the old train book, wrap our Hibernate persistence stuff in a session bean and hopefully get back to doing some load testing.

Even after all that, compared with the performance of OrionServer, Websphere seems to mysteriously turn my P4 into a Casio wrist watch. Given the amount of CPU power required to run it, I think we're going to need to find alternative means of power.

Update: Having jadded the websphere code, it seems that the default isolation level for Sybase and Oracle is a more sensible READ_COMMITTED. That of course doesn't help us. It also turns out that once you've called an EJB, even a nop method, the database connection is then set to whatever isolation level was set for the EJB! Oh we're having fun!

July 03, 2004

IKVM

Listen to this articleListen to this article

As you're probably aware, some time ago I ported Simian to C# and ever since I've been maintaining two versions of the source code. This was becoming tiresome to say the least and recently I've been toying with installing VisualStudio.NET under VMWare to see if I can use J# instead. Not only did this idea urk me "just because", but the thought of installing anywhere up to 3GB worth of software that I would be forced to run under Windows just didn't impress me in the slightest.

If you're not up with the latest on mono you're probably unaware that the site has been overwhelmed for days now since the release of 1.0. Almost hidden within the distribution is IKVM.NET "an implementation of Java for Mono and the Microsoft .NET Framework." It includes the following components:

  • A Java Virtual Machine implemented in .NET
  • A .NET implementation of the Java class libraries
  • Tools that enable Java and .NET interoperability

So, having just recently emerged the latest packages under Gentoo, I figured what the heck, I'll give it go.

First off, I tried ikvm. It's like a java.exe replacement. Where I would usually run:

java -jar simian.jar

I can instead run:

ikvm -jar simian.jar

Which will run simian under the .Net framework instead. And it worked. My jar was happily running under .NET with no code changes! But it gets better. The next step was to try ikvmc the compiler. Yes you heard it, a "static compiler used to compile Java classes and jars into a .NET assembly." So I gave it a whirl:

ikvmc simian.jar

It read the Manifest and determined where my main method was, "converted" all my classes and spat out an executable: simian.exe. So I ran it and once again, it worked first time. It just blew me away! No need to convert to C#. No need to installed Gigabytes of wizard-ware and best of all, the tools run under linux as well as windows.

So for a bit of extra bandwidth required to download the supporting DLLs, I can finally ditch all that lovingly hand-crufted C# code and deliver on just about any platform you can imagine!

I can't vouch for it's suitability with regards to your project but it's definitely worth a look if only for it's pure geek value. I'm sure yet another layer of indirection is exactly what you architects out there have been looking for. Just think, you too could have a Java application running under IKVM under .NET under Windows under VMWare under Linux ;-P

July 02, 2004

Suite Memories

Listen to this articleListen to this article

One of the managers at the client I'm currently working for observed that I hadn't blogged quite so much recently as in the past and wondered if I was, perhaps, suffering blogstipation. But today I received a good dose of editorial cod-liver oil.

I mentioned some time ago our success in speeding the build with respect to JUnit execution times. That has worked sensationally well for us for some time now. Unfortunately, as more and more tests were added we started getting OutOfMemoryErrors forcing us to generate multiple suites which in turn slowed the build.

Our short term solution was to stop instrumenting the build. This bought us some time but that was in no way considered a viable long-term solution. So finally today, after much distruption to the cruise build, we decided to get to the bottom of it. We already knew that JRules classes have some quirky behaviour that meant special care was needed to ensure it can free all working memory before being garbage collected. So we took a punt and looked at the tests involving rules.

On inspection, it did indeed look as if we had forgotten to clean up. Voila! No more memory errors. But then something struck me. I had just recently implemeted a solution to this for our mainline code for this very problem that ensured we were cleaning up in the finalize method of the same class we were using in our tests. This implied there was something else going on. Something most peculiar.

Unconvinced we had found the real cause of the problem, we decided to back-out the change and try something else. This time we made sure that the objects being used were candidates for garbage collection by explicitly setting the instance variables to null in the tearDown() method. We ran the tests again and bingo! Problem solved. But hang on a second. Surely the test classes themselves are being garbage collected? Surely clearing the instance variable was redundant?

A bit of digging around and we were soon scruitinising the JUnit TestSuite source code. And most fascinating reading it was too. Right there in plain Java for all the world to see: A Vector (how Java 1.1); a constructor that creates and stores (in said Vector) an instance of the test class for each test method it finds; and; a run method that simply iterates over an Enumeration of the instances, running each one in turn.

No wonder we were running out of memory! The bloody test class instances, all 2000+ of them, and the data they were holding on to were never released until the suite had finished.

A bit of decoration and a custom test suite class later and it's bye bye to our OutOfMemoryErrors. I wonder what the next gotcha will be?