Wednesday, December 19, 2007

Refactoring from EJB's to Spring & Hibernate, part I

As part of our infrastructure we have some "legacy" EJB applications. As usual these are slow, hard to test, hard to maintain, etc etc. As a result we'd like to refactor them to use Spring/Hibernate. One of these applications is a proprietary monster that it's easier to throw away and rewrite (one of the few occasions where I will agree to the rewrite over refactor path, it's that bad!!), the other two are prime candidates for refactoring: we own the source and we control their lifecycle.

I hope to post a few more articles on our experiences as we go along, but in the meantime here's some reading on other peoples experiences:

First, lets review EJB's, the why and wherefore..

Example with a single entity application:

High-level overview of the process :

Story of migrating a large application:

debugging SQL statements from EJB's

EJB's...(sigh!) I don't know what the ejb community was thinking when they went off onto this tangent. Granted that in the narrow domain of systems that genuinely need distributed transactions and tiers, and compared to the alternatives at the time for transaction management & ORM (CORBA & nothing), EJB was good.
It could have been a lot better if not for standard-itis and if SUN had thought for 5 minutes about what most applications need (instead of how they could cash in), but it (++sh) happens. The problem then was every man and his dog j2ee developer going off and architecting systems with no distributed requirements at all with full-blown EJB architecture and every J2ee pattern in the catalogue. Enter the current breed of "legacy" applications less than ten years old...

Anyway, if you are in the situation of wanting a non-proprietary way to see what SQL the container is producing on your behalf, then you're in trouble, it's not as easy as saying show_sql=true.

Having just dug around on this topic, here's my two cents:
1) use Log4JDBC
this is really the premier solution, Log4jdbc wraps your jdbc driver transparently, and you can fully configure the logging via standard log4j xml. The caveat with this method is that you need to keep in mind that the JDBC driver will be loaded in to a different ClassLoader than your application, and you need to be aware of this because it can cause some strange errors otherwise.
The basic idea with log4j is to replace all references in your config (you don't configure your Datasources in code, do you?) to your JDBC driver with the log4jdbc driver, and prepend the jdbc url with "jdbc:log4". then configure your logging and you're away!
This method is preferred, but can take a bit of configuring and hacking if you're many levels removed from the DriverManager, eg - in a managed environment.

2) The retarded cousin...
decompile your JDBC driver with JAD or similar, then *manually* add in logging statements to print SQL and parameters, then replace your existing driver with this hack version. This is an ugly hack and should only be used in the absolute last resort where all else has failed.

Ideally *any* SQL abstraction should allow the printing of the SQL it generates as it executes, to allow debugging and profiling, but unfortunately it's not always possible.

Java Sizeof() & sessions

I've just been doing some stuff to optimise our infrastructure to stop it calling an external ejb 6 times per request, which I fixed by sticking stuff in the session. there's similar problems in other places in our app and I was thinking about sticking them in the session as well, but then the issues of session size/scalability & stale data stopped me.
long story short, I found some interesting stuff on reinventing the sizeof operator for java. in C you use it all the time, but in java such a thing doesn't exist. Now, you could go and profile your application, but that usually takes a bit of setting up, and if you want to instrument your app in production then it doesn't really work so good.
Anyhoo, here's three interesting links on the topic of figuring out how big objects in java are in general, and session size in particular:
[1] how big are primitives? brute force approach, useful for boot-strapping
[2] Article developing the issue and source of tool to get a good (approximate) idea of the size of an arbitrary rooted graph.
[3] Java web parts helper class to determine size of your session

and we're back...!

Ok I haven't posted for awhile, it's been pretty hectic with the new job. I've got a few posts in draft mode that I haven't had the chance to get to a point where I could publish them. They're coming, but in the meantime there's a few interesting thoughts that I thought I'd put up, so there may be some posts out-of-order coming up. ah well!