EJB Revisionist History… and a look forward

Floyd Marinescu has blogged about the history of EJB, which I find somewhat fascinating because in it, he makes the same common mistake that most EJB developers made when they first started working with it.

    I speak at conferences fairly often, and at some point during a talk I will ask the audience how many have used EJB. Usually, 90% put up their hand. Then I ask them, how many of you have used EJB as distributed objects, meaning, where you have a separate physical tier for your business logic and a separate tier for your presentation (servlets/jsp) tier? Usually only 15% of the 90% will put up their hand. These results have been consistent at conference I’ve spoken at in North America, Europe, and Japan. The result still never ceases to amaze me, since EJB was designed to be a distributed object framework, for use on large-scale systems, but most of the audience was using it as a local framework for their small – medium sized web apps.

Unfortunately, Floyd seems to have fallen into the same trap that everybody else did back then, which was to assume that since EJB built itself on top of RMI (or so it seemed), then EJB must essentially be a distributed object framework just as RMI was, just as CORBA was before it, just as DCOM was over in the Microsoft space.

The EJB specification, however, spent very little time talking about distributed objects, even as far back as the 1.0 specification. Instead, it spent most of its time, as it does today, talking about transactional behavior of session beans and entity beans (not to mention making vague and nonsensical promises about O/R mapping that eventually didn’t hold up in practice). If you look at EJB and compare it to most traditional Transaction Processing systems and then compare it to a distributed object toolkit like RMI, the relationship becomes much much more clear: EJB isn’t really about objects at all (just as COM+ isn’t really about objects, either), but about building scalable procedurally-oriented systems that happened to be wrapped into something vague resembling an object (largely because Java is an object-oriented system).

Floyd points out that lots of companies used EJB for small- to medium-sized projects, and this was true: lots of companies did largely because the Java vendors made it VERY clear that not doing EJB was the First Sign of the Apocalypse, and that if you wanted to Do The Right Thing in Java, you did EJB. (Failure to do EJB was tantamount to pasting an upside-down pentagram on your forehead… or putting a "COM is Love" sticker on your notebook, one of the two.)

He goes on to boil EJB essentially down to three things:

        Framework benefits? At the time, if you were doing any kind of web or enterprise development, you were living in a proprietary, confusing world, or you were using the nuts and bolts tools like RMI, Servlets, etc, and creating your own frameworks. Couple that with the fact that during the dot com boom, most software developers were new, attracted by the dot come boom – the industry was just waiting to be given a standard, agreed upon way to do enterprise development. EJB provided that – a standard framework for doing transactions, Security, stateful components, etc. Having a standard "framework" solved a real and present need – there was no open source movement, no web frameworks, etc.
        Distribution benefits ? EJB standardized a programming model and platform for building business logic with distributed objects. Hot on the heels of RMI and Corba, this too was needed. If you wanted to do distributed objects, EJB was the answer.
        Component Benefits – This is where things got nutty. In my opinion, Sun was reacting to the success of the Visual Basic component market and dreamed of having a similarly active market in the area of Java business components. You all remember all the component re-use retoric, and attempts at building online marketplaces for EJB components. As a result, EJB gained a lot of weight in the API’s, deployment and package semantics in order to have EJB components run consistently well across appservers. If it were not for the component aspect of it, wouldn’t EJB have been designed more like the modern POJO framework to begin with?

