Ted replying to Rod replying to Don replying to Ted

October 5th, 2004

On 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.

Method Injection

August 6th, 2004

A couple of months ago, in the days before I had a blog, there was a discussion by Cedric and Bob about “Getter Injection.”

The basic concept is that the IoC container can override abstract or concrete methods on managed objects on deployment. The container is injecting a method, such as a getter method, rather than a reference or primitive as in Setter Injection. As it happened, I was already working on a container method override mechanism for Spring 1.1, which has since been released in Spring 1.1 RC1. It’s an interesting concept, and definitely part of a complete IoC container. However, I believe that the concept is more general and needs a more general name. Also, that it should only be used in a fairly narrow range of scenarios.

Why would you want to do this? Cedric’s motivation was that setter methods are “useless” and that “having methods in a Java object that you will never invoke is a Design Smell.” In his view, the most important methods in the objects are really the getters, which usually return object references saved in the setters. Thus he proposes having the container implement the getter methods, and doing away with the setters. In practice this will mean that the container will actually override getter methods defined as part of application code, as otherwise it’s impossible to use them. Thus the container will end up implementing it using a similar mechanism to CMP 2.x (although hopefully any similarity will end there).

I don’t really buy the “useless method” argument, because setters will be invoked by an IoC container using Dependency Injection, and will be invoked in unit tests, without any container at all. They’ll be invoked by application code if the object is used outside a container. Furthermore, a getter/setter combination is a nice way of establishing defaults, in case you don’t choose to configure one or more setters to be invoked: the setter is there if you need it. While I can see Cedric’s motivation, there’s a tradeoff here: if we get rid of the supposedly useless setters we’re left with incomplete classes. If the getters are abstract, we go back to the CMP 2.x testing scenario of needing to test abstract objects. If the getters are concrete, we’re routinely writing methods that are going to be overridden at runtime. Now that really is useless code, in my view. (In general, I’m not a fan of overriding concrete methods, and avoid it where possible. I think I first read that suggestion in the UML Reference Manual and it makes a lot of sense.) There’s also an element of magic involved in “setter injection.” If I can have a simple POJO, with no fancy container subclassing, I prefer it. As Cedric himself put it very well in a panel discussion at TSSS last May, “use magic only when science fails.”

I think the concept should be renamed Method Injection, and that its value is far greater for some other–less common–scenarios.

I wouldn’t use it as an alternative to Setter or Constructor Injection in typical configuration of objects using Dependency Injection. Setter methods and constructors are plain Java constructs that work very well in a container, but aren’t reliant on a container. That’s good. Magic methods supplied by the IoC container create a bit more of a reliance on a container, although of course it’s still possible to subclass objects outside the container, and although they’re still just Java.

Essentially I see Method Injection as an alternative to subclassing in some corner cases, where the superclass should be kept isolated from a container dependency, and the container can more easily implement the necessary behaviour than a regular subclass. The method in question doesn’t need to be a getter method (as in Setter Injection getters), although typically it will be a method that returns something.

I see three main cases for methods implemented by the container:

  • They can move a container dependency out of application code.
  • They can rely on infrastructure not known until deployment.
  • They can customize the behaviour of legacy code for the runtime environment. However, plain old subclassing also makes sense here.

Container-subclassing is also a bit more dynamic than regular subclassing. We can potentially take the one base class and deploy it in different ways without ever needing to manage source code for more than one class. However, because its magic quotient is higher than that of regular subclassing, Strategy interfaces or various alternatives, I feel that Method Injection shouldn’t be used too eagerly.

The main appeal of Method Injection to me is as a way of getting rid of a container dependency I sometimes had to incur using Spring 1.0, and which will apply to any container that supports the concept of “non-singleton” or “prototype” objects. (That is, a container that gives you the option of getting a shared or new instance of an IoC-managed object on request, depending on configuration.) I love working with Spring, but I hate having to import Spring APIs for configuration.

