Ted replying to Rod replying to Don replying to Ted
October 5th, 2004On Don Box’s blog a few days ago, I tried to answer the question “Is Spring simpler than EJB.” Now it’s an odd kind of question, because Spring and EJB don’t aim to do quite the same thing, but it’s possible to answer it to some extent with respect to the overlap between the two. Ted Neward replied to my reply on his blog. I’m going to respond to some of Ted’s points today.
Spring is simpler than EJB mostly because they take a more POJO-based approach, but to some, that’s not simpler, that’s harder.
Well, “to some” the Earth is flat. In my experience, people who think that implementing at least 3 Java files for a business object is simpler than using a POJO (usually with an interface) are rare: the number I’ve come across who think that a non-POJO approach is simpler after actually trying both approaches is zero. Perhaps there’s a point here, but I don’t get it. (Maybe that explicit knowledge of transaction semantics and remoting is desirable?) I would really like to see some arguments as to why using a POJO-based approach can be harder.
How is Spring simpler than EJB? I can’t claim to give you an independent view, but given that I started from EJB and designed Spring with that experience in mind, I’m happy to compare the two. For a start, Spring (or any IoC + services framework) keeps the framework out of your code. That’s a huge difference with many implications. Any object can be made transactional etc without that object needing to jump through hoops as with EJB. This is also great for reusing legacy code. The fact that there are less framework-specific requirements on objects means that you have greater freedom to practise OO.Uh…. Now I have concerns. Enterprise systems often don’t *want* to practice OO, because doing so has an alarming tendency to get us into trouble–this is what got the CORBA guys and DCOM guys and RMI guys into problems in the first place, when they viewed the network as one big object party place. You start thinking that it makes sense to put the collection on the server and the iterator on the client, and next thing you know….
Ted, I mentioned “greater freedom to practise OO”, rather than implied that OO should always be used everywhere. Sure, there is no such thing as a distributed object. But it’s important not to confuse “enterprise” with “distributed”. Applications should be OO internally, as far as possible, with a facade on top to address remoting. Ideally only that facade level should give up on OO. (Ultimately solutions like SDO will probably become big in that space.) So IMO distribution is no argument for inviting object-killer APIs into application internals. Spring and other IoC containers don’t put barriers towards internal OO; EJB does, to a varying extent depending on which type of EJB you use.
To my comment on the complexity of EJB deployment descriptors–and note that Spring’s XML config is simpler–Ted writes:
Be fair, Rod–JSR 175 will address a significant (but not all!) percentage of what deployment descriptors (and your own config files) need. Were deployment descriptors a necessary evil in a pre-Java 5 environment? Unfortunately, yes, and arguably they were the best solution of the others possible. (Anybody remember the “object-based” descriptors of EJB 1.0! Yikes!)
Yes, JSR-175 will definitely improve things in the DD area. (Mostly improve, although annotations are also likely to be overused. But that’s another topic.) Yes, DDs were a necessary evil prior to Java borrowing the idea of attributes/annotations from C#. But the problem with today’s EJB deployment descriptors is that they are astoundingly verbose, as much as that they are in XML. Also, the standard ejb-jar.xml descriptor fails to convey a good deal of essential information, so you normally need 2 DDs. In contrast, Spring’s config files are significantly less verbose, and can be self-contained. Anyway, EJB 3.0 is not really relevant here, because I was discussing the reality of using an EJB approach right now (and until early 2006 or whenever JSR-220 completes).
On Don’s blog, I commented with respect to testing in Spring:
Because your code isn’t heavily dependent on the container, you can easily unit test it with something like JUnit. Huge productivity gain vs the cumbersome in-container testing strategies often seen in the past in J2EE. You can even run some integration tests using a Spring container but not a heavier J2EE app server–unlike any app server, a Spring container takes very little time to start up.That just speaks to the lack of an in-proc container, Rod, not necessarily a failure of EJB as a technology as a whole. The Exolab OpenEJB container doesn’t take a whole lot to fire up in-proc, either, at least from my (very nominal) tests.
I’m not convinced that “lightweight” EJB containers like OpenEJB are a satisfactory answer. I’ve never come across anyone using it, for a start, although I haven’t played with it myself for a while now. The reality of testing EJBs is messy, and usually involves Cactus and 5-minute code/test cycles.
Compare the Spring Pet Store sample with a traditional EJB approach. In the Spring approach there’s very little Java code that doesn’t do anything…no service locators, JNDI lookup etc etc. In my experience from client projects, using a combination like Spring/Hibernate it’s not unusual to end up with 10-20% of the code a traditional EJB-heavy J2EE app would have taken, with a significant gain in speed of delivery and maintainability.I’m going to take issue here–simpler doesn’t always mean better, unfortunately, it just means simpler. No JNDI lookup means no ability to have that necessary layer of indirection to allow admins the opportunity to reset configuration settings without having to bounce the server. While this may not seem like a big deal in an application that serves up a single department, when it goes into the NOC and has to run 24×7, that’s actually a big deal.
You end up with “no service locators, no JNDI lookup” in your code using Spring, regardless of whether you’re actually using JNDI under the covers. For example, if you want to access an EJB, Spring will generate a proxy for you and conceal the JNDI lookup.
In the case of the Pet Store, we went for a much simpler architecture–but then we’re talking about a Pet Store. The key thing is that Spring and other lighter-weight technologies give you the choice when you need a simpler solution. With traditional J2EE, if you wanted to build a Pet Store, you were better to use Perl or .NET. Or ignore “J2EE” the brand and stick with Servlets and JSP, rolling your own simple infrastructure where necessary.
“No JNDI lookup means no ability to have that necessary layer of indirection to allow admins the opportunity to reset configuration settings without having to bounce the server”: Mmmm, what useful JNDI reconfiguration can be done in a typical J2EE web app? A better approach is using JMX, but the app server doesn’t know enough about your app to do much meaningful configuration there, either. Spring 1.2 will add JMX support that will go down to the level of whatever application objects–and their config info–the developer wants to expose. For example, changing the value of a JNDI “environment variable” is something I’ve rarely seen in practise. Developers usually steer clear of environment variables because of the pain involved in looking them up. (I agree, it’s probably not good practice, but it’s the norm.) And if you want to change the values through JNDI, you’re on your own in deciding when to look them up again etc.
Remember, EJB was built for 2PC transactions, something that Spring was never initially intended to accomodate. The fact that it’s now including that makes me nervous that Spring is losing its focus.
Spring doesn’t do any more or less with 2PC than it ever did: not sure where the idea of scope creep and “loss of focus” comes from. Spring’s transaction abstraction is a layer over the top of a range of underlying transaction “strategies”. One of those is JTA, and in that case the 2PC capability comes from the app server’s underlying infrastructure, rather than Spring. In fact the JTA transaction strategy was the first that we envisaged and implemented. It was only after we’d done that that we realized that there was value in providing a consistent approach to non-JTA environments such as a simple web container, doing away with the old up-front choice between “local” and “global” transaction programming models.