In response:

    Framework benefits. Frankly, EJB was created and shoved upon the Java developers largely because Sun desperately wanted an answer to Microsoft’s MTS, which was seen as "the" successor to TP systems in the "modern" era. It was widely believed that if Sun didn’t have a logical successor in this space, Microsoft would take home the majority of the large enterprise systems. As it turned out, neither really displaced any existing systems, but did claim new projects.
    Distribution benefits. A good distributed object model is a contradiction in terms, and anyone who’d done CORBA or RMI (or DCOM or OSF RPC, for that matter) knew this; Peter Deutsch created his "Fallacies of Distributed Systems" list, and Waldo and Wollrath wrote their "A Note on Distributed Computing" paper as far back as 1994. Unfortunately, the hordes of programmers who took up EJB never heard either of these items, and the vendors who pushed EJB were not about to tell them that creating fine-grained objects with fine-grained methods was a Really Bad Idea. It still is, and this is principally a factoid that most object purists would like to avoid, because it forces them to face up to the fact that objects are NOT the silver bullet.
    Component benefits. Yes, Sun got nutty, looking at the wild success of components in the VB space, but hey, so did everybody else, including Microsoft. (MTS "component markets" were going to spring up ANY day now.) But frankly, Sun never really "got" the power of components that COM actually provided, and this is an oversight that continues to plague them to this day–this lack of isolation is what leads Java containers to have to rely on ClassLoaders to provide isolation between components (or modules, or whatever you care to call them in the JEE space), and clearly that’s not been the best decision Sun ever made.

What bothers me more than anything, though, is this immediate assumption that POJOs are inherently better as a design approach, and that smacks of distributed objects again, with all of the inherent problems that go with it. I know, ranting against POJOs is like saying "Martin Fowler’s an idiot" (he’s not). But let’s be honest here, folks–Fowler never suggested that POJOs should be the next big distribution model. In fact, it was Fowler who said that distributed object models "suck like an inverted hurricane". (Bonus points to anybody who can identify where that quote came from.) POJOs will lead people to do "proper" object design, which flies entirely contrary to "proper" distribution design, so let’s just bite the bullet, and recognize that objects inside a process are good, objects across processes are Bad.

Floyd goes on, taking a look at these three axes in current tools:

    Framework – Now we have open source frameworks that provide transactionality, pooling, security, and all the other good programming model benefits of EJB. Tools like XDoclet, Spring, and methodologies such as AOP are bringing all the framework benefits of EJB to lighter weight environments. JBoss was an important innovator here as well.

JBoss didn’t really innovate anything, they just took an interesting age-old design pattern (Interception) and built a container around it. (Funny how the fact that MTS/COM+ did this too, yet that wasn’t "innovation", that was "proprietary lock-in".) But this is just a nit; for the most part, he’s right on this part.

    Distribution – RMI is no longer the defacto standard for distribution. Web services are now being touted as a way to do distribution, many frameworks for doing WS over POJO’s were maturing. In addition, other remoting protocols such as Hessian were picking up steam.

WS as a tool for doing distributed objects is entirely missing the point of Web services, and frankly anybody who tries to use WS-* tools as a replacement for RMI is going to end up in a world of hurt. The object-hierarchical impedence mismatch is just too large to overcome, just as the object-relational one is. RMI remains the central non-WS distribution protocol, whether it goes over JRMP or IIOP.

    Components ? Who cares? The Enterprise Component Market is dead. When Sun was eyeing the success of the VB market, they failed to notice that that marketplace consisted mostly of UI widgets and "utility" type components that are re-useable across projects. We did not see things like payroll classes or the notion of a "user" captured as a VP component. The fact is, business logic is generally not re-useable across projects, and so the market discovered, and so all the weight added to EJB was not necessary. Come on people, do you REALLY NEED binary compatibility between EJB-JARs on appservers? How often did you deploy EJB’s from one component into your project by deploying the already compiled JARS? I can’t remember hearing of a case, what was common was simply adding the EJB source to your build and packaging it at build time. If building re-useable components were not an objective of the EJB 3 team, perhaps we would have had the equivalent of EJB 3 back in 2001.

