lysergicjava

oh, technology

Menu Close

Month: July 2008

Knocking back Hibernate (cleanse your objects!)

Sometimes, you realize you’ve stumbled into a hard problem, and you start to feel bad.  Then you search around for a while and see that other people, some of them quite smart, have the same problem.  Then you feel better.

This happened to me lately: I encountered the dreaded Hibernate cruft.

As others have discovered, Hibernate’s slick trickery at runtime can cause headaches.  Specifically, when Hibernate wraps a CGLib proxy around your POJO and you send said proxy off to XStream for serialization to XML, you end up serializing stuff you didn’t intend.

See, XStream, slick as it is, depends heavily on reflection.  Commonly, you annotate your POJOs so XStream knows exactly how to serialize them.  But if Hibernate has substituted a proxy with additional fields, or swapped out a java.util.list for a org.hibernate.PersistentBag, XStream just shrugs and tries its best… without your carefully thought-through annotations.

So, what you really need is to cleanse an object fetched from a Hibernate session of all Hibernate artifacts.  There’s been much gnashing of teeth over lazy fetching and incomplete object graphs, but all it boils down to is that you’ve got to make sure your objects are in a good-enough state to serialize before you try.  Either make the calls to fetch the desired linked objects, or live with the consequences.

Anyway, cleansing the object: turns out it’s more work than I thought originally.  Well, there’s really two approaches.  The first approach is to just create a new POJO and traverse the proxy, explicitly setting the POJO values you want.  A factory method could do this.  And for a small number of POJOs, with just a small handful of fields and/or very shallow graphs, this would be fine.  But…

I’ve got a gangload of POJOs, with complex and deep graphs.  I want more of a once-and-for-all solution.  I opted for reflection after reading this post about the performance of reflection in deep cloning.

Here’s what I’m doing: I’ve taken Matt Hick’s approach of deep cloning using reflection, and added methods that filter out Hibernate specific stuff and swap back in what you started with.  A key part:

private static Map<Class, Class> hibernateCollectionsMap = new HashMap<Class, Class>();
static
{
   hibernateCollectionsMap.put(PersistentBag.class, ArrayList.class);
   hibernateCollectionsMap.put(PersistentList.class, ArrayList.class);
   hibernateCollectionsMap.put(PersistentMap.class, HashMap.class);
   hibernateCollectionsMap.put(PersistentSet.class, HashSet.class);
   hibernateCollectionsMap.put(PersistentSortedMap.class, SortedMap.class);
   hibernateCollectionsMap.put(PersistentSortedSet.class, SortedSet.class);
}

…which is used to map Hibernate proxy collections back to the java collections they once were.  I also turn java.sql.Timestamps back into java.util.Dates.  You can just kill that if you wanted sql Timestamps in the first place.

This whole exercise got me thinking.  With more work I could craft an entire toolchain, complete with XML config files and the like, that would allow anyone, anywhere to sanitize a Hibernate-fetch object graph.  But this would be total overkill, and anyway, at some point Hibernate will probably do this for you.

I decided to keep it simple, and handle the vast majority of the cases I’m going to encounter, and let the rest of the world take care of itself.  Feel free to take the code and tweak it to your heart’s content.  Special thanks to Matt Hicks for his deep-clone approach and his ClassUtilities which I made use of.

Download my code here.

Desultory thoughts on the Spring framework

All I really remember feeling when I first encountered Spring (in 2005) was confusion.  Hip leet Java hackers were gushing over it, and wanting to be seen as hip and leet myself, I wanted to be genuinely excited by it, but I just wasn’t.  Spring was designed from the start to be an IoC container, and IoC (while elegant) just isn’t excitement material, but that’s not the reason I was skeptical about Spring.  No, it was the highly touted silver bullet application of IoC called Dependency Injection that got me to thinking.

Specifically, thinking that I didn’t need it.

I’ve encountered a lot of problems with programming computers.  From my childhood hacking on Logo and BASIC on Apple ][s and Atari 400s to my professional life where I’ve done all kinds of crazy shit (I was even tasked once with installing an Oracle app suite onto a Sunfire server with one physical disk).  Along the way, I’ve encountered strange paradigms, nonexistent requirements, clueless users, impatient managers, cranky quirky tenured developers and their cranky quirky grandfathered-in piece-of-crap apps.  I’ve seen horrendous code, cryptic variable names, and surely-this-is-a-joke code snippets such as the following (yes, this was absolutely real):

if (val > 0 || val < 0)
   val=0;
else
{
}

(I guess someone really really wanted to set val equal to zero.)  Anyhoo, the point is, I’ve encountered a lot of problems in programming, and managing dependencies wasn’t among them.  Not once, not ever, do I recall thinking, “Damn!  There’s got to be a better way!”

Now, I’m not saying that IoC or DI are bad things.  They’re just unnecessary.  Nor am I saying there’s nothing to be concerned about whatsoever with dependency management.  It’s just not hard.  A Foo contains a Bar.  Foo instantiates a Bar and goes to town.  Most of the time, pushing that off to some framework seems like it’s more trouble than it’s worth.  The complexity hasn’t gone away, it’s just gone somewhere else.  When the framework requires lots of configuration via XML files, you’re most definitely robbing Peter to pay Paul.

“But wait!” say the enthusiasts.  “What if your implementation of Bar (gasp) changes? Dependency Injection is so helpful then.”  Right, because it encourages (though doesn’t demand) that you program against interfaces.  You could, I guess, do what every decent OO programmer has done (right…?) for the last decade and program to the interface as a general rule, but maybe that’s crazy talk.  Long story short: DI may very well solve a problem, but it’s a problem I’ve never had.

And it doesn’t solve it for free.  I’m not talking about any of those kvetchy cost-based objections to Spring like “it’s slow” (it isn’t) or “it takes too long to start up” (yeah, kinda, but how often are you restarting your app, man?) or (my favorite) “it takes up too much memory”.  No, I’m just saying that it’s one more chunk o’ expertise you need in your toolkit.  You need to be familiar not just with Java and J2EE and Tomcat and Struts and Hibernate and JBoss and Drools and JNDI and EJB and JMX and MVC and SQL and the whole alphabet soup of XML technologies but now you need to know about Spring, too.  I’m most certainly not against knowing things.  I like knowing things.  But having to know arbitrary things gets a little tiresome.

For all that, I do use Spring.  One, it makes no sense to be willfully ignorant of a common technology.  Two, it’s convenient at this point, and that’s what I mostly use it for.  If I’m building a Java web app (something I do frequently) then Spring allows me easy access to Hibernate (with annotation support and transaction management) and Acegi.  Bada-bing, bada-boom, I can get the basics up in no time, and do it in essentially the same way so I have consistency across projects.  In the long term, it’s a net gain.  But the gain comes from all those other people who poured a ton of work into Spring integrations (making it a de facto standardized Java sub-stack) not the time I “save” via the wonders of dependency injection.

YAGNI, part 1 (of 10,000)

So.  Here I am blogging with WordPress.  Eh, you ask?  A ready-to-use blog app?  Written in PHP?

What kind of software engineer doesn’t write his own blogging app?  Well, my kind of software engineer.  The kind that just wants to get something done. I’ve had it with the overly complex.  I’m dog-tired of reinventing the wheel, trying to correct every mistake (no matter how trivial), and in general doing far more work than is necessary.

Therefore, I am resolved to more-or-less do things the easy way from now on, and this blog — its implementation as well as its content — will be my sounding board.