A book challenging a platform and developing an open source project to prove its point is unprecedented. That’s how
Spring is born, from the ideas of (its manifesto) book "J2EE with out ejb". Spring’s alternative to ejb is an aspect oriented and POJO based inversion of control or
dependency injection (IOC/DI) container, which integrates with other enterprise ingredients--orm tools, transaction services, custom protocols etc--and also provides client interfaces to Spring. While the ingredients, at least orm tools, are not new, integrating them together to build a toolset is different. IOC, DI, POJOs and
hype make me take a closer look at Spring.
Dependency injection, that too for POJOs (i.e. without no explicit interfaces) is good--less burden on lazy developers, we don’t need to worry about building objects or learning new APIs. However, objects can have many possible lifecycles, can Spring
really inject dependencies in all cases?
Spring documents limitations in some cases:
- on lifecycle mismatch it says "There is however a problem when the bean lifecycles are different. Consider a singleton bean A which needs to use a non-singleton (prototype) bean B, perhaps on each method invocation on A." and suggests to forgo POJO ness get it,
- warns on prototype lifecycle by saying "Spring cannot manage the complete lifecycle of a non-singleton/prototype bean".
- There are many other limitations too: sharing a prototype (state-full) object across multiple objects, composing object graph of non-singletons with circular references among others, temporal objects (objects with time to live) etc are not possible in Spring. Spring barely supports non-singleton objects, and justifies can’t support or missing features as "they are not common", "not needed", or "heavy weight".
Non-singletons, state full objects, objects with circular dependencies are not uncommon.
Containers have a smell in them, their lookup services are very plain, e.g. Spring bean-factory looks up objects based on their id. We are used to factories or registries that have meaning full lookups and classifiers, our lookups have methods like get a pricer for a product type and region, or get a data access object for currencies etc. and a lot more magic is possible in our localized factories/lookup utilities.
Whatever elegance gained in dependency injection is lost by lack of rich object composition and vanilla object classifications of spring. Managing singletons is not a big deal, perhaps, dependency injection is just a good
idea only.
So can, Spring, "torchbearer of anti ejb", replace ejb? Yes and no.
Transactional ejbesque services follow a pattern of business service depending on an orm tool and together participating in transactions. In these scenarios rarely state-full services are needed, at the maximum business façade may be a state-full service, they don’t have lifecycle mismatch problems. Spring integrates well with almost all persistence solutions, and its declarative transactions work inside and outside a container.
Declarative transactions are part of the ejb story only; remoting or distribution support is another important feature in ejb. Spring's remoting/distribution is through custom protocols (non rmi-iiop) --hessian, burlap,httpinvoker, these protocols have serialization and user/transaction context propagation limitations.
Even with problems in dependency injection and incomplete remoting, spring framework accomplishes what very few contemporary frameworks are able to do--declarative transactions inside or outside container and of course lot of hype.