So close… and yet so far, far away. We need components NOT as a means to allow code to "port" between containers, but as an isolation barrier between your code and mine and the next guy’s. In a distributed system, we want to remain loosely coupled across layers because we’re never really going to revise all layers at once except in the smallest systems (which probably didn’t need the separation anyway, then). More importantly, the "weight" of EJB is not in the API itself, but in the implementations the vendors sold us. Where was the lightweight EJB container that runs in-process, a la COM+? Turns out, there is one, an open-source one, from Exolab (OpenEJB), and it works pretty good at doing unit testing of EJB components–at least as well as unit-testing your servlet/JSP code works, anyway. The worst part of all this, though, is that Floyd misses out on the absolute number one requirement of making EJB look like EJB 3 is being proposed to look: annotations, which Sun simply didn’t recognize the need for at the time. (You can’t blame Sun, really–it’s something that most everybody didn’t see a need for until .NET came out and we could see how it greatly simplified the situation.) No annotations, then no EJB 3. The rest of EJB 3–the "common-sense defaults", for example–really isn’t all that impressive.

Floyd continues:

    Now, bringing the survey question I started off this blog with back into perspective, notice that the majority of people were NOT using EJB for it’s component benefits, or it’s distribution benefits. The majority of people were using it for it’s framework benefits, and those benefits were better served by light weight open source. In 2003, I think the only real value proposiiton EJB brought to the table was it’s use as a distributed object framework, for real large scale systems, which was where it was originally intended to be used to begin with. Thus, as I would tell the audience at th talk: "you’ve all misused EJB".

Well… yes, they’ve misused EJB, but largely because they were looking to design distributed objects. Distributed objects do not scale, period. If you choose to design your distributed object model around service-oriented principles (as EJB does), then you can scale, but how much OO-ness are you giving up in turn? If you write classes with one big method that drives everything, are you still doing OO?

    So where are we today? Well, I have to applaud Sun and the EJB expert group and all the vendors that support EJB. They made the hard choice, and acknowledged that the community really wants a standard framework for doing business logic in objects, with ORM instead of persistent components, and that is the direction that the expert group is taking. Why is this worthy of applause? Because Sun and the vendors are taking a risk in supporting this new lightweight EJB, they are risking their own revenue models by standardizing what is already widely being used in the open source world. They will NOT be able to compte on the programming model alone (and they know this), it will have to be their "transparent middleware" services, such as clustering, XA, management and monitoring, etc.

The hard choice is to realize that EJB’s "heavyweight" or "lightweight" factor isn’t in the API at all, but in the implementation of that API. And frankly, the big vendors have ALWAYS competed, at least with one another, on their "transparent middleware" services. That story doesn’t change.

What DOES change is that the Java community has come to recognize that not every project needs EJB, and now the vendors need to figure out how to tailor their containers to address the needs of smaller projects. Spring did that, successfully, and now we need to see a vendor-supported world where either Spring goes into the JSR process to become part of the JEE space, or else the containers start looking into hosting more than just "transactional processors", which they’re also doing. JBI is ripe for inclusion, if not outright merger, with EJB, to create a "generic Java component container", and we should probably just accept that a servlet container and EJB container really aren’t that far apart from one another to begin with, and just unify the two.

The secret sauce in the Java space–as with any middleware space right now–is in the container/component relationships. The sooner we unify that space and create a coherent story around it, rather than creating lots of specifications that fundamentally do the same thing, the better off we’ll all be in the Java space.


Good tips, JZ

Just got the latest "Core Java Technologies" Technical Tips email, and in it are two interesting little tidbits:

    Three Swing "Urban Legends":
        "Create threads for long tasks from the event dispatch thread." Problem is, as it turns out, the event thread runs at a higher priority than normal, so threads spun from the event thread also run at a higher priority level. Set them back to NORM_PRIORITY before starting them.
        "Use SwingUtilities for running tasks on the event dispatch thread." Turns out that SwingUtilities is just a wrapper around EventQueue, so just use those methods directly.
        "Synchronize methods for synchronization." Turns out that synchronizing on the method is dangerous for AWT Components, so prefer to use an internal lock object instead.
    From Runtime.exec() to ProcessBuilder: Stop using Runtime.exec() (which was always problematic anyway), and start using ProcessBuilder instead, which gives you more control over the launch, environment, and reading/writing to the stdout/stderr/stdin streams anyway.

It’s been a long time since I saw tidbits in here that weren’t rehashes of existing documentation, so kudos to John Zukowski, the author of the Tips!