Thursday, July 22, 2010

Java "Enterprise" tools: every problem half-solved with twice the required complexity

The more I work with Java, the more I feel like it's a great core language surrounded by endless onion-like layers of increasingly awful frameworks and tools.

The Netbeans platform. JPA2. Hibernate / OpenJPA / EclipseLink / Swing. EJB3. OSGi. With tools like those, you'd think that a simple task like writing a business database application would be easy, right?

Ha! You spend so much time working around problems created by these tools' solutions to other problems that you're lucky to get any actual work done on your app.

Java is like a variant of the game of Tetris in which none of the pieces can fill gaps created by the other pieces, so all you can do is pile them up endlessly. -- Steve Yegge (2007, Codes Worst Enemy)

Examples demonstrating the use of JPA, Hibernate, etc are full of assumptions and limitations that render them useful only for utterly trivial toy projects. For tools that're touted as making it easy to build "scalable" apps, I find this interesting. One Hibernate+JSF tutorial, for example, writes:

One of JCatalog's assumptions is that no more than 500 products are in the catalog. All product information can fit into the user session.

We're building an Enterprise Application with n-teir Enterprise Architecture ... that's limited to many fewer items tracked than there are lines of code in the project. Does this seem off to you? If it's so easy to build scalable data access with Hibernate, why isn't it done in demoes and tutorials? My own experience suggests that's because it's not actually at all easy, it's painful and complex if possible at all.

This post expresses much of what I'm trying to say below, and expresses it much, much better than I can.

I should've just stuck to JDBC and core Java + Swing. Not that Swing is exactly nice, as its event-driven single-threaded design combined with rather less than event-driven models requires some complex thread-juggling to maintain a reliable, responsive app. Maybe just learned Ruby+Rails, PHP, or done it as a simple Python webapp. I'd be done in no time, with none of the stupidity involved in fighting the JPA to make it do what you need. My productivity in terms of real, usable application code produced has gone down to near-zero with these tools. There are endless demos on how great these tools all are (most of which demonstrate tiny toy apps with hopeless limitations) but there's no information out there on how to solve the problems with their real-world use and get a usable app going with them. See, eg:

Creating a CRUD netbeans application, which produces a completely useless toy app that fails to solve any of the interesting problems with desktop DB apps, like handling DB disconnects, 'net connection loss, latency, limited bandwidth, etc while maintaining a responsive and well behaved UI. I know, let's sweep those problems under the rug and pretend they don't exist! For just how complex some of these problems are, see this excellent article on using JPA with Swing.

For others considering combining these technologies: JPA is designed for the server-side world, where it lives in an application server with reliable low-latency access to the database and a pool of identical connections available to it. It claims to let you write database-transparent code that works with database entities as normal Java objects, largely taking care of the persistence of these objects for you. It offers transaction management features and is theoretically very nice to use.

On the server. Well, sometimes it's fine on the server, sometimes a horrifying train wreck of multi-layered duplicate code and copying that's in true Enterprise Application style.

Don't expect easy use of native database types, easy type mapping and translation (think: emulating boolean in crap databases that don't support it), though.

As for desktop and simple 2-teir apps: People will say JPA can work happily in desktop apps, but I suspect these people haven't written real desktop apps with it, or they're into over-abstraction, pain, and "Enterprise-y" design. You know, where you spend twice as long building the tools to build the tools to build the frameworks to control the enterprise architecture to model the modules that eventually contain some actual useful application-domain code as you do writing the code that does the work your application is for. Either that, or they think that having their app appear to crash/hang for long periods when the user's wifi drops, they go out of 3G cellular range, etc is OK. They also have no problem with transferring 1000x as much data is needed or making 100x as many database round trips as required so the app is incredibly, glacially slow on high latency connections.

Why is JPA so dreadful for desktop apps? For just one reason, see my previous post on issues with the interaction of JPA lazy fetching with the need to keep the EDT from blocking in Swing.

What it all comes down to is that your app's code really all does have to be aware of the database. It has to be aware that database access can be slow, can time out, and requires user feedback. It has to figure out what it'll need to know in advance and fetch that information in efficient batches. It has to selectively retrieve only what information it needs, and do so without having to call back to the database continuously to get information it missed. This is unavoidably hard to do, and trying to hide it from the app like JPA does makes it much harder, not easier, to get right.

Overall, my personal experience with JPA/Hibernate and friends like EclipseLink and TopLink Essentials has been that they're absolute productivity killers. They seem great at first brush, but the more you work with them the more you realise they're a clumsy solution and create more problems than they solve.

Hibernate and co can make deleting an object from a database into a complicated operation where you stare at inter-entity cascades until you're half blind.

Even the experts can't get it right. The NetBeans IDE generates rather broken JPA mappings by default, which can't even be used to remove an entity until they're fixed. Lest you think it's my UI code, I'm using an IDE-generated JSF2 interface too, and haven't typed a line of code in this project. Pity it doesn't work.

So: If you're going to use the NetBeans Platform or any Swing app, think very carefully about whether it's a good idea to use JPA, and understand the issues nobody likes to talk about. For that matter, think carefully about it if you're building a webapp too - you might well be better off with something like iBatis/MyBatis.

With Enterprise Java in general you'll get very used to this feeling:

Whenever I write code in Java I feel like I'm filling out endless forms in triplicate. -- Joe Marshall (aka jrm)

Quotes from here. Some of the later ones ring really, really true of "modern" Java development, where frameworks are stacked on frameworks to the point where you can't even see your own code anymore.

No comments:

Post a Comment