The specific use case that caused me to implement this is when one “singleton” object configured via Spring needs to create instances of a non-singleton object–for example, a single-threaded, single-use processing object–yet wants that object to be configured using Dependency Injection, rather than just using new. For example, imagine that ThreadSafeService needs to create an instance of SingleShotHelper, which is itself configured via Dependency Injection. In Spring 1.0.x it’s necessary for ThreadSafeService to implement the BeanFactoryAware lifecycle interface, save the BeanFactory reference and call

    (SingleShotHelper) beanFactory.getBean("singleShotHelper")

each time it needs to create a helper. That works fine, it’s not too hard to test (BeanFactory is a simple interface, so it’s easy to mock), but it’s a Spring dependency, and it would be ideal to get that bit closer to a perfectly non-invasive framework. The type cast is also a little inelegant, although no big deal.

I usually ended up with one case of this situation in maybe 10 classes. I’d sometimes refactor this to extract a method, like this:

    protected SingleShotHelper createSingleShotHelper()  {
        return (SingleShotHelper) context.getBean("singleShotHelper");
    }

I could now subclass to implement this and keep the Spring dependency out of the superclass, but that seemed a bit excessive.

This kind of method is an ideal candidate for being implemented by the container, not the application developer. It’s returning an object the container knows about; the whole thing can actually be expressed more concisely in configuration than code (when you allow for the little bit of code needed to save the BeanFactory reference).

With the new Method Injection functionality introduced in Spring 1.1, it’s possible to use an abstract
(or concrete) method such as:

   protected abstract SingleShotHelper createSingleShotHelper();

and tell the container to override that method on deployment to return a specific bean from the same or a parent factory, like this:

<lookup-method name="createSingleShotHelper" bean="singleShotHelper" />

The methods can be protected or public. Any number of methods can be overridden. <lookup-method> elements can be used within bean definition elements just like property or constructor-arg elements.

I see the most compelling case for Method Injection being to return the result of looking up a named object managed by the container. (Of course this is not Spring-specific: any container could implement this.) The lookup will typically be of a non-singleton bean (in Spring parlance).

This way there are no dependencies in application code on Spring or any other IoC container. A corner case closed off without needing to import a Spring API. As I said, this feature was directly motivated by requirements in a client project I’m working on, and has proven useful in practice.

Lookup methods can be combined with either Setter Injection or Constructor Injection. They don’t take arguments, hence method overloading isn’t an issue.

The implementation uses CGLIB to subclass the class. (It’s only available if CGLIB is on the class path, to avoid making the Spring core container dependent on CGLIB.)

Spring goes a step further, allowing you to define arbitrary behaviour for the overridden method–not just a bean lookup. You might want to do this, for example, to use a generic behaviour based on the runtime infrastructure–such as transaction rollback using the Spring TransactionInterceptor class. (Of course, rollback rules should normally be used to avoid this.) Or there may be compelling cases for generic override behaviours–such as “return transactional datasource DS1 if there’s an active transaction, otherwise return nontransactional datasource DS2″. Again, if we can conceal this kind of logic from application code, it’s a win. Here we’re beyond the scope of pure “getters”: we could override methods to publish an event, for example.

There are often alternatives to arbitrary container overrides, such as subclassing the class and overriding the method in the normal way (science, rather than magic), or using AOP. In the case of a bean lookup as in the example, there is a clear benefit in the container doing the override, as it eliminates dependency on a Spring API. It’s also much simpler to describe in XML. With the more general case, it’s necessary to have a way of resolving overloaded methods.

This is already longer than I planned–and has taken a while!–so I’ll leave discussing Spring 1.1’s arbitrary override mechanism (including how it resolves overloaded methods) to a future post, if anyone is interested. I’m gaining a new admiration for all those indefatigable bloggers out there like Dion and Matt Raible, who seem to blog about 3 times